VHDL 中 SIGNALS 的阻塞分配
Blocking Assignments on SIGNALS in VHDL
我正在用 VHDL 制作 FSM。当 valid = 1 从 stateA 变为 stateB 时,最简单的可能。
令人困惑的部分是蓝色矩形选择的上升沿。当有效 = '1' 时。在第一个上升沿,状态将被计算为 B,但直到下一个上升沿才会生效,但在第一个上升沿生效的情况发生了什么。
因为从A到B的状态变化应该会影响到NEXT循环中设计中的其他部分(并行过程)。从波形来看,If valid = '1' 就在 CLK_1.
之前
At, CLK_1 all other processes should see state = A | waveform correct
output
- 状态=A
- 进入最后一个周期 = 0
At, CLK_2 all processes start seeing state = B. another parallel
process checks if state = B then it drives ENTERED_STATEB_LASTCYCLE to
be 1 waveform correct output
- 状态=B
- 进入最后一个周期 = 0
Then at CLK_3, waveform correct output
- 状态=B
- 进入最后一个周期 = 1
我是不是理解错了什么?
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.KDlib.all;
entity nearestPoint is
generic ( ARRAY_WIDTH : integer := 8);
port (
clk: in std_logic;
reset: in std_logic;
inpoint: in kdvector;
valid: in std_logic;
finished: buffer std_logic
);
end nearestPoint;
architecture behave of nearestPoint is
signal state: two_state_type;
signal stateB_entered_lastCycle: std_logic;
begin
process ( clk )
begin
if ( reset = '1' ) then
elsif ( rising_edge(clk) ) then
case state is
when stateA =>
if ( valid = '1' ) then
state <= stateB;
end if;
when stateB =>
when others =>
end case;
end if;
end process;
process(clk)
begin
if ( reset = '1' ) then
elsif ( clk = '1' ) then
case state is
when stateA =>
when stateB =>
stateB_entered_lastCycle <= '1';
when others =>
end case;
end if;
end process;
end behave;
VHDL 没有 blocking/non-blocking 赋值的概念。有信号和变量,它们的赋值不同。
对于您的情况,您需要记住模拟是在一系列增量循环上运行的。 1 delta 是无限小的 space 时间,但它们是按顺序发生的。信号分配直到delta结束才生效,因此在时钟上升沿之后的delta周期中state = B
。第二个进程只对时钟敏感,所以它不能更新stateB_entered_lastcycle
直到时钟再次上升。
我通过数字电路棱镜给大家讲解一下。这是开发VHDL时必须牢记的一种思维方式。
你的有效在时钟边沿之前为1。你在模拟中,所以你可以想象你所有的计算都是即时的。在你的触发器的输入端,你的状态的新值已经计算出来了。
我习惯于只使用一个顺序过程和一个或多个组合过程进行编码。也许你会更好地理解这段代码与你的代码具有相同的功能(有点简化):
SEQ : process(clk, rst)
begin
if rst = '1' then
current_state <= '0';
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process SEQ;
此代码对应的电路:
COMB : process(current_state, valid)
begin
next_state <= current_state; -- Default value to ensure that next_state will always be affected
if current_state = '0' and valid = '1' then
next_state <= '1';
end if;
end process COMB;
此代码对应的电路:
如果考虑到valid变化时next_state是瞬间刷新的,current_state(代码中的 state)在下一个时钟上升沿变高。
希望您能理解,如果您需要更精确的信息,请不要犹豫,我可以编辑我的 post 或在评论中回答。
重要说明:如果您在顺序过程中有异步重置,它必须在敏感列表中。
令人困惑的部分是蓝色矩形选择的上升沿。当有效 = '1' 时。在第一个上升沿,状态将被计算为 B,但直到下一个上升沿才会生效,但在第一个上升沿生效的情况发生了什么。
因为从A到B的状态变化应该会影响到NEXT循环中设计中的其他部分(并行过程)。从波形来看,If valid = '1' 就在 CLK_1.
之前At, CLK_1 all other processes should see state = A | waveform correct output
- 状态=A
- 进入最后一个周期 = 0
At, CLK_2 all processes start seeing state = B. another parallel process checks if state = B then it drives ENTERED_STATEB_LASTCYCLE to be 1 waveform correct output
- 状态=B
- 进入最后一个周期 = 0
Then at CLK_3, waveform correct output
- 状态=B
- 进入最后一个周期 = 1
我是不是理解错了什么?
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.KDlib.all;
entity nearestPoint is
generic ( ARRAY_WIDTH : integer := 8);
port (
clk: in std_logic;
reset: in std_logic;
inpoint: in kdvector;
valid: in std_logic;
finished: buffer std_logic
);
end nearestPoint;
architecture behave of nearestPoint is
signal state: two_state_type;
signal stateB_entered_lastCycle: std_logic;
begin
process ( clk )
begin
if ( reset = '1' ) then
elsif ( rising_edge(clk) ) then
case state is
when stateA =>
if ( valid = '1' ) then
state <= stateB;
end if;
when stateB =>
when others =>
end case;
end if;
end process;
process(clk)
begin
if ( reset = '1' ) then
elsif ( clk = '1' ) then
case state is
when stateA =>
when stateB =>
stateB_entered_lastCycle <= '1';
when others =>
end case;
end if;
end process;
end behave;
VHDL 没有 blocking/non-blocking 赋值的概念。有信号和变量,它们的赋值不同。
对于您的情况,您需要记住模拟是在一系列增量循环上运行的。 1 delta 是无限小的 space 时间,但它们是按顺序发生的。信号分配直到delta结束才生效,因此在时钟上升沿之后的delta周期中state = B
。第二个进程只对时钟敏感,所以它不能更新stateB_entered_lastcycle
直到时钟再次上升。
我通过数字电路棱镜给大家讲解一下。这是开发VHDL时必须牢记的一种思维方式。
你的有效在时钟边沿之前为1。你在模拟中,所以你可以想象你所有的计算都是即时的。在你的触发器的输入端,你的状态的新值已经计算出来了。
我习惯于只使用一个顺序过程和一个或多个组合过程进行编码。也许你会更好地理解这段代码与你的代码具有相同的功能(有点简化):
SEQ : process(clk, rst)
begin
if rst = '1' then
current_state <= '0';
elsif rising_edge(clk) then
current_state <= next_state;
end if;
end process SEQ;
此代码对应的电路:
COMB : process(current_state, valid)
begin
next_state <= current_state; -- Default value to ensure that next_state will always be affected
if current_state = '0' and valid = '1' then
next_state <= '1';
end if;
end process COMB;
此代码对应的电路:
如果考虑到valid变化时next_state是瞬间刷新的,current_state(代码中的 state)在下一个时钟上升沿变高。
希望您能理解,如果您需要更精确的信息,请不要犹豫,我可以编辑我的 post 或在评论中回答。
重要说明:如果您在顺序过程中有异步重置,它必须在敏感列表中。