如何判断所有for循环是否结束,VHDL,Quartus-II

How to determine if all for loops have ended, VHDL, Quartus-II

我正在为一个 VHDL 难题而苦苦挣扎。这里有一些代码可以解释我正在尝试做什么:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.all;

entity forLoopTest is
-- Number of bits known only at compilation
generic(
    bits : integer  range 1 to 1024;                := 256;
);
port(
    clk:    in  std_logic                           := '0';
    -- Single bit inputs from foo
    foo:    in  std_logic_vector(bits-1 downto 0)   := (others => '0');
    -- Output should be high when all inputs have gone to '1' at some point
    bar:    out std_logic
);
end forLoopTest;

------------------------------------------------------------------------------------------------------------

architecture implementation of forLoopTest is
    -- Create states for finite state machine, where finish implies a '1' has been received
    type FSM_states_single is (waitForHigh, finish);
    -- Make an array of the states, one for each input bit
    type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single;
    -- Create signal of states initialised to the waiting condition
    signal state : FSM_states_multi                 := (others => waitForHigh);

begin

    process(clk, foo)
        -- For each input bit:
        for bitNumber in 0 to bits-1 loop
            case state(bitNumber) is
                -- Whilst waiting, poll the input bit
                when waitForHigh =>
                    -- If it goes high, then switch states
                    if (foo(bitNumber) = '1') then
                        state(bitNumber) <= finish;
                    end if;
                -- If input bit has gone high:
                when finish =>
                    -- What is simplest method of setting "bar"?
                        -- "bar" should be high if and only if all bits have equalled '1' at some point
                        -- Otherwise it should be '0'
                        -- Though of dominant setting '0', and submissive setting 'H', but multiple things setting output fails
                            -- Either explicitly, or only one of them is used, others ignored
            end case;
        end loop;

    end process;        

end implementation;

基本上,我试图找到一种最佳方法来推断 for 循环的所有 "threads" 何时完成。以上是一个假设的例子来说明这一点。使用上述代码的一种方法是简单地 "AND" 所有状态。但是,我不确定如何和未知数量的变量(预编译)。我也很想知道解决这个问题的其他方法是什么。

提前致谢!

(给定的进程有很多问题:它可能应该被计时,以便它在每个 rising_edge(clk) 上运行,然后在敏感列表中不需要 foo .不过....)

一种方法是布尔变量 finished 在进入 for 循环之前设置为 TRUE

任何未完成的迭代(例如进入 waitforHigh 状态或 finish 以外的任何状态)将清除 finished 变量...(可选,除非它是过渡到 finish 状态)。

然后,在 end loop 之后,下一个语句 if finished then ... 将告诉您您想知道的内容。

为您的进程添加了时钟和重置。重置允许您清除状态。

没有条形触发器,很容易做到,搬个if语句。

由于 bar 的派生方式,删除了 case 语句,没有必要评估两种状态:

library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_arith.all;  -- not used
use work.all;

entity forlooptest is
    generic (
        bits : integer  range 1 to 1024 := 256 -- removed ';' 2 places
    );
    port (
        clk:    in  std_logic;
        reset:  in  std_logic;  -- added
        foo:    in  std_logic_vector(bits-1 downto 0) := (others => '0');
        bar:    out std_logic
    );
end entity forlooptest;

architecture foo of forlooptest is

    type FSM_states_single is (waitForHigh, finish);
    type FSM_states_multi is array (bits-1 downto 0) of FSM_states_single;
    signal state : FSM_states_multi := (others => waitForHigh);

begin

FOO_BAR:
    process (clk, reset)
        variable state_v:   FSM_states_multi;  -- added
    begin -- original missing begin

        state_v := state;  -- variable can be evaluated after assignment
        if reset = '1' then
            state_v := (others => WaitForHigh);
        elsif rising_edge(clk) then 
            for bitNumber in 0 to bits-1 loop 
                if state_v(bitNumber) = waitForHigh and 
                                foo(BitNumber) = '1'     then
                    state_v(bitNumber) := finish;
                end if;
            end loop;  
            state <= state_v;  
        end if;
        if state_v = (state_v'range => finish)  then 
            bar <= '1';  -- bar not a FlipFlop move if statement above
        else             -- preceding end if and add to reset condition for FF
            bar <= '0';  -- no latch
        end if;
    end process;    

end architecture;

可以通过将 bar 的 if 语句移动到前面的 end if 之上,删除 else 并赋值给 '0',并将 bar <= '0' 添加到 reset 来使 bar 成为触发器。

还有状态的可变副本,因此任何更新的位都可以立即用于评估。 (信号赋值不会立即生效,而变量赋值会立即生效)。

注意问题的核心,如何使用每个位置都设置为完成的聚合值来评估状态 (state_v)。您不能在此处使用 others。作为相等运算符的输入,元素的数量及其类型必须能够从聚合表达式中辨别出来。

添加一个位范围有限的小型测试平台:

library ieee;
use ieee.std_logic_1164.all;

entity for_loop_test_tb is
end entity;

architecture fum of for_loop_test_tb is
    constant bits:  integer range 1 to 1024 := 16; 
    signal clk:    std_logic := '0';
    signal reset:  std_logic;  -- added
    signal foo:    std_logic_vector(bits-1 downto 0) := (others => '0');
    signal bar:    std_logic;
begin
DUT:
    entity work.forlooptest
        generic map (bits => bits)
        port map (
            clk => clk,
            reset => reset,
            foo => foo,
            bar => bar
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if now > 150 ns then
            wait;
        end if;
    end process;

STIMULI:
    process
    begin
        wait for 10 ns;
        reset <= '1';
        wait for 10 ns;
        reset <= '0';
        wait for 10 ns;
        foo <= x"0FF0";
        wait for 10 ns;
        foo <= x"0001";
        wait for 10 ns;
        foo <= x"F002";
        wait for 10 ns;
        foo <= x"0F00";
        wait for 10 ns;
        foo <= x"FF00";
        wait for 10 ns;
        foo <= x"0001";
        wait for 10 ns;
        foo <= x"00F0";
        wait for 10 ns;
        foo <= x"F0F0";
        wait for 10 ns;
        foo <= x"0004";
        wait for 10 ns;
        foo <= x"CCCC";
        wait;
    end process;

end architecture;

这给出了:

(限制了位的值和 foo 的不同输入值的数量以提供易于解释的波形。)