【问题标题】:Implementing a VHDL binary search on a std_logic_vector [vhdl]在 std_logic_vector [vhdl] 上实现 VHDL 二进制搜索
【发布时间】:2018-04-13 04:09:25
【问题描述】:

我正在尝试为 ASIC(它必须是 ASIC 的一部分)创建可合成的 VHDL(函数或过程),它将在 standard_logic_vector 中查找第一个“1”并输出“1”所在的向量位置例如,我有一个“10001000”的 8 位 slv(位置 3 和 7 中的“1”)。如果我使用这个 slv,输出应该是 4(输出是基于 1)。

实际的 VHDL 将搜索一个大的 slv,最长可达 512 位。我尝试实现二进制搜索功能,但我得到综合错误,指出 “无法合成非常数范围值。[CDFG-231] [详细] 非常量范围值在第 61 行的文件'...'中“我在下面的代码中指出了它抱怨的地方。我不确定如何在没有非常量范围的情况下实现二进制搜索算法值。我将如何修改此代码以使其可合成?

我已尝试搜索 HDL 的二进制搜索算法,以寻找潜在的代码来查看我的错误,但我没有找到任何东西。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

entity bin_search is
    generic (
        constant NREGS  : positive  := 16               -- number of registers
    );
    port (
        clk_i   : in    std_logic;                      -- clock
        bin_i   : in    unsigned( NREGS-1 downto 0 );   -- input
        en_i    : in    std_logic;                      -- input enable
        addr_o  : out   natural range 0 to NREGS        -- first binary location
    );
end bin_search;

architecture rtl of bin_search   is

  function f_bin_search( input: unsigned; nob: positive ) return natural is
        constant nbits  : positive                      := 2**nob;
        variable lower  : natural   range 0 to 1        := 0;
        variable upper  : natural   range 0 to 1        := 0;
        variable idx    : natural   range 0 to nob      := 4;
        variable cnt    : natural   range 0 to nbits    := 0;
        variable mid    : positive  range 1 to nbits    := nbits/2; --
        variable ll     : natural   range 0 to nbits    := 0;
        variable ul     : positive  range 1 to nbits    := nbits;   -- 
    begin
        if input = 0 then
            cnt := 0;
            return cnt;
        else
            loop1: while ( idx > 0 ) loop
                if ( input( mid-1 downto ll ) > 0 ) then --  <===WHERE SYNTH COMPLAINS
                    lower   := 1;
                else
                    lower   := 0;
                end if;
                if ( input( ul-1 downto mid ) > 0 ) then
                    upper   := 1;
                else
                    upper   := 0;
                end if;
                if ( idx = 1 ) then
                    if ( lower = 1 ) then
                        cnt := mid;
                    else
                        cnt := ul;
                    end if;
                elsif ( lower = 1 ) then
                    ul  := mid;
                    mid := ( ( ll+ul )/2 );
                elsif ( upper = 1 ) then
                    ll  := mid;
                    mid := ( ll+ul )/2;
                else
                    cnt := 0;
                    exit loop1;
                end if;
                idx := idx-1;
            end loop loop1;
            return cnt;
        end if;
    end f_bin_search;

begin

    test_proc: process ( clk_i )
    begin
        if rising_edge( clk_i ) then
            if en_i = '1' then
                addr_o  <= f_bin_search( bin_i, 4 );
            end if;
        end if;
    end process test_proc;
end rtl;

这是一个简单的测试台,其中输入加“1”。 addr_o 应该是带有 '1' 的输入 lsb 的位置(基于 1)。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;

entity bin_search_tb is
end bin_search_tb;

architecture behavior of bin_search_tb is

    constant    NREGS   : positive  := 16;

    signal      clk     : std_logic;
    signal      input   : unsigned( NREGS-1 downto 0 );
    signal      start   : std_logic;
    signal      addr    : natural range 0 to NREGS;

    constant    clk_per : time  := 1 ns;
    signal      row     : natural range 0 to 2**NREGS-1;

begin

    bin_search_inst: entity work.bin_search( rtl )
    generic map (
        NREGS   => NREGS
    )
    port map (
        clk_i   => clk,     -- master clock
        bin_i   => input,   -- captured events
        en_i    => start,   -- start binary search
        addr_o  => addr     -- addr where the first '1' appears
    );

    -- master clock process
    clk_proc: process
    begin
        clk <= '0';
        wait for clk_per / 2;
        clk <= '1';
        wait for clk_per / 2;
    end process clk_proc;

    -- 
    stim1_proc: process
    begin
        input   <= ( others => '0' );
        start   <= '0';
        row     <= 1;   
        wait until clk'event and clk = '1';
        loop
            wait until clk'event and clk = '1';
            input   <= to_unsigned( row, input'length );
            start   <= '1';
            wait until clk'event and clk = '1';
            start   <= '0';
            wait for 4*clk_per;
            row <= row+1;
        end loop;   
    end process stim1_proc;

end architecture behavior;

感谢您的帮助! -杰森

编辑代码并添加了一个测试台

【问题讨论】:

  • 显示实际完整的错误信息。还提供Minimal, Complete and Verifiable example - 您的代码 sn-p 缺少子程序名称,并且您不能将十进制文字作为初始值分配给 std_logic 类型的对象。您的综合工具文档应与综合资格指南以及针对特定错误消息的纠正措施相关。问题多于您指出的错误。
  • 我的错。我必须输入这个,因为我的工作计算机没有互联网接入(没有复制/粘贴)。我更正了代码(我想我都找到了)。它在行为上模拟 find,但是当我使用 Cadence 的 Genus v16 进行合成时,我得到“错误:无法合成非常量范围值。[CDFG-231] [详细说明] 非常量范围值在文件中 .... 在线...(它指向 or_reduce 行。
  • 不幸的是,我可以在 Cadence 的文档中找到与该错误相关的所有内容,只是我不能在没有任何方向的情况下使用非常量范围。如果您曾经使用过 Cadence 软件,您就会知道它不是最好的 :(。因此,由于某种原因,该工具无法推出看起来的范围。我希望有一种更好的方法来进行二进制搜索而不是拥有输入所有可能的范围。
  • 感谢 cmets。我会给你的建议一些想法。我也在考虑只使用桶右移位器,因为我认为我可以使用固定索引。
  • 如果您要检查 IEEE Std 1076.6-2004(撤回,RTL 综合)8.8.9 循环语句,您会发现不支持带有 while 迭代方案的 while 循环和 8.6.5 切片名称- 对于作为切片名称一部分出现的离散范围,离散范围的边界应直接或间接指定为属于整数类型的静态值。 具有边界范围的想法匹配整数边界的范围需要具有每个可能的宽度和边界集的多路复用器(选择器)来表示一个很容易不切实际的切片。

标签: vhdl binary-search asic


【解决方案1】:

您的设计肯定会取决于延迟和其他性能要求,但是,您可以使用或减少、定序器(用于切片向量的多路复用选择)、移位寄存器和计数器的某种组合。我画了一个简单的电路,它应该在大约 30 个时钟周期内找到你的 lsb 实例“1”

实现这种设计的 RTL 翻译应该是直截了当的。

【讨论】:

    【解决方案2】:

    你说你在考虑硬件,但实际上你不是。或者你是在误导自己。

    input( mid-1 downto ll ) > 0
    

    不是 OR-reduction,而是比较操作。您必须知道&gt;larger than 比较运算符。综合将因此推断出一个比较器。但我问,比较器必须有多少输入?好吧,这就是你的问题:它取决于mid 的值,其中:

    • 最初取决于nbits 的值,这取决于nob 的值,nob 是函数的变量输入。
    • 在循环内更改。因此它的值不是恒定的。

    硬件组件不能有可变数量的电线。

    但是你为什么要二分查找呢?为什么不保持简单?

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity detect_one is
        generic(
            input_size : positive := 512);
        port(
            input : in std_logic_vector (input_size-1 downto 0);
            output : out natural range 0 to input_size);
    end entity;
    
    architecture rtl of detect_one is
    begin
        main: process(input)
        begin
            output <= 0;
            for i in input_size-1 downto 0 loop
                if input(i)='1' then
                    output <= i+1;
                end if;
            end loop;
        end process;
    end architecture;
    
    
    entity detect_one_tb is end entity;
    library ieee;
    architecture behavior of detect_one_tb is
        constant input_size : positive := 512;
        use ieee.std_logic_1164.all;
        signal input : std_logic_vector (input_size-1 downto 0) := (others => '0');
        signal output : integer;
    begin
        DUT : entity work.detect_one
            generic map ( input_size => input_size )
            port map(
                input => input,
                output => output);
    
        test: process begin
            wait for 1 ns;
            assert (output = 0) report "initial test failure" severity warning;
            for i in 0 to input_size-1 loop
                input <= (others => '0');
                input(i) <= '1';
                wait for 1 ns;
                assert (output = i+1) report "single ones test failure" severity warning;
            end loop;
            input <= (others => '1');
            wait for 1 ns;
            assert (output = 1) report "initial multiple ones test failure" severity warning;
            for i in 0 to input_size-2 loop
                input(i) <= '0';
                wait for 1 ns;
                assert (output = i+2) report "multiple ones test failure" severity warning;
            end loop;
            wait;
        end process;
    end architecture;
    

    【讨论】:

      猜你喜欢
      • 2015-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多