VHDL状态机问题-重复状态

时间:2018-12-09 22:54:56

标签: vhdl state-machine

我们正在为最终项目构建处理器。该控制单元是一个状态机,但是它似乎停留在状态中的时间比应有的更长,因此它会重复执行指令。

我们正在使用Vivado 2015.4和Nexys4开发板。

因此,使用一行指令将值存储到加载到指令存储器中的7段中,状态变为:

Fetch =>
Fetch =>
Fetch =>
L_S_D (Load/Store Decode) =>
L_S_E (Load/Store Execute) =>
S_Mem (Store Memory Access) =>
Fetch =>
L_S_D =>
L_S_E =>
S_Mem =>
Fetch =>
L_S_D =>
L_S_E =>
Fetch (forever)

在两个完整的遍历中,显示七个段。第三,它们不完整,没有。

我附加了状态机(相关状态)和程序计数器相关的代码,因为我认为这就是问题所在。

状态机:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Fred is
    Port ( Inst : in STD_LOGIC_vector (31 downto 21);
           clk : in std_logic;
           rst : in std_logic;
           Reg2Loc : out std_logic;
           ALUSRC : out std_logic;
           MemtoReg : out std_logic;
           RegWrite : out std_logic;
           Branch : out std_logic;
           ALUOp : out std_logic_vector (1 downto 0);
           UnconB : out std_logic;
           en : out std_logic;
           wea : out std_logic;
           PCWrite : out std_logic;
           REGCEA : out std_logic;
           LEDCode : out std_logic_vector (4 downto 0));
end Fred;

architecture Behavioral of Fred is
    Type type_fstate is (Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
        L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
            CBZ_WB);
    attribute enum_encoding : string;
    attribute enum_encoding of type_fstate : type is "one-hot";
    signal current_state : type_fstate;
    signal next_state : type_fstate;
begin

    clockprocess : process (clk, rst, current_state)
    begin 
        if rst = '1' then
            next_state <= Fetch;
        elsif clk'EVENT and clk = '1' then
            next_state <= current_state;
        end if;
    end process clockprocess;

    state_logic: process (next_state)
    begin
            case next_state is
                when Fetch => --00001
                    if ((Inst = "11111000010")) then --LDUR
                        current_state <= L_S_D;
                    elsif ((Inst = "11111000000")) then --STUR
                        current_state <= L_S_D;                        
                    --Additional State Logic Here
                    else
                        current_state <= Fetch;
                    end if;

                when L_S_D => --00010
                    current_state <= L_S_E;

                when L_S_E => --00011
                    if ((Inst = "11111000010")) then
                        current_state <= L_Mem;
                    elsif ((Inst = "11111000000")) then
                        current_state <= S_Mem;
                    end if;

                when S_Mem => --00110
                    current_state <= Fetch;

                --Additional States Here

                when others =>
                    current_state <= Fetch;
            end case;
    end process state_logic;

    output_logic : process (next_state)
    begin
        case next_state is
            when Fetch =>
                Reg2Loc <= '0';
                ALUSRC <= '0';
                MemtoReg <= '0';
                RegWrite <= '0';
                Branch <= '0';
                ALUOp <= "00";
                UnconB <= '0';
                en <= '0';
                wea <= '0';
                PCWrite <= '0';
                REGCEA <= '1';
                LEDCode <= "00001";
            when L_S_D =>
                Reg2Loc <= '1';
                ALUSRC <= '0';
                MemtoReg <= '0';
                RegWrite <= '0';
                Branch <= '0';
                ALUOp <= "00";
                UnconB <= '0';
                en <= '0';
                wea <= '0';
                PCWrite <= '0';
                REGCEA <= '0';
                LEDCode <= "00010";
            when L_S_E =>
                Reg2Loc <= '1';
                ALUSRC <= '1';
                MemtoReg <= '0';
                RegWrite <= '0';
                Branch <= '0';
                ALUOp <= "00";
                UnconB <= '0';
                en <= '0';
                wea <= '0';
                PCWrite <= '1';
                REGCEA <= '0';
                LEDCode <= "00011";
            when S_Mem =>
                Reg2Loc <= '1';
                ALUSRC <= '1';
                MemtoReg <= '0';
                RegWrite <= '0';
                Branch <= '0';
                ALUOp <= "00";
                UnconB <= '0';
                en <= '1';
                wea <= '1';
                PCWrite <= '0';
                REGCEA <= '0';
                LEDCode <= "00110";
            --Additional State Outputs Here                                                                                                                                                        
            when others =>
                Reg2Loc <= '0';
                ALUSRC <= '0';
                MemtoReg <= '0';
                RegWrite <= '0';
                Branch <= '0';
                ALUOp <= "00";
                UnconB <= '0';
                en <= '0';
                wea <= '0';
                PCWrite <= '0';
                REGCEA <= '0';
                LEDCode <= "00000";
        end case;
    end process output_logic;
end Behavioral;

数据路径:

entity Datapath is
    Port (BTNClock : in STD_LOGIC;
          clock : in STD_LOGIC;
          UncondBranch : in STD_LOGIC;
          CondBranch : in STD_LOGIC;
          RRtwoSelect : in STD_LOGIC;
          RegWriteSelect : in STD_LOGIC;
          ALUSource : in STD_LOGIC;
          ALUOpCode : in STD_LOGIC_VECTOR(1 downto 0);
          WriteSelect : in STD_LOGIC;
          MemWrite : in STD_LOGIC;
          REGCEA : in STD_LOGIC;
          PCWrite : in STD_LOGIC;
          seg_select : out STD_LOGIC_vector(6 downto 0);
          anode_select : out STD_LOGIC_vector(7 downto 0);
          ins_out : out STD_LOGIC_VECTOR(31 downto 0);
          RAMSelect : in STD_LOGIC;
          ALUEleven : out STD_LOGIC;
          REGEleven : out STD_LOGIC;
          SwitchReset : in STD_LOGIC);
end Datapath;

architecture Behavioral of Datapath is

    signal PC : STD_LOGIC_VECTOR(9 downto 0);
    signal instruction : STD_LOGIC_VECTOR(31 downto 0);
    signal BranchSelect : STD_LOGIC;
    signal ZeroBranch : STD_LOGIC;
    signal RRtwo : STD_LOGIC_VECTOR(4 downto 0);
    signal RegDataOut1 : STD_LOGIC_VECTOR(63 downto 0);
    signal RegDataOut2 : STD_LOGIC_VECTOR(63 downto 0);
    signal ALUMuxOut : STD_LOGIC_VECTOR(63 downto 0);
    signal SignExtendOut : STD_LOGIC_VECTOR(63 downto 0);
    signal BranchExtend : STD_LOGIC_VECTOR(9 downto 0);
    signal ALUOut : STD_LOGIC_VECTOR(63 downto 0);
    signal ALUZero : STD_LOGIC;
    signal MemoryOut : STD_LOGIC_VECTOR(63 downto 0);
    signal WriteMuxOut : STD_LOGIC_VECTOR(63 downto 0);
    signal Branch : STD_LOGIC_VECTOR(9 downto 0);
    signal PCNext : STD_LOGIC_VECTOR(9 downto 0);
    signal PCIncrement : STD_LOGIC_VECTOR(9 downto 0);
    signal ALUCommand : STD_LOGIC_VECTOR(3 downto 0);
    signal InstEn : STD_LOGIC := '1';
    signal OnlySeven : STD_LOGIC_VECTOR(0 downto 0);
    signal SevSegReset : STD_LOGIC := '0';

begin

    OnlySeven(0) <= MemWrite and not ALUOut(11);
    BranchSelect <= UncondBranch or ZeroBranch;
    ZeroBranch <= CondBranch and ALUZero;
    ins_out <= instruction;
    ALUEleven <= ALUout(11);
    REGEleven <= RegDataOut1(11);

    --Program Counter
    PCReg : PCounter port map ( clk => BTNClock,
               wea => PCWrite,
               newaddress => PCNext,
               thisaddress => PC);

    --Incremental adder
    IncAddr : B_adder port map ( a => PC,
               x => PCIncrement);

    --Branch Adder
    BranchAddr : In_adder port map ( a => PC,
                   b => BranchExtend,
                   x => Branch);

    --Next Instruction Address Mux
    NextPCMux : nine_mux port map ( s => BranchSelect,
                   in1 => PCIncrement,
                   in2 => Branch,
                   output => PCNext);

 --Additional Datapath Elements Here
 end Behavioral;

程序计数器:

entity PCounter is
    Port ( clk : in STD_LOGIC; --clock
           wea : in STD_LOGIC; --write enable
           newaddress : in STD_LOGIC_VECTOR (9 downto 0); --new address coming in
           thisaddress : out STD_LOGIC_VECTOR (9 downto 0) --current address to be executed
           );
end PCounter;

architecture Behavioral of PCounter is
    signal reg: std_logic_vector(9 downto 0); --internal register storage

begin
    process(clk) --nothing happens if this register isn't selected
    begin
        if clk'EVENT and clk = '1' then
                thisaddress <= reg; --send out currently saved address
            if wea = '1' then    
                reg <= newaddress; --and set register to next address
            end if;
            else
                reg <= reg; --otherwise, maintain current value
        end if;
    end process; 
end Behavioral;

此加法器仅将PC当前的值加一个:

entity B_adder is
    Port ( a : in STD_LOGIC_VECTOR (9 downto 0);
           x : out STD_LOGIC_VECTOR (9 downto 0));
end B_adder;

architecture Behavioral of B_adder is

begin

            x <= a + 1;

end Behavioral;

这个小复用器将选择下一个地址是来自分支加法器(此处未包括)还是来自上面的增量加法器:

entity nine_mux is
    Port ( s : in STD_LOGIC;
           in1 : in STD_LOGIC_VECTOR (9 downto 0);
           in2 : in STD_LOGIC_VECTOR (9 downto 0);
           output : out STD_LOGIC_VECTOR (9 downto 0));
end nine_mux;

architecture Behavioral of nine_mux is

begin

            with s select
                output <= in1 when '0',
                    in2 when others;


end Behavioral;

这是控制单元映射到数据路径的方式:

entity WholeThing is
    Port ( BTNClock : in STD_LOGIC;
           BTNReset : in STD_LOGIC;
           SwitchReset : in STD_LOGIC;
           clock : in STD_Logic;
           LEDs : out STD_LOGIC_VECTOR(4 downto 0);
           seg : out STD_LOGIC_vector(6 downto 0);
           an : out STD_LOGIC_vector(7 downto 0);
           alu11 : out STD_LOGIC;
           reg11 : out STD_LOGIC
           );
end WholeThing;

architecture Behavioral of WholeThing is

    signal instruction : STD_LOGIC_VECTOR(31 downto 0);
    signal Reg2Loc : STD_LOGIC;
    signal ALUSRC : std_logic;
    signal MemtoReg : std_logic;
    signal RegWrite : std_logic;
    signal Branch : std_logic;
    signal ALUOp : std_logic_vector (1 downto 0);
    signal UnconB : std_logic;
    signal en : std_logic;
    signal wea : std_logic;
    signal PCWrite : std_logic;
    signal REGCEA : std_logic;
    signal SwRst : STD_LOGIC;

begin

    --SwitchReset <= SwRst;

    --Control Unit
    CU : Fred port map ( Inst => instruction(31 downto 21),
           clk => BTNClock,
           rst => BTNReset,
           Reg2Loc => Reg2Loc,
           ALUSRC => ALUSRC,
           MemtoReg => MemtoReg,
           RegWrite =>RegWrite,
           Branch => Branch,
           ALUOp => ALUOp,
           UnconB => UnconB,
           en => en,
           wea => wea,
           PCWrite => PCWrite,
           REGCEA => REGCEA,
           LEDCode => LEDs);

    --Datapath
    DP : Datapath port map (BTNClock => BTNClock,
           clock => clock,
           UncondBranch => UnconB,
           CondBranch => Branch,
           RRtwoSelect => Reg2Loc,
           RegWriteSelect => RegWrite,
           ALUSource => ALUSRC,
           ALUOpCode => ALUOp,
           WriteSelect => MemtoReg,
           MemWrite => wea,
           REGCEA => REGCEA,
           PCWrite => PCWrite,
           seg_select => seg,
           anode_select => an,
           ins_out => instruction,
           RAMSelect => en,
           ALUEleven => alu11,
           REGEleven => reg11,
           SwitchReset => SwitchReset
           );


end Behavioral;

1 个答案:

答案 0 :(得分:1)

FSM-主要问题

您的第二个过程应实现默认分配,以节省大量不必要的else分支,在这些分支中您定义了FSM图的自镶边。因为您错过了,所以FSM为信号current_state创建了附加的锁存器!检查综合报告中是否存在闩锁警告,您可能会发现其中的多个警告。

同一文件中的其他错误

  • 您混合了current_statenext_state。信号的含义不 反映您的代码!您的case语句需要打开current_state

  • 不要使用3进程模式来描述FSM。这是一场噩梦 可读性和维护性!一个人可以阅读并验证此FSM表单的行为。

  • 您使用错误的方式使用了enum_encoding属性:

    1. 要定义FSM编码,请将fsm_encoding应用于状态信号
    2. 要定义用户定义的编码,请将fsm_encoding的值为user应用于状态信号,并将enum_encoding的二进制值以空格分隔的列表应用于您的状态类型。
  • 请勿使用异步重置。同步的时钟进程在灵敏度列表中只有一个信号!

  • 联合流程需要在该列表中列出所有读取的信号!

  • 您不应使用clk'EVENT and clk = '1'。请改用rising_edge(clk)

  • 如果您多次打开同一信号,请使用case语句,但不要使用if-elsif构造!

  • 您的眼睛以及您的LED可能不够快,无法看到和显示LEDCode

更正的代码:

architecture Behavioral of Fred is
  attribute fsm_encoding : string;

  type type_fstate is (
    Fetch, L_S_D, L_S_E, L_Mem, S_Mem,
    L_WB, R_I_D, I_E, R_E, I_WB, R_WB, B_E, CBZ_D, B_WB, CBZ_E,
    CBZ_WB);

  signal current_state : type_fstate := Fetch;
  signal next_state    : type_fstate;
  attribute fsm_encoding of current_state : signal is "one-hot";
begin
  clockprocess : process(clk)
  begin 
    if rising_edge(clk) then
      if rst = '1' then
        current_state <= Fetch;
      else
        current_state <= next_state;
      end if;
    end if;
  end process;

  state_logic: process (current_state, Inst)
  begin
    next_state <= current_state;

    Reg2Loc  <= '0';
    ALUSRC   <= '0';
    MemtoReg <= '0';
    RegWrite <= '0';
    Branch   <= '0';
    ALUOp    <= "00";
    UnconB   <= '0';
    en       <= '0';
    wea      <= '0';
    PCWrite  <= '0';
    REGCEA   <= '0';
    LEDCode  <= "00000";

    case current_state is
      when Fetch => --00001
        REGCEA  <= '1';
        LEDCode <= "00001";

        case Inst is
          when "11111000010" => --LDUR
            next_state <= L_S_D;
          when "11111000000" => --STUR
            next_state <= L_S_D;                        

          --Additional State Logic Here
          when others =>
            next_state <= Fetch;
        end case;

      when L_S_D => --00010
        Reg2Loc <= '1';
        LEDCode <= "00010";

        next_state <= L_S_E;

      when L_S_E => --00011
        Reg2Loc <= '1';
        ALUSRC  <= '1';
        PCWrite <= '1';
        LEDCode <= "00011";

        case Inst is
          when "11111000010" =>
            next_state <= L_Mem;
          when "11111000000" =>
            next_state <= S_Mem;
          when others =>
            -- ???
        end case;

      when S_Mem => --00110
        Reg2Loc <= '1';
        ALUSRC  <= '1';
        en      <= '1';
        wea     <= '1';
        LEDCode <= "00110";

        next_state <= Fetch;

      --Additional States Here

      when others =>
        next_state <= Fetch;
    end case;
  end process;

end architecture;

PC中的错误:

  • 请不要在VHDL中分配类似reg <= reg的内容!

  • 您正在对类型std_logic_vector使用算术。该操作是:

    1. 未为该类型定义,或
    2. 您使用的是synopsys.std_logic_unsigned之类的非IEEE程序包,完全不应该使用。如果需要算术运算,请使用软件包ieee.numeric_std和类型signed / unsigned
  • 您的程序计数器(PC)不计数(还?)。根据单一责任原则,您的PC应该能够:

    • 加载新的指令指针
    • 增加指令指针
    • 输出当前指令指针
  • 您的PC为输出thisaddress分配了一个延迟周期。通常,这会破坏任何CPU功能...

  • 当您要在FPGA器件上实现设计时,请确保使用适当的初始化值初始化所有转换为存储器(例如寄存器)的信号。

改进的代码:

architecture Behavioral of PCounter is
  signal reg: unsigned(9 downto 0) := (others => '0');
begin

  process(clk)
  begin
    if rising_edge(clk) then
      if wea = '1' then    
        reg <= unsigned(newaddress);
      end if;
    end if;
  end process; 

  thisaddress <= reg;
end architecture;

您的加法器B_adder

在消耗9行代码的实体中实现一行代码明智吗?
而且,您的代码描述的是增量器,而不是加法器。

描述多路复用器

没有用with ... select语句描述多路复用器。这将创建一个优先级逻辑,例如一系列if-elseif分支。

output <= in1 when (s = '0') else in2;

由于现在这是一个不受大小限制的单线,所以请拧紧nine_mux实体。