可合成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;