fsm2进程VHDL

fsm2进程VHDL,vhdl,fpga,fsm,Vhdl,Fpga,Fsm,我正试图为我的项目的一个控制单元的FSM写下VHDL代码。我选择了2进程方式,一个进程用于状态寄存器,另一个进程用于下一个状态和输出逻辑。无论如何,我在设置解决方案时遇到了一些问题,因为一些信号会发出警告(我知道它们为什么会出现)。我发现的唯一解决方案(没有为状态寄存器和输出逻辑使用一个进程,也没有再添加3个状态)是在管理状态逻辑的进程中添加一些输出逻辑 令人惊讶的是,它是有效的,但这在概念上是正确的吗?我的意思是,用一些输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式 这是我的

我正试图为我的项目的一个控制单元的FSM写下VHDL代码。我选择了2进程方式,一个进程用于状态寄存器,另一个进程用于下一个状态和输出逻辑。无论如何,我在设置解决方案时遇到了一些问题,因为一些信号会发出警告(我知道它们为什么会出现)。我发现的唯一解决方案(没有为状态寄存器和输出逻辑使用一个进程,也没有再添加3个状态)是在管理状态逻辑的进程中添加一些输出逻辑

令人惊讶的是,它是有效的,但这在概念上是正确的吗?我的意思是,用一些输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式

这是我的工作和“无锁警告”控制单元的代码。无论如何,闩锁涉及信号
sel_mode
,因为我不知道如何在状态IDLE的else分支中指定类似“保留“sel_mode”的先前值”(没有闩锁警告)

IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.ALL;
实体控制单元为
端口(时钟:标准_逻辑中;
reset_n_in:标准逻辑中;
基本操作数:在标准逻辑中;
二次操作数:在标准逻辑中;
在STD_逻辑中添加_sub:;
ov:标准逻辑中;
在标准逻辑中减去;
led_ov:输出标准_逻辑;
复位输出:输出标准逻辑;
减法输出:输出标准输出逻辑;
基本操作:输出标准逻辑;
第二步:输出标准逻辑;
en_w_risultato:输出标准逻辑;
选择模式:输出标准逻辑向量(1到0)
);
终端控制单元;
控制单元的结构是
类型状态为(空闲、第一次操作、第二次操作、中断);
信号电流,nxt:状态:=空闲;
开始
更改状态:进程(时钟、复位)
开始
如果reset_n_in='0',则

当前添加了以下内容:

令人惊讶的是,它可以工作,但这在概念上是正确的吗?我的意思是,用一些输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式

设计状态始终由设计中的所有寄存器组成,而不仅仅是设计中的寄存器
curr
。您可以这样想:

  • FSM的(部分)状态由
    curr
    定义。这是使用两个进程形式描述的

  • 您发布的代码中的寄存器
    sel_mode
    是一个数据路径寄存器,因此定义了数据路径部分的状态。您已经使用单进程形式对其进行了描述。下面我将介绍使用双进程形式的替代解决方案


无论如何,锁存器涉及信号“sel_mode”,因为我不知道如何在状态IDLE的else分支中指定类似“保留“sel_mode”的先前值”(没有锁存器警告)

为了防止闩锁推断,您必须将sel_模式的当前值保存到时钟边缘触发寄存器中,并在您想要输出前一个值时分配寄存器值。由于寄存器表示上一个值,我将其称为
sel\u mode\u 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;

令人惊讶的是,它是有效的,但这在概念上是正确的吗?我的意思是,用一些输出逻辑弄脏状态寄存器进程的代码是正确的,还是我打破了2进程模式?您是否有编程问题,或者这都是关于风格的问题?如果
sel\u模式
在空闲的第一个分支之前无效,会发生什么情况?(并在映射
sel_mode
的默认值可能为“00”之前合成为二进制表示)。你在模仿你的设计吗?谢谢你,马丁。那么,我发现的解决方案是错误的吗?@Mazzola不,只要
sel_mode
符合您的规范,您的解决方案就是正确的。您只是混合了代码模式。我扩展了我的回答来讨论这一点。
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;
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;