首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >FSM 2工艺VHDL

FSM 2工艺VHDL
EN

Stack Overflow用户
提问于 2016-02-03 00:41:31
回答 1查看 741关注 0票数 1

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

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

这是我的工作代码和“无锁存警告”控制单元。总之,锁存涉及信号sel_mode,因为我不知道如何在状态空闲的其他分支中指定类似于“保留”“sel_mode”的前一个值(没有锁存警告)。

代码语言:javascript
运行
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-03 07:55:59

添加了

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

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

  • 有限状态机的(部分)状态由curr定义。这是使用两个进程形式描述的。
  • 您发布的代码中的寄存器sel_mode是一个数据路径寄存器,因此定义了数据路径部分的状态。您已经使用单进程形式描述了它。使用两个过程形式的替代解决方案,我将在下面描述.

总之,锁存涉及信号"sel_mode“,因为我不知道如何在状态的其他分支中指定空闲的东西,比如”保留“以前的值”sel_mode“(没有锁存警告)。

为了防止锁存的推断,您必须将sel_mode的当前值保存到时钟边缘触发寄存器中,并在需要输出前一个值时分配寄存器值。由于寄存器表示前面的值,所以我称它为sel_mode_prev。寄存器的分配是在时钟过程中与一些重置逻辑一起进行的:

代码语言:javascript
运行
复制
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;的分配与其他输出赋值一起在流程下面组合完成。

这里是包含注释的完整的修改后的体系结构:

代码语言:javascript
运行
复制
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;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35166524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档