如何判断所有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 的不同输入值的数量以提供易于解释的波形。)
我正在为一个 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 的不同输入值的数量以提供易于解释的波形。)