可合成VHDL递归,Vivado:模拟器以意外方式终止
我想用最少的更新和访问时间来实现 基本上,一个输入样本由多个可合成VHDL递归,Vivado:模拟器以意外方式终止,vhdl,simulation,vivado,synthesis,Vhdl,Simulation,Vivado,Synthesis,我想用最少的更新和访问时间来实现 基本上,一个输入样本由多个(d)散列函数进行散列,每个散列函数在其命中的桶中增加一个计数器。查询样本时,将比较与样本对应的所有存储桶的计数器,并返回最小计数器的值作为结果 我试图用以下代码在log_2(d)time中找到计数器的最小值: entity main is Port ( rst : in STD_LOGIC; a_val : out STD_LOGIC_VECTOR(63 downto 0); b_val
(d)
散列函数进行散列,每个散列函数在其命中的桶中增加一个计数器。查询样本时,将比较与样本对应的所有存储桶的计数器,并返回最小计数器的值作为结果
我试图用以下代码在log_2(d)
time中找到计数器的最小值:
entity main is
Port ( rst : in STD_LOGIC;
a_val : out STD_LOGIC_VECTOR(63 downto 0);
b_val : out STD_LOGIC_VECTOR(63 downto 0);
output : out STD_LOGIC_VECTOR(63 downto 0);
. .
. .
. .
CM_read_ready : out STD_LOGIC;
clk : in STD_LOGIC);
end main;
architecture Behavioral of main is
impure function min( LB, UB: in integer; sample: in STD_LOGIC_VECTOR(long_length downto 0)) return STD_LOGIC_VECTOR is
variable left : STD_LOGIC_VECTOR(long_length downto 0) := (others=>'0');
variable right : STD_LOGIC_VECTOR(long_length downto 0) := (others=>'0');
begin
if (LB < UB)
then
left := min(LB, ((LB + UB) / 2) - 1, sample);
right := min(((LB + UB) / 2) - 1, UB, sample);
if (to_integer(unsigned(left)) < to_integer(unsigned(right)))
then
return left;
else
return right;
end if;
elsif (LB = UB)
then
-- return the counter's value so that it can be compared further up in the stack.
return CM(LB, (to_integer(unsigned(hasha(LB)))*to_integer(unsigned(sample))
+ to_integer(unsigned(hashb(LB)))) mod width);
end if;
end min;
begin
CM_hashes_read_log_time: process (clk, rst)
begin
if (to_integer(unsigned(instruction)) = 2)
then
output <= min(0, depth - 1, sample);
end if;
end if;
end process;
end Behavioral;
删除以下行可解决上述错误:
output <= min(0, depth - 1, sample);
output并不是说我能找到递归在现实世界中的任何用途,而是为了让@EML感到惊讶(正如上面评论中所要求的):您实际上可以用VHDL定义递归硬件结构
至少在Quartus中,只有当您给编译器一个最大递归深度的明确指示时,这才有效,否则它将尝试将递归展开到任何可能的输入,最终死于堆栈溢出:
entity recursive is
generic
(
MAX_RECURSION_DEPTH : natural
);
port
(
clk : in std_ulogic;
n : in natural;
o : out natural
);
end recursive;
architecture Behavioral of recursive is
function fib(max_depth : natural; n : natural) return natural is
variable res : natural;
begin
if max_depth <= 1 then
res := 0;
return res;
end if;
if n = 0 then
res := 0;
elsif n = 1 or n = 2 then
res := 1;
else
res := fib(max_depth - 1, n - 1) + fib(max_depth - 1, n - 2);
end if;
return res;
end function fib;
begin
p_calc : process
begin
wait until rising_edge(clk);
o <= fib(MAX_RECURSION_DEPTH, n);
end process;
end Behavioral;
实体是递归的
通用的
(
最大递归深度:自然
);
港口
(
时钟:标准逻辑;
n:自然的;
o:自然的
);
结束递归;
递归is的行为体系结构
函数fib(最大深度:自然;n:自然)返回自然
可变分辨率:自然;
开始
如果max_犯了很多错误<代码>样本
和深度
在代码中不作为信号/变量存在,因此无法传递给最小函数。进程在灵敏度列表中有时钟和重置,但未在进程中使用(因此这不是一个同步进程),long\u length
不存在hasha
和hashb
不存在。请提供MCVERecursion通常不建议用于合成,因为它可能不清楚电路的意图。特别是当递归是一个不可能进行流水线处理的函数时。问题可能是“问题”:您的函数min
并不总是返回值——没有else
子句来处理LB>UB
情况。这几乎肯定是代码无法编译的原因。问题也是“a”问题:您的函数min
不应不纯净。请参阅此参考资料,其中描述了VHDL中纯函数和非纯函数之间的差异:……但正如@Tricky所指出的,一旦您修复了min
函数,您仍然会遇到问题。我希望您的代码会在那时编译,但由于代码中的其他问题,它仍然不能像您预期的那样工作(您的CM_hashes\u read\u log\u time
进程将不会有您想要的计时行为);到处都是虫子。发布至少可编译的内容,然后在精化或运行时失败。换句话说,至少xvhdl必须完整无误。除了使用有界深度的递归函数调用外,还可以使用泛型常量将“深度”绑定。@user1155120 cudos对于链接的答案,这是一个聪明的答案。不幸的是,Quartus II不够聪明,无法编译它(因为它不允许泛型引用同一接口列表中的其他泛型)。如回答中所述,只有-2008年才提供两个功能,Quartus II不兼容。注意,OP的问题提到了Vivado。是的,很惊讶……:)
entity recursive is
generic
(
MAX_RECURSION_DEPTH : natural
);
port
(
clk : in std_ulogic;
n : in natural;
o : out natural
);
end recursive;
architecture Behavioral of recursive is
function fib(max_depth : natural; n : natural) return natural is
variable res : natural;
begin
if max_depth <= 1 then
res := 0;
return res;
end if;
if n = 0 then
res := 0;
elsif n = 1 or n = 2 then
res := 1;
else
res := fib(max_depth - 1, n - 1) + fib(max_depth - 1, n - 2);
end if;
return res;
end function fib;
begin
p_calc : process
begin
wait until rising_edge(clk);
o <= fib(MAX_RECURSION_DEPTH, n);
end process;
end Behavioral;