1

standard_logic_vector の最初の '1' を検索し、'1' がどのベクトル位置にあったかを出力する ASIC (ASIC の一部である必要があります) 用の合成可能な VHDL (関数またはプロシージャ) を作成しようとしています。たとえば、「10001000」の 8 ビット slv があります (位置 3 と 7 の「1」)。この slv を使用すると、出力は 4 になります (出力は 1 ベースです)。

実際の VHDL は、長さが最大 ​​512 ビットの大きな slv を検索します。二分探索関数を実装しようとしましたが、「定数でない範囲の値を合成できませんでした。[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;

ご協力ありがとうございます。-ジェイソン

コードを編集し、テストベンチを追加しました

4

2 に答える 2