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

Мы используем 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
whimsey 10 Дек 2018 в 01:54

1 ответ

Лучший ответ

Автомат - главная проблема

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

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

  • Вы перепутали current_state и next_state. Смысл сигналов не отразите свой код! В вашем операторе case необходимо включить current_state.

  • Не используйте шаблон из трех процессов для описания конечного автомата. Это кошмар кода читаемость и обслуживание! Можно прочитать и проверить поведение этой формы конечного автомата.

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

Разве разумно реализовать однострочную сущность, занимающую 9 строк кода?
Более того, ваш код описывает инкремент, а не сумматор.

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

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

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

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

1
Paebbels 10 Дек 2018 в 00:09