VHDL State Machine Проблемы - повторяет состояния - PullRequest
0 голосов
/ 10 декабря 2018

Мы строим процессор для нашего финального проекта.Блок управления является конечным автоматом, но, похоже, он застревает в состояниях дольше, чем должен, и поэтому он повторяет инструкции.

Мы используем 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;

Этот сумматор просто добавляет единицу к значению, которое в данный момент находится на ПК:

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 голосов
/ 10 декабря 2018

FSM - основная проблема

Ваш второй процесс должен реализовать назначения по умолчанию, чтобы сэкономить множество ненужных веток, где вы определяете самообрезь своего графика FSM.Поскольку вы пропустили это, ваш FSM создает дополнительные защелки для сигнала current_state!Проверьте свой сводный отчет на наличие предупреждений о защелках, и вы можете найти их несколько.

Другие ошибки в том же файле

  • Вы перепутали current_state и next_state.Значение сигналов не отражает ваш код!В вашем случае необходимо включить 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!

  • Ваши глаза и, вероятно, также ваши светодиоды не будут достаточно быстры, чтобы видеть и отображать 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;

Ошибки в ПК:

  • Никогда не назначайте что-то подобное reg <= reg в VHDL!

  • Вы используете арифметику для типа std_logic_vector.Эта операция:

    1. не определена для этого типа, или
    2. вы используете пакет не IEEE, такой как synopsys.std_logic_unsigned, который вообще не должен использоваться.Используйте пакет ieee.numeric_std и введите signed / unsigned, если вам нужны арифметические операции.
  • Ваш программный счетчик (ПК) не учитывается (пока?).Основываясь на принципе единой ответственности, ваш ПК должен:

    • загружать новый указатель инструкций
    • увеличивать указатель инструкций
    • выводить текущий указатель инструкций
  • Ваш ПК назначает выход thisaddress с одним циклом задержки.Обычно это нарушает любую функциональность процессора ...

  • Поскольку вы собираетесь реализовать свой дизайн на устройстве 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

Есть isцелесообразно реализовать одну строку в объекте, потребляющем 9 строк кода?
Кроме того, ваш код описывает инкрементатор, а не сумматор.

Описание мультиплексора

Мультиплексорне описывается оператором with ... select.Это создаст логику приоритетов, такую ​​как цепочка ветвей if-elseif.

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

Поскольку теперь это независимая от размера однострочная строка, привинтите сущность nine_mux.

...