我试图为我的项目的一个控制单元的FSM编写VHDL代码。我选择了两个进程方式,一个进程用于状态寄存器,另一个进程用于下一个状态和输出逻辑。无论如何,我在设置解决方案时遇到了一些问题,因为一些信号发出了合成锁存警告(我知道它们出现的原因)。我找到的唯一解决方案(没有对状态寄存器和输出逻辑使用一个单独的进程,也没有再添加3个状态)是在管理状态逻辑的进程中添加一些输出逻辑。
令人惊讶的是,它有效,但这在概念上是正确的吗?我的意思是,用某种输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式?
这是我的工作代码和“无锁存警告”控制单元。总之,锁存涉及信号sel_mode,因为我不知道如何在状态空闲的其他分支中指定类似于“保留”“sel_mode”的前一个值(没有锁存警告)。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity control_unit is
Port ( clock : in STD_LOGIC;
reset_n_in : in STD_LOGIC;
primo_operando : in STD_LOGIC;
secondo_operando : in STD_LOGIC;
add_sub : in STD_LOGIC;
ov : in STD_LOGIC;
subtract_in : in STD_LOGIC;
led_ov : out STD_LOGIC;
reset_n_out : out STD_LOGIC;
subtract_out : out STD_LOGIC;
en_w_primo_op : out STD_LOGIC;
en_w_secondo_op : out STD_LOGIC;
en_w_risultato : out STD_LOGIC;
sel_mode : out STD_LOGIC_VECTOR(1 downto 0)
);
end control_unit;
architecture Behavioral of control_unit is
type state is (IDLE, PRIMO_OP, SECONDO_OP, RISULTATO);
signal curr, nxt : state := IDLE;
begin
change_state : process(clock, reset_n_in)
begin
if reset_n_in = '0' then
curr <= IDLE;
-- in the following lines I mix the state register logic with output logic
elsif rising_edge(clock) then
if curr = PRIMO_OP then
sel_mode <= "10";
elsif curr = SECONDO_OP then
sel_mode <= "01";
elsif curr = RISULTATO then
sel_mode <= "00";
end if;
curr <= nxt;
end if;
end process;
fsm: process(curr, reset_n_in, primo_operando, secondo_operando, add_sub)
begin
if reset_n_in = '0' then
reset_n_out <= '0';
else
reset_n_out <= '1';
end if;
en_w_primo_op <= '0';
en_w_secondo_op <= '0';
en_w_risultato <= '0';
case curr is
when IDLE =>
if primo_operando = '1' then
-- sel_mode <= "10";
nxt <= PRIMO_OP;
elsif secondo_operando = '1' then
-- sel_mode <= "01";
nxt <= SECONDO_OP;
elsif add_sub = '1' then
-- sel_mode <= "00";
nxt <= RISULTATO;
else
nxt <= IDLE;
-- how to specify keep sel_mode to the previous value??
end if;
when PRIMO_OP =>
-- sel_mode <= "10";
en_w_primo_op <= '1';
nxt <= IDLE;
when SECONDO_OP =>
-- sel_mode <= "01";
en_w_secondo_op <= '1';
nxt <= IDLE;
when RISULTATO =>
-- sel_mode <= "00";
en_w_risultato <= '1';
nxt <= IDLE;
end case;
end process;
led_ov <= ov;
subtract_out <= subtract_in;
end Behavioral;发布于 2016-02-03 07:55:59
添加了
令人惊讶的是,它有效,但这在概念上是正确的吗?我的意思是,用某种输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式?
设计状态总是由设计中的所有寄存器组成,而不仅仅是设计中的寄存器curr。你可以这样想:
curr定义。这是使用两个进程形式描述的。sel_mode是一个数据路径寄存器,因此定义了数据路径部分的状态。您已经使用单进程形式描述了它。使用两个过程形式的替代解决方案,我将在下面描述.总之,锁存涉及信号"sel_mode“,因为我不知道如何在状态的其他分支中指定空闲的东西,比如”保留“以前的值”sel_mode“(没有锁存警告)。
为了防止锁存的推断,您必须将sel_mode的当前值保存到时钟边缘触发寄存器中,并在需要输出前一个值时分配寄存器值。由于寄存器表示前面的值,所以我称它为sel_mode_prev。寄存器的分配是在时钟过程中与一些重置逻辑一起进行的:
change_state : process(clock, reset_n_in)
begin
if reset_n_in = '0' then
curr <= IDLE;
sel_mode_prev <= "00"; -- or some other value
elsif rising_edge(clock) then
curr <= nxt;
sel_mode_prev <= sel_mode_i; -- save current value
end if;
end process;在组合部分中分配输出sel_mode。但是,由于不能在上面的sel_mode_prev赋值中读取输出的值,所以必须将sel_mode的所需值分配给中间值,我称之为sel_mode_i。然后组合过程fsm分配这个信号。输出sel_mode <= sel_mode_i;的分配与其他输出赋值一起在流程下面组合完成。
这里是包含注释的完整的修改后的体系结构:
architecture Behavioral of control_unit is
type state is (IDLE, PRIMO_OP, SECONDO_OP, RISULTATO);
signal curr, nxt : state := IDLE;
signal sel_mode_i : std_logic_vector(1 downto 0); -- internal version of output
signal sel_mode_prev : std_logic_vector(1 downto 0); -- previous version of sel_mode
begin
change_state : process(clock, reset_n_in)
begin
if reset_n_in = '0' then
curr <= IDLE;
sel_mode_prev <= "00"; -- or some other value
elsif rising_edge(clock) then
curr <= nxt;
sel_mode_prev <= sel_mode_i; -- save current value
end if;
end process;
fsm: process(curr, reset_n_in, primo_operando, secondo_operando, add_sub,
sel_mode_prev) -- also add sel_mode_prev here
begin
if reset_n_in = '0' then
reset_n_out <= '0';
else
reset_n_out <= '1';
end if;
en_w_primo_op <= '0';
en_w_secondo_op <= '0';
en_w_risultato <= '0';
case curr is
when IDLE =>
if primo_operando = '1' then
sel_mode_i <= "10"; -- assign internal signal
nxt <= PRIMO_OP;
elsif secondo_operando = '1' then
sel_mode_i <= "01"; -- assign internal signal
nxt <= SECONDO_OP;
elsif add_sub = '1' then
sel_mode_i <= "00"; -- assign internal signal
nxt <= RISULTATO;
else
sel_mode_i <= sel_mode_prev; -- output old value at default
nxt <= IDLE;
end if;
when PRIMO_OP =>
sel_mode_i <= "10"; -- assign internal signal
en_w_primo_op <= '1';
nxt <= IDLE;
when SECONDO_OP =>
sel_mode_i <= "01"; -- assign internal signal
en_w_secondo_op <= '1';
nxt <= IDLE;
when RISULTATO =>
sel_mode_i <= "00"; -- assign internal signal
en_w_risultato <= '1';
nxt <= IDLE;
end case;
end process;
sel_mode <= sel_mode_i; -- assign internal signal to output
led_ov <= ov;
subtract_out <= subtract_in;
end Behavioral;https://stackoverflow.com/questions/35166524
复制相似问题