OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [rtl/] [riverlib/] [core/] [decoder.vhd] - Rev 5

Compare with Previous | Blame | View Log

-----------------------------------------------------------------------------
--! @file
--! @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
--! @author    Sergey Khabarov - sergeykhbr@gmail.com
--! @brief     CPU Instruction Decoder stage.
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
library commonlib;
use commonlib.types_common.all;
--! RIVER CPU specific library.
library riverlib;
--! RIVER CPU configuration constants.
use riverlib.river_cfg.all;
 
 
entity InstrDecoder is
  port (
    i_clk  : in std_logic;
    i_nrst : in std_logic;
    i_any_hold : in std_logic;                               -- Hold pipeline by any reason
    i_f_valid : in std_logic;                                -- Fetch input valid
    i_f_pc : in std_logic_vector(BUS_ADDR_WIDTH-1 downto 0); -- Fetched pc
    i_f_instr : in std_logic_vector(31 downto 0);            -- Fetched instruction value
 
    o_valid : out std_logic;                                 -- Current output values are valid
    o_pc : out std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);  -- Current instruction pointer value
    o_instr : out std_logic_vector(31 downto 0);             -- Current instruction value
    o_memop_store : out std_logic;                           -- Store to memory operation
    o_memop_load : out std_logic;                            -- Load from memoru operation
    o_memop_sign_ext : out std_logic;                        -- Load memory value with sign extending
    o_memop_size : out std_logic_vector(1 downto 0);         -- Memory transaction size
    o_rv32 : out std_logic;                                  -- 32-bits instruction
    o_compressed : out std_logic;                            -- 16-bits opcode (C-extension)
    o_unsigned_op : out std_logic;                           -- Unsigned operands
    o_isa_type : out std_logic_vector(ISA_Total-1 downto 0); -- Instruction format accordingly with ISA
    o_instr_vec : out std_logic_vector(Instr_Total-1 downto 0); -- One bit per decoded instruction bus
    o_exception : out std_logic                              -- Unimplemented instruction
  );
end; 
 
architecture arch_InstrDecoder of InstrDecoder is
 
  -- LB, LH, LW, LD, LBU, LHU, LWU
  constant OPCODE_LB     : std_logic_vector(4 downto 0) := "00000";
  -- FENCE, FENCE_I
  constant OPCODE_FENCE  : std_logic_vector(4 downto 0) := "00011";
  --  ADDI, ANDI, ORI, SLLI, SLTI, SLTIU, SRAI, SRLI, XORI
  constant OPCODE_ADDI   : std_logic_vector(4 downto 0) := "00100";
  -- AUIPC
  constant OPCODE_AUIPC  : std_logic_vector(4 downto 0) := "00101";
  -- ADDIW, SLLIW, SRAIW, SRLIW
  constant OPCODE_ADDIW  : std_logic_vector(4 downto 0) := "00110";
  -- SB, SH, SW, SD
  constant OPCODE_SB     : std_logic_vector(4 downto 0) := "01000";
  -- ADD, AND, OR, SLT, SLTU, SLL, SRA, SRL, SUB, XOR, DIV, DIVU, MUL, REM, REMU
  constant OPCODE_ADD    : std_logic_vector(4 downto 0) := "01100";
  -- LUI
  constant OPCODE_LUI    : std_logic_vector(4 downto 0) := "01101";
  -- ADDW, SLLW, SRAW, SRLW, SUBW, DIVW, DIVUW, MULW, REMW, REMUW
  constant OPCODE_ADDW   : std_logic_vector(4 downto 0) := "01110";
  -- BEQ, BNE, BLT, BGE, BLTU, BGEU
  constant OPCODE_BEQ    : std_logic_vector(4 downto 0) := "11000";
  -- JALR
  constant OPCODE_JALR   : std_logic_vector(4 downto 0) := "11001";
  -- JAL
  constant OPCODE_JAL    : std_logic_vector(4 downto 0) := "11011";
  -- CSRRC, CSRRCI, CSRRS, CSRRSI, CSRRW, CSRRWI, URET, SRET, HRET, MRET
  constant OPCODE_CSRR   : std_logic_vector(4 downto 0) := "11100"; 
  -- Compressed instruction set
  constant OPCODE_C_ADDI4SPN : std_logic_vector(4 downto 0) := "00000";
  constant OPCODE_C_NOP_ADDI : std_logic_vector(4 downto 0) := "00001";
  constant OPCODE_C_SLLI     : std_logic_vector(4 downto 0) := "00010";
  constant OPCODE_C_JAL_ADDIW : std_logic_vector(4 downto 0) := "00101";
  constant OPCODE_C_LW       : std_logic_vector(4 downto 0) := "01000";
  constant OPCODE_C_LI       : std_logic_vector(4 downto 0) := "01001";
  constant OPCODE_C_LWSP     : std_logic_vector(4 downto 0) := "01010";
  constant OPCODE_C_LD       : std_logic_vector(4 downto 0) := "01100";
  constant OPCODE_C_ADDI16SP_LUI : std_logic_vector(4 downto 0) := "01101";
  constant OPCODE_C_LDSP     : std_logic_vector(4 downto 0) := "01110";
  constant OPCODE_C_MATH     : std_logic_vector(4 downto 0) := "10001";
  constant OPCODE_C_JR_MV_EBREAK_JALR_ADD : std_logic_vector(4 downto 0) := "10010";
  constant OPCODE_C_J        : std_logic_vector(4 downto 0) := "10101";
  constant OPCODE_C_SW       : std_logic_vector(4 downto 0) := "11000";
  constant OPCODE_C_BEQZ     : std_logic_vector(4 downto 0) := "11001";
  constant OPCODE_C_SWSP     : std_logic_vector(4 downto 0) := "11010";
  constant OPCODE_C_SD       : std_logic_vector(4 downto 0) := "11100";
  constant OPCODE_C_BNEZ     : std_logic_vector(4 downto 0) := "11101";
  constant OPCODE_C_SDSP     : std_logic_vector(4 downto 0) := "11110";
 
 
  constant INSTR_NONE : std_logic_vector(Instr_Total-1 downto 0) := (others => '0');
 
  type RegistersType is record
      valid : std_logic;
      pc : std_logic_vector(BUS_ADDR_WIDTH-1 downto 0);
      isa_type : std_logic_vector(ISA_Total-1 downto 0);
      instr_vec : std_logic_vector(Instr_Total-1 downto 0);
      instr : std_logic_vector(31 downto 0);
      memop_store : std_logic;
      memop_load : std_logic;
      memop_sign_ext : std_logic;
      memop_size : std_logic_vector(1 downto 0);
      unsigned_op : std_logic;
      rv32 : std_logic;
      compressed : std_logic;
      instr_unimplemented : std_logic;
  end record;
 
  signal r, rin : RegistersType;
 
begin
 
 
  comb : process(i_nrst, i_any_hold, i_f_valid, i_f_pc, i_f_instr, r)
    variable v : RegistersType;
    variable w_o_valid : std_logic;
    variable w_error : std_logic;
    variable w_compressed : std_logic;
    variable wb_instr : std_logic_vector(31 downto 0);
    variable wb_instr_out : std_logic_vector(31 downto 0);
    variable wb_opcode1 : std_logic_vector(4 downto 0);
    variable wb_opcode2 : std_logic_vector(2 downto 0);
    variable wb_dec : std_logic_vector(Instr_Total-1 downto 0);
    variable wb_isa_type : std_logic_vector(ISA_Total-1 downto 0);
  begin
 
    v := r;
    w_error := '0';
    w_compressed := '0';
    wb_instr := i_f_instr;
    wb_opcode1 := wb_instr(6 downto 2);
    wb_opcode2 := wb_instr(14 downto 12);
    wb_dec := (others => '0');
    wb_isa_type := (others => '0');
 
    if wb_instr(1 downto 0) /= "11" then
        w_compressed := '1';
        wb_opcode1 := wb_instr(15 downto 13) & wb_instr(1 downto 0);
        wb_instr_out := X"00000003";
        case wb_opcode1 is
        when OPCODE_C_ADDI4SPN =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_ADDI) := '1';
            wb_instr_out(11 downto 7) := "01" & wb_instr(4 downto 2);   -- rd
            wb_instr_out(19 downto 15) := "00010";                     -- rs1 = sp
            wb_instr_out(29 downto 22) :=
                wb_instr(10 downto 7) & wb_instr(12 downto 11) & wb_instr(5) & wb_instr(6);
        when OPCODE_C_NOP_ADDI =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_ADDI) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);   -- rd
            wb_instr_out(19 downto 15) := wb_instr(11 downto 7);  -- rs1
            wb_instr_out(24 downto 20) := wb_instr(6 downto 2);   -- imm
            if wb_instr(12) = '1' then
                wb_instr_out(31 downto 25) := (others => '1');
            end if;
        when OPCODE_C_SLLI =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_SLLI) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);      -- rd
            wb_instr_out(19 downto 15) := wb_instr(11 downto 7);     -- rs1
            wb_instr_out(25 downto 20) := wb_instr(12) & wb_instr(6 downto 2);  -- shamt
        when OPCODE_C_JAL_ADDIW =>
            -- JAL is the RV32C only instruction
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_ADDIW) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);      -- rd
            wb_instr_out(19 downto 15) := wb_instr(11 downto 7);     -- rs1
            wb_instr_out(24 downto 20) := wb_instr(6 downto 2);      -- imm
            if wb_instr(12) = '1' then
                wb_instr_out(31 downto 25) := (others => '1');
            end if;
        when OPCODE_C_LW =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_LW) := '1';
            wb_instr_out(11 downto 7) := "01" & wb_instr(4 downto 2);   -- rd
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
            wb_instr_out(26 downto 22) :=
                wb_instr(5) & wb_instr(12 downto 10) & wb_instr(6);
        when OPCODE_C_LI =>  -- ADDI rd = r0 + imm
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_ADDI) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);      -- rd
            wb_instr_out(24 downto 20) := wb_instr(6 downto 2);      -- imm
            if wb_instr(12) = '1' then
                wb_instr_out(31 downto 25) := (others => '1');
            end if;
        when OPCODE_C_LWSP =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_LW) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);    -- rd
            wb_instr_out(19 downto 15) := "00010";                 -- rs1 = sp
            wb_instr_out(27 downto 22) :=
                wb_instr(3 downto 2) & wb_instr(12) & wb_instr(6 downto 4);
        when OPCODE_C_LD =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_LD) := '1';
            wb_instr_out(11 downto 7) := "01" & wb_instr(4 downto 2);   -- rd
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
            wb_instr_out(27 downto 23) :=
                wb_instr(6) & wb_instr(5) & wb_instr(12 downto 10);
        when OPCODE_C_ADDI16SP_LUI =>
            if wb_instr(11 downto 7) = "00010" then
                wb_isa_type(ISA_I_type) := '1';
                wb_dec(Instr_ADDI) := '1';
                wb_instr_out(11 downto 7) := "00010";     -- rd = sp
                wb_instr_out(19 downto 15) := "00010";    -- rs1 = sp
                wb_instr_out(28 downto 24) :=
                    wb_instr(4 downto 3) & wb_instr(5) & wb_instr(2) & wb_instr(6);
                if wb_instr(12) = '1' then
                    wb_instr_out(31 downto 29) := (others => '1');
                end if;
            else
                wb_isa_type(ISA_U_type) := '1';
                wb_dec(Instr_LUI) := '1';
                wb_instr_out(11 downto 7) := wb_instr(11 downto 7);  -- rd
                wb_instr_out(16 downto 12) := wb_instr(6 downto 2);
                if wb_instr(12) = '1' then
                    wb_instr_out(31 downto 17) := (others => '1');
                end if;
            end if;
        when OPCODE_C_LDSP =>
            wb_isa_type(ISA_I_type) := '1';
            wb_dec(Instr_LD) := '1';
            wb_instr_out(11 downto 7) := wb_instr(11 downto 7);  -- rd
            wb_instr_out(19 downto 15) := "00010";               -- rs1 = sp
            wb_instr_out(28 downto 23) :=
                wb_instr(4 downto 2) & wb_instr(12) & wb_instr(6 downto 5);
        when OPCODE_C_MATH =>
            if wb_instr(11 downto 10) = "00" then
                wb_isa_type(ISA_I_type) := '1';
                wb_dec(Instr_SRLI) := '1';
                wb_instr_out(11 downto 7) := "01" & wb_instr(9 downto 7);   -- rd
                wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
                wb_instr_out(25 downto 20) := wb_instr(12) & wb_instr(6 downto 2);  -- shamt
            elsif wb_instr(11 downto 10) = "01" then
                wb_isa_type(ISA_I_type) := '1';
                wb_dec(Instr_SRAI) := '1';
                wb_instr_out(11 downto 7) := "01" & wb_instr(9 downto 7);   -- rd
                wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
                wb_instr_out(25 downto 20) := wb_instr(12) & wb_instr(6 downto 2);  -- shamt
            elsif wb_instr(11 downto 10) = "10" then
                wb_isa_type(ISA_I_type) := '1';
                wb_dec(Instr_ANDI) := '1';
                wb_instr_out(11 downto 7) := "01" & wb_instr(9 downto 7);   -- rd
                wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
                wb_instr_out(24 downto 20) := wb_instr(6 downto 2);        -- imm
                if wb_instr(12) = '1' then
                    wb_instr_out(31 downto 25) := (others => '1');
                end if;
            elsif wb_instr(12) = '0' then
                wb_isa_type(ISA_R_type) := '1';
                wb_instr_out(11 downto 7) := "01" & wb_instr(9 downto 7);   -- rd
                wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
                wb_instr_out(24 downto 20) := "01" & wb_instr(4 downto 2);  -- rs2
                case wb_instr(6 downto 5) is
                when "00" =>
                    wb_dec(Instr_SUB) := '1';
                when "01" =>
                    wb_dec(Instr_XOR) := '1';
                when "10" =>
                    wb_dec(Instr_OR) := '1';
                when others =>
                    wb_dec(Instr_AND) := '1';
                end case;
            else
                wb_isa_type(ISA_R_type) := '1';
                wb_instr_out(11 downto 7) := "01" & wb_instr(9 downto 7);   -- rd
                wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
                wb_instr_out(24 downto 20) := "01" & wb_instr(4 downto 2);  -- rs2
                case wb_instr(6 downto 5) is
                when "00" =>
                    wb_dec(Instr_SUBW) := '1';
                when "01" =>
                    wb_dec(Instr_ADDW) := '1';
                when others =>
                    w_error := '1';
                end case;
            end if;
        when OPCODE_C_JR_MV_EBREAK_JALR_ADD =>
            wb_isa_type(ISA_I_type) := '1';
            if wb_instr(12) = '0' then
                if wb_instr(6 downto 2) = "00000" then
                    wb_dec(Instr_JALR) := '1';
                    wb_instr_out(19 downto 15) := wb_instr(11 downto 7);  -- rs1
                else
                    wb_dec(Instr_ADDI) := '1';
                    wb_instr_out(11 downto 7) := wb_instr(11 downto 7);   -- rd
                    wb_instr_out(19 downto 15) := wb_instr(6 downto 2);   -- rs1
                end if;
            else
                if wb_instr(11 downto 7) = "00000" and wb_instr(6 downto 2) = "00000" then
                    wb_dec(Instr_EBREAK) := '1';
                elsif wb_instr(6 downto 2) = "00000" then
                    wb_dec(Instr_JALR) := '1';
                    wb_instr_out(11 downto 7) := "00001";                 -- rd = ra
                    wb_instr_out(19 downto 15) := wb_instr(11 downto 7);  -- rs1
                else
                    wb_dec(Instr_ADD) := '1';
                    wb_isa_type(ISA_R_type) := '1';
                    wb_instr_out(11 downto 7) := wb_instr(11 downto 7);   -- rd
                    wb_instr_out(19 downto 15) := wb_instr(11 downto 7);  -- rs1
                    wb_instr_out(24 downto 20) := wb_instr(6 downto 2);   -- rs2
                end if;
            end if;
        when OPCODE_C_J =>   -- JAL with rd = 0
            wb_isa_type(ISA_UJ_type) := '1';
            wb_dec(Instr_JAL) := '1';
            wb_instr_out(20) := wb_instr(12);            -- imm11
            wb_instr_out(23 downto 21) := wb_instr(5 downto 3);      -- imm10_1(3:1)
            wb_instr_out(24) := wb_instr(11);            -- imm10_1(4)
            wb_instr_out(25) := wb_instr(2);             -- imm10_1(5)
            wb_instr_out(26) := wb_instr(7);             -- imm10_1(6)
            wb_instr_out(27) := wb_instr(6);             -- imm10_1(7)
            wb_instr_out(29 downto 28) := wb_instr(10 downto 9);     -- imm10_1(9:8)
            wb_instr_out(30) := wb_instr(8);             -- imm10_1(10)
            if wb_instr(12) = '1' then
                wb_instr_out(19 downto 12) := (others => '1'); -- imm19_12
                wb_instr_out(31) := '1';                 -- imm20
            end if;
        when OPCODE_C_SW =>
            wb_isa_type(ISA_S_type) := '1';
            wb_dec(Instr_SW) := '1';
            wb_instr_out(24 downto 20) := "01" & wb_instr(4 downto 2);    -- rs2
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);    -- rs1
            wb_instr_out(11 downto 9) := wb_instr(11 downto 10) & wb_instr(6);
            wb_instr_out(26 downto 25) := wb_instr(5) & wb_instr(12);
        when OPCODE_C_BEQZ =>
            wb_isa_type(ISA_SB_type) := '1';
            wb_dec(Instr_BEQ) := '1';
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);    -- rs1
            wb_instr_out(11 downto 8) := wb_instr(11 downto 10) & wb_instr(4 downto 3);
            wb_instr_out(27 downto 25) := wb_instr(6 downto 5) & wb_instr(2);
            if wb_instr(12) = '1' then
                wb_instr_out(30 downto 28) := (others => '1');
                wb_instr_out(7) := '1';
                wb_instr_out(31) := '1';
            end if;
        when OPCODE_C_SWSP =>
            wb_isa_type(ISA_S_type) := '1';
            wb_dec(Instr_SW) := '1';
            wb_instr_out(24 downto 20) := wb_instr(6 downto 2);  -- rs2
            wb_instr_out(19 downto 15) := "00010";             -- rs1 = sp
            wb_instr_out(11 downto 9) := wb_instr(11 downto 9);
            wb_instr_out(27 downto 25) := wb_instr(8 downto 7) & wb_instr(12);
        when OPCODE_C_SD =>
            wb_isa_type(ISA_S_type) := '1';
            wb_dec(Instr_SD) := '1';
            wb_instr_out(24 downto 20) := "01" & wb_instr(4 downto 2);  -- rs2
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);  -- rs1
            wb_instr_out(11 downto 10) := wb_instr(11 downto 10);
            wb_instr_out(27 downto 25) := wb_instr(6 downto 5) & wb_instr(12);
        when OPCODE_C_BNEZ =>
            wb_isa_type(ISA_SB_type) := '1';
            wb_dec(Instr_BNE) := '1';
            wb_instr_out(19 downto 15) := "01" & wb_instr(9 downto 7);    -- rs1
            wb_instr_out(11 downto 8) := wb_instr(11 downto 10) & wb_instr(4 downto 3);
            wb_instr_out(27 downto 25) := wb_instr(6 downto 5) & wb_instr(2);
            if wb_instr(12) = '1' then
                wb_instr_out(30 downto 28) := (others => '1');
                wb_instr_out(7) := '1';
                wb_instr_out(31) := '1';
            end if;
        when OPCODE_C_SDSP =>
            wb_isa_type(ISA_S_type) := '1';
            wb_dec(Instr_SD) := '1';
            wb_instr_out(24 downto 20) := wb_instr(6 downto 2);  -- rs2
            wb_instr_out(19 downto 15) := "00010";               -- rs1 = sp
            wb_instr_out(11 downto 10) := wb_instr(11 downto 10);
            wb_instr_out(28 downto 25) := wb_instr(9 downto 7) & wb_instr(12);
        when others =>
            w_error := '1';
        end case;
    else -- compressed/!not compressed
        case wb_opcode1 is
        when OPCODE_ADD =>
            wb_isa_type(ISA_R_type) := '1';
            case wb_opcode2 is
            when "000" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_ADD) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_MUL) := '1';
                elsif wb_instr(31 downto 25) = "0100000" then
                    wb_dec(Instr_SUB) := '1';
                else
                    w_error := '1';
                end if;
            when "001" =>
                wb_dec(Instr_SLL) := '1';
            when "010" =>
                wb_dec(Instr_SLT) := '1';
            when "011" =>
                wb_dec(Instr_SLTU) := '1';
            when "100" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_XOR) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_DIV) := '1';
                else 
                    w_error := '1';
                end if;
            when "101" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_SRL) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_DIVU) := '1';
                elsif wb_instr(31 downto 25) = "0100000" then
                    wb_dec(Instr_SRA) := '1';
                else
                    w_error := '1';
                end if;
            when "110" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_OR) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_REM) := '1';
                else
                    w_error := '1';
                end if;
            when "111" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_AND) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_REMU) := '1';
                else
                    w_error := '1';
                end if;
            when others =>
                w_error := '1';
            end case;
        when OPCODE_ADDI =>
            wb_isa_type(ISA_I_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_ADDI) := '1';
            when "001" =>
                wb_dec(Instr_SLLI) := '1';
            when "010" =>
                wb_dec(Instr_SLTI) := '1';
            when "011" =>
                wb_dec(Instr_SLTIU) := '1';
            when "100" =>
                wb_dec(Instr_XORI) := '1';
            when "101" =>
                if wb_instr(31 downto 26) = "000000" then
                    wb_dec(Instr_SRLI) := '1';
                elsif wb_instr(31 downto 26) = "010000" then
                    wb_dec(Instr_SRAI) := '1';
                else
                    w_error := '1';
                end if;
            when "110" =>
                wb_dec(Instr_ORI) := '1';
            when "111" =>
                wb_dec(Instr_ANDI) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_ADDIW =>
            wb_isa_type(ISA_I_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_ADDIW) := '1';
            when "001" =>
                wb_dec(Instr_SLLIW) := '1';
            when "101" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_SRLIW) := '1';
                elsif wb_instr(31 downto 25) = "0100000" then
                    wb_dec(Instr_SRAIW) := '1';
                else
                    w_error := '1';
                end if;
            when others =>
                w_error := '1';
            end case;
        when OPCODE_ADDW =>
            wb_isa_type(ISA_R_type) := '1';
            case wb_opcode2 is
            when "000" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_ADDW) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_MULW) := '1';
                elsif wb_instr(31 downto 25) = "0100000" then
                    wb_dec(Instr_SUBW) := '1';
                else
                    w_error := '1';
                end if;
            when "001" =>
                wb_dec(Instr_SLLW) := '1';
            when "100" =>
                if wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_DIVW) := '1';
                else
                    w_error := '1';
                end if;
            when "101" =>
                if wb_instr(31 downto 25) = "0000000" then
                    wb_dec(Instr_SRLW) := '1';
                elsif wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_DIVUW) := '1';
                elsif wb_instr(31 downto 25) = "0100000" then
                    wb_dec(Instr_SRAW) := '1';
                else
                    w_error := '1';
                end if;
            when "110" =>
                if wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_REMW) := '1';
                else
                    w_error := '1';
                end if;
            when "111" =>
                if wb_instr(31 downto 25) = "0000001" then
                    wb_dec(Instr_REMUW) := '1';
                else
                    w_error := '1';
                end if;
            when others =>
                w_error := '1';
            end case;
        when OPCODE_AUIPC =>
            wb_isa_type(ISA_U_type) := '1';
            wb_dec(Instr_AUIPC) := '1';
        when OPCODE_BEQ =>
            wb_isa_type(ISA_SB_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_BEQ) := '1';
            when "001" =>
                wb_dec(Instr_BNE) := '1';
            when "100" =>
                wb_dec(Instr_BLT) := '1';
            when "101" =>
                wb_dec(Instr_BGE) := '1';
            when "110" =>
                wb_dec(Instr_BLTU) := '1';
            when "111" =>
                wb_dec(Instr_BGEU) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_JAL =>
            wb_isa_type(ISA_UJ_type) := '1';
            wb_dec(Instr_JAL) := '1';
        when OPCODE_JALR =>
            wb_isa_type(ISA_I_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_JALR) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_LB =>
            wb_isa_type(ISA_I_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_LB) := '1';
            when "001" =>
                wb_dec(Instr_LH) := '1';
            when "010" =>
                wb_dec(Instr_LW) := '1';
            when "011" =>
                wb_dec(Instr_LD) := '1';
            when "100" =>
                wb_dec(Instr_LBU) := '1';
            when "101" =>
                wb_dec(Instr_LHU) := '1';
            when "110" =>
                wb_dec(Instr_LWU) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_LUI =>
            wb_isa_type(ISA_U_type) := '1';
            wb_dec(Instr_LUI) := '1';
        when OPCODE_SB =>
            wb_isa_type(ISA_S_type) := '1';
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_SB) := '1';
            when "001" =>
                wb_dec(Instr_SH) := '1';
            when "010" =>
                wb_dec(Instr_SW) := '1';
            when "011" =>
                wb_dec(Instr_SD) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_CSRR =>
            wb_isa_type(ISA_I_type) := '1';
            case wb_opcode2 is
            when "000" =>
                if wb_instr = X"00000073" then
                    wb_dec(Instr_ECALL) := '1';
                elsif wb_instr = X"00100073" then
                    wb_dec(Instr_EBREAK) := '1';
                elsif wb_instr = X"00200073" then
                    wb_dec(Instr_URET) := '1';
                elsif wb_instr = X"10200073" then
                    wb_dec(Instr_SRET) := '1';
                elsif wb_instr = X"20200073" then
                    wb_dec(Instr_HRET) := '1';
                elsif wb_instr = X"30200073" then
                    wb_dec(Instr_MRET) := '1';
                else
                    w_error := '1';
                end if;
            when "001" =>
                wb_dec(Instr_CSRRW) := '1';
            when "010" =>
                wb_dec(Instr_CSRRS) := '1';
            when "011" =>
                wb_dec(Instr_CSRRC) := '1';
            when "101" =>
                wb_dec(Instr_CSRRWI) := '1';
            when "110" =>
                wb_dec(Instr_CSRRSI) := '1';
            when "111" =>
                wb_dec(Instr_CSRRCI) := '1';
            when others =>
                w_error := '1';
            end case;
        when OPCODE_FENCE =>
            case wb_opcode2 is
            when "000" =>
                wb_dec(Instr_FENCE) := '1';
            when "001" =>
                wb_dec(Instr_FENCE_I) := '1';
            when others =>
                w_error := '1';
            end case;
 
        when others =>
            w_error := '1';
        end case;
        wb_instr_out := wb_instr;
    end if;
 
 
    if i_f_valid = '1' then
        v.valid := '1';
        v.pc := i_f_pc;
        v.instr := wb_instr_out;
        v.compressed := w_compressed;
 
        v.isa_type := wb_isa_type;
        v.instr_vec := wb_dec;
        v.memop_store := wb_dec(Instr_SD) or wb_dec(Instr_SW) 
                      or wb_dec(Instr_SH) or wb_dec(Instr_SB);
        v.memop_load := wb_dec(Instr_LD) or wb_dec(Instr_LW)
                or wb_dec(Instr_LH) or wb_dec(Instr_LB)
                or wb_dec(Instr_LWU) or wb_dec(Instr_LHU) 
                or wb_dec(Instr_LBU);
        v.memop_sign_ext := wb_dec(Instr_LD) or wb_dec(Instr_LW)
                or wb_dec(Instr_LH) or wb_dec(Instr_LB);
        if (wb_dec(Instr_LD) or wb_dec(Instr_SD)) = '1' then
            v.memop_size := MEMOP_8B;
        elsif (wb_dec(Instr_LW) or wb_dec(Instr_LWU) or wb_dec(Instr_SW)) = '1' then
            v.memop_size := MEMOP_4B;
        elsif (wb_dec(Instr_LH) or wb_dec(Instr_LHU) or wb_dec(Instr_SH)) = '1' then
            v.memop_size := MEMOP_2B;
        else
            v.memop_size := MEMOP_1B;
        end if;
        v.unsigned_op := wb_dec(Instr_DIVU) or wb_dec(Instr_REMU) or
                         wb_dec(Instr_DIVUW) or wb_dec(Instr_REMUW);
 
        v.rv32 := wb_dec(Instr_ADDW) or wb_dec(Instr_ADDIW) 
            or wb_dec(Instr_SLLW) or wb_dec(Instr_SLLIW) or wb_dec(Instr_SRAW)
            or wb_dec(Instr_SRAIW)
            or wb_dec(Instr_SRLW) or wb_dec(Instr_SRLIW) or wb_dec(Instr_SUBW) 
            or wb_dec(Instr_DIVW) or wb_dec(Instr_DIVUW) or wb_dec(Instr_MULW)
            or wb_dec(Instr_REMW) or wb_dec(Instr_REMUW);
 
        v.instr_unimplemented := w_error;
    elsif i_any_hold = '0' then
        v.valid := '0';
    end if;
    w_o_valid := r.valid and not i_any_hold;
 
    if i_nrst = '0' then
        v.valid := '0';
        v.pc := (others => '0');
        v.instr := (others => '0');
        v.isa_type := (others => '0');
        v.instr_vec := (others => '0');
        v.memop_store := '0';
        v.memop_load := '0';
        v.memop_sign_ext := '0';
        v.memop_size := MEMOP_1B;
        v.unsigned_op := '0';
        v.rv32 := '0';
        v.compressed := '0';
        v.instr_unimplemented := '0';
        if wb_dec = INSTR_NONE then
            v.instr_unimplemented := '1';
        end if;
    end if;
 
    o_valid <= w_o_valid;
    o_pc <= r.pc;
    o_instr <= r.instr;
    o_memop_load <= r.memop_load;
    o_memop_store <= r.memop_store;
    o_memop_sign_ext <= r.memop_sign_ext;
    o_memop_size <= r.memop_size;
    o_unsigned_op <= r.unsigned_op;
    o_rv32 <= r.rv32;
    o_compressed <= r.compressed;
    o_isa_type <= r.isa_type;
    o_instr_vec <= r.instr_vec;
    o_exception <= r.instr_unimplemented;
 
    rin <= v;
  end process;
 
  -- registers:
  regs : process(i_clk)
  begin 
     if rising_edge(i_clk) then 
        r <= rin;
     end if; 
  end process;
 
end;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.