【发布时间】: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