331 lines
21 KiB
Verilog
331 lines
21 KiB
Verilog
/*****************************************************************************\
|
|
| Copyright (C) 2021 Luke Wren |
|
|
| SPDX-License-Identifier: Apache-2.0 |
|
|
\*****************************************************************************/
|
|
|
|
`default_nettype none
|
|
|
|
module hazard3_decode #(
|
|
`include "hazard3_config.vh"
|
|
,
|
|
`include "hazard3_width_const.vh"
|
|
) (
|
|
input wire clk,
|
|
input wire rst_n,
|
|
|
|
input wire [31:0] fd_cir,
|
|
input wire [1:0] fd_cir_err,
|
|
input wire [1:0] fd_cir_vld,
|
|
output wire [1:0] df_cir_use,
|
|
output wire df_cir_lock,
|
|
output wire [W_ADDR-1:0] d_pc,
|
|
|
|
input wire debug_mode,
|
|
|
|
output wire d_starved,
|
|
input wire x_stall,
|
|
input wire f_jump_now,
|
|
input wire [W_ADDR-1:0] f_jump_target,
|
|
input wire x_jump_not_except,
|
|
|
|
output reg [W_DATA-1:0] d_imm,
|
|
output reg [W_REGADDR-1:0] d_rs1,
|
|
output reg [W_REGADDR-1:0] d_rs2,
|
|
output reg [W_REGADDR-1:0] d_rd,
|
|
output reg [W_ALUSRC-1:0] d_alusrc_a,
|
|
output reg [W_ALUSRC-1:0] d_alusrc_b,
|
|
output reg [W_ALUOP-1:0] d_aluop,
|
|
output reg [W_MEMOP-1:0] d_memop,
|
|
output reg [W_MULOP-1:0] d_mulop,
|
|
output reg d_csr_ren,
|
|
output reg d_csr_wen,
|
|
output reg [1:0] d_csr_wtype,
|
|
output reg d_csr_w_imm,
|
|
output reg [W_BCOND-1:0] d_branchcond,
|
|
output reg [W_ADDR-1:0] d_addr_offs,
|
|
output reg d_addr_is_regoffs,
|
|
output reg [W_EXCEPT-1:0] d_except,
|
|
output reg d_wfi
|
|
);
|
|
|
|
`include "rv_opcodes.vh"
|
|
`include "hazard3_ops.vh"
|
|
|
|
localparam HAVE_CSR = CSR_M_MANDATORY || CSR_M_TRAP || CSR_COUNTER;
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Expand compressed instructions
|
|
|
|
wire [31:0] d_instr;
|
|
wire d_instr_is_32bit;
|
|
wire d_invalid_16bit;
|
|
reg d_invalid_32bit;
|
|
wire d_invalid = d_invalid_16bit || d_invalid_32bit;
|
|
|
|
hazard3_instr_decompress #(
|
|
.PASSTHROUGH(!EXTENSION_C)
|
|
) decomp (
|
|
.instr_in (fd_cir),
|
|
.instr_is_32bit (d_instr_is_32bit),
|
|
.instr_out (d_instr),
|
|
.invalid (d_invalid_16bit)
|
|
);
|
|
|
|
// Decode various immmediate formats
|
|
wire [31:0] d_imm_i = {{21{d_instr[31]}}, d_instr[30:20]};
|
|
wire [31:0] d_imm_s = {{21{d_instr[31]}}, d_instr[30:25], d_instr[11:7]};
|
|
wire [31:0] d_imm_b = {{20{d_instr[31]}}, d_instr[7], d_instr[30:25], d_instr[11:8], 1'b0};
|
|
wire [31:0] d_imm_u = {d_instr[31:12], {12{1'b0}}};
|
|
wire [31:0] d_imm_j = {{12{d_instr[31]}}, d_instr[19:12], d_instr[20], d_instr[30:21], 1'b0};
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// PC/CIR control
|
|
|
|
// Must not flag bus error for a valid 16-bit instruction *followed by* an
|
|
// error, because instruction fetch errors are speculative, and can be
|
|
// flushed by e.g. a branch instruction. Note the 16 LSBs must be valid for
|
|
// us to know an instruction's size.
|
|
wire d_except_instr_bus_fault = fd_cir_vld > 2'd0 && fd_cir_err[0] ||
|
|
fd_cir_vld > 2'd1 && d_instr_is_32bit && fd_cir_err[1];
|
|
|
|
assign d_starved = ~|fd_cir_vld || fd_cir_vld[0] && d_instr_is_32bit;
|
|
wire d_stall = x_stall || d_starved;
|
|
|
|
assign df_cir_use =
|
|
d_starved || d_stall ? 2'h0 :
|
|
d_instr_is_32bit ? 2'h2 : 2'h1;
|
|
|
|
// CIR Locking is required if we successfully assert a jump request, but decode is stalled.
|
|
// (This only happens if decode stall is caused by X stall, not if fetch is starved!)
|
|
// The reason for this is that, if the CIR is not locked in, it can be trashed by
|
|
// incoming fetch data before the roadblock clears ahead of us, which will squash any other
|
|
// side effects this instruction may have besides jumping! This includes:
|
|
// - Linking for JAL
|
|
// - Mispredict recovery for branches
|
|
// Note that it is not possible to simply gate the jump request based on X stalling,
|
|
// because X stall is a function of hready, and jump request feeds haddr htrans etc.
|
|
|
|
wire jump_caused_by_d = f_jump_now && x_jump_not_except;
|
|
wire assert_cir_lock = jump_caused_by_d && d_stall;
|
|
wire deassert_cir_lock = !d_stall;
|
|
reg cir_lock_prev;
|
|
|
|
assign df_cir_lock = (cir_lock_prev && !deassert_cir_lock) || assert_cir_lock;
|
|
|
|
always @ (posedge clk or negedge rst_n)
|
|
if (!rst_n)
|
|
cir_lock_prev <= 1'b0;
|
|
else
|
|
cir_lock_prev <= df_cir_lock;
|
|
|
|
reg [W_ADDR-1:0] pc;
|
|
wire [W_ADDR-1:0] pc_next = pc + (d_instr_is_32bit ? 32'h4 : 32'h2);
|
|
assign d_pc = pc;
|
|
|
|
always @ (posedge clk or negedge rst_n) begin
|
|
if (!rst_n) begin
|
|
pc <= RESET_VECTOR;
|
|
end else begin
|
|
if ((f_jump_now && !assert_cir_lock) || (cir_lock_prev && deassert_cir_lock)) begin
|
|
pc <= f_jump_target;
|
|
`ifdef FORMAL
|
|
// Being cheeky above to save a 32 bit mux. Check that we never get an M target by mistake.
|
|
|
|
// FIXME disabled this for now -- we do sometimes see an exception taking
|
|
// place during the stall, which then leads to a different branch target
|
|
// appearing. (i.e. f_jump_now is asserted for two cycles, the first one
|
|
// from this instruction and the second from the exception; this is ok,
|
|
// because the exception will return to this branch when done.)
|
|
|
|
// if (cir_lock_prev && deassert_cir_lock)
|
|
// assert(f_jump_target == d_jump_target);
|
|
`endif
|
|
end else if (!d_stall && !df_cir_lock) begin
|
|
pc <= pc_next;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
always @ (*) begin
|
|
casez ({|EXTENSION_A, |EXTENSION_ZIFENCEI, d_instr[6:2]})
|
|
{1'bz, 1'bz, 5'b11011}: d_addr_offs = d_imm_j ; // JAL
|
|
{1'bz, 1'bz, 5'b11000}: d_addr_offs = d_imm_b ; // Branches
|
|
{1'bz, 1'bz, 5'b01000}: d_addr_offs = d_imm_s ; // Store
|
|
{1'bz, 1'bz, 5'b11001}: d_addr_offs = d_imm_i ; // JALR
|
|
{1'bz, 1'bz, 5'b00000}: d_addr_offs = d_imm_i ; // Loads
|
|
{1'b1, 1'bz, 5'b01011}: d_addr_offs = 32'h0000_0000; // Atomics
|
|
{1'bz, 1'b1, 5'b00011}: d_addr_offs = 32'h0000_0004; // Zifencei
|
|
default: d_addr_offs = 32'hxxxx_xxxx;
|
|
endcase
|
|
end
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Decode X controls
|
|
|
|
localparam X0 = {W_REGADDR{1'b0}};
|
|
|
|
always @ (*) begin
|
|
// Assign some defaults
|
|
d_rs1 = d_instr[19:15];
|
|
d_rs2 = d_instr[24:20];
|
|
d_rd = d_instr[11: 7];
|
|
d_imm = d_imm_i;
|
|
d_alusrc_a = ALUSRCA_RS1;
|
|
d_alusrc_b = ALUSRCB_RS2;
|
|
d_aluop = ALUOP_ADD;
|
|
d_memop = MEMOP_NONE;
|
|
d_mulop = M_OP_MUL;
|
|
d_csr_ren = 1'b0;
|
|
d_csr_wen = 1'b0;
|
|
d_csr_wtype = CSR_WTYPE_W;
|
|
d_csr_w_imm = 1'b0;
|
|
d_branchcond = BCOND_NEVER;
|
|
d_addr_is_regoffs = 1'b0;
|
|
d_invalid_32bit = 1'b0;
|
|
d_except = EXCEPT_NONE;
|
|
d_wfi = 1'b0;
|
|
|
|
casez (d_instr)
|
|
RV_BEQ: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_SUB; d_branchcond = BCOND_ZERO; end
|
|
RV_BNE: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_SUB; d_branchcond = BCOND_NZERO; end
|
|
RV_BLT: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_LT; d_branchcond = BCOND_NZERO; end
|
|
RV_BGE: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_LT; d_branchcond = BCOND_ZERO; end
|
|
RV_BLTU: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_LTU; d_branchcond = BCOND_NZERO; end
|
|
RV_BGEU: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_rd = X0; d_aluop = ALUOP_LTU; d_branchcond = BCOND_ZERO; end
|
|
RV_JALR: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_aluop = ALUOP_ADD; d_alusrc_a = ALUSRCA_PC; d_alusrc_b = ALUSRCB_IMM; d_imm = d_instr_is_32bit ? 32'h4 : 32'h2; end
|
|
RV_JAL: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; d_rs1 = X0; d_rs2 = X0; d_aluop = ALUOP_ADD; d_alusrc_a = ALUSRCA_PC; d_alusrc_b = ALUSRCB_IMM; d_imm = d_instr_is_32bit ? 32'h4 : 32'h2; end
|
|
RV_LUI: begin d_aluop = ALUOP_RS2; d_imm = d_imm_u; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; d_rs1 = X0; end
|
|
RV_AUIPC: begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_aluop = ALUOP_ADD; d_imm = d_imm_u; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; d_alusrc_a = ALUSRCA_PC; d_rs1 = X0; end
|
|
RV_ADDI: begin d_aluop = ALUOP_ADD; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_SLLI: begin d_aluop = ALUOP_SLL; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_SLTI: begin d_aluop = ALUOP_LT; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_SLTIU: begin d_aluop = ALUOP_LTU; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_XORI: begin d_aluop = ALUOP_XOR; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_SRLI: begin d_aluop = ALUOP_SRL; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_SRAI: begin d_aluop = ALUOP_SRA; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_ORI: begin d_aluop = ALUOP_OR; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_ANDI: begin d_aluop = ALUOP_AND; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; d_rs2 = X0; end
|
|
RV_ADD: begin d_aluop = ALUOP_ADD; end
|
|
RV_SUB: begin d_aluop = ALUOP_SUB; end
|
|
RV_SLL: begin d_aluop = ALUOP_SLL; end
|
|
RV_SLT: begin d_aluop = ALUOP_LT; end
|
|
RV_SLTU: begin d_aluop = ALUOP_LTU; end
|
|
RV_XOR: begin d_aluop = ALUOP_XOR; end
|
|
RV_SRL: begin d_aluop = ALUOP_SRL; end
|
|
RV_SRA: begin d_aluop = ALUOP_SRA; end
|
|
RV_OR: begin d_aluop = ALUOP_OR; end
|
|
RV_AND: begin d_aluop = ALUOP_AND; end
|
|
RV_LB: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LB; end
|
|
RV_LH: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LH; end
|
|
RV_LW: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LW; end
|
|
RV_LBU: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LBU; end
|
|
RV_LHU: begin d_addr_is_regoffs = 1'b1; d_rs2 = X0; d_memop = MEMOP_LHU; end
|
|
RV_SB: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SB; d_rd = X0; end
|
|
RV_SH: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SH; d_rd = X0; end
|
|
RV_SW: begin d_addr_is_regoffs = 1'b1; d_aluop = ALUOP_RS2; d_memop = MEMOP_SW; d_rd = X0; end
|
|
|
|
RV_MUL: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MUL; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MULH: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULH; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MULHSU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULHSU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MULHU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_MULHU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_DIV: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_DIV; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_DIVU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_DIVU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_REM: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REM; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_REMU: if (EXTENSION_M) begin d_aluop = ALUOP_MULDIV; d_mulop = M_OP_REMU; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_LR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_LR_W; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_SC_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_SC_W; d_aluop = ALUOP_RS2; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOSWAP_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_RS2; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOADD_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_ADD; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOXOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_XOR; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOAND_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_AND; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOOR_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_OR; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOMIN_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MIN; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOMAX_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MAX; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOMINU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MINU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_AMOMAXU_W: if (EXTENSION_A) begin d_addr_is_regoffs = 1'b1; d_memop = MEMOP_AMO; d_aluop = ALUOP_MAXU; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_SH1ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH1ADD; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_SH2ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH2ADD; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_SH3ADD: if (EXTENSION_ZBA) begin d_aluop = ALUOP_SH3ADD; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_ANDN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ANDN; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CLZ: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CLZ; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CPOP: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CPOP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CTZ: if (EXTENSION_ZBB) begin d_aluop = ALUOP_CTZ; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MAX: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MAX; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MAXU: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MAXU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MIN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MIN; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MINU: if (EXTENSION_ZBB) begin d_aluop = ALUOP_MINU; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ORC_B: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ORC_B; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ORN: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ORN; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_REV8: if (EXTENSION_ZBB) begin d_aluop = ALUOP_REV8; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ROL: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROL; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ROR: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROR; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_RORI: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ROR; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_SEXT_B: if (EXTENSION_ZBB) begin d_aluop = ALUOP_SEXT_B; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_SEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_SEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_XNOR: if (EXTENSION_ZBB) begin d_aluop = ALUOP_XNOR; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ZEXT_H: if (EXTENSION_ZBB) begin d_aluop = ALUOP_ZEXT_H; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_CLMUL: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMUL; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CLMULH: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULH; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CLMULR: if (EXTENSION_ZBC) begin d_aluop = ALUOP_CLMULR; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_BCLR: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BCLR; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BCLRI: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BCLR; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BEXT: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BEXT; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BEXTI: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BEXT; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BINV: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BINV; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BINVI: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BINV; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BSET: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BSET; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_BSETI: if (EXTENSION_ZBS) begin d_aluop = ALUOP_BSET; d_rs2 = X0; d_imm = d_imm_i; d_alusrc_b = ALUSRCB_IMM; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_PACK: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_PACK; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_PACKH: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_PACKH; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_REV_B: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_REV_B; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_UNZIP: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_UNZIP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ZIP: if (EXTENSION_ZBKB) begin d_aluop = ALUOP_ZIP; d_rs2 = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
|
|
RV_FENCE: begin d_rs2 = X0; end // NOP, note rs1/rd are zero in instruction
|
|
RV_FENCE_I: if (EXTENSION_ZIFENCEI) begin d_invalid_32bit = DEBUG_SUPPORT && debug_mode; d_branchcond = BCOND_ALWAYS; end else begin d_invalid_32bit = 1'b1; end // note rs1/rs2/rd are zero in instruction
|
|
RV_CSRRW: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CSRRS: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CSRRC: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CSRRWI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = 1'b1 ; d_csr_ren = |d_rd; d_csr_wtype = CSR_WTYPE_W; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CSRRSI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_S; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_CSRRCI: if (HAVE_CSR) begin d_imm = d_imm_i; d_csr_wen = |d_rs1; d_csr_ren = 1'b1 ; d_csr_wtype = CSR_WTYPE_C; d_csr_w_imm = 1'b1; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_ECALL: if (HAVE_CSR) begin d_except = EXCEPT_ECALL; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_EBREAK: if (HAVE_CSR) begin d_except = EXCEPT_EBREAK; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_MRET: if (HAVE_CSR) begin d_except = EXCEPT_MRET; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
RV_WFI: if (HAVE_CSR) begin d_wfi = 1'b1; d_rs2 = X0; d_rs1 = X0; d_rd = X0; end else begin d_invalid_32bit = 1'b1; end
|
|
default: begin d_invalid_32bit = 1'b1; end
|
|
endcase
|
|
|
|
if (d_invalid || d_starved || d_except_instr_bus_fault) begin
|
|
d_rs1 = {W_REGADDR{1'b0}};
|
|
d_rs2 = {W_REGADDR{1'b0}};
|
|
d_rd = {W_REGADDR{1'b0}};
|
|
d_memop = MEMOP_NONE;
|
|
d_branchcond = BCOND_NEVER;
|
|
d_csr_ren = 1'b0;
|
|
d_csr_wen = 1'b0;
|
|
d_except = EXCEPT_NONE;
|
|
d_wfi = 1'b0;
|
|
if (EXTENSION_M)
|
|
d_aluop = ALUOP_ADD;
|
|
|
|
if (d_except_instr_bus_fault)
|
|
d_except = EXCEPT_INSTR_FAULT;
|
|
else if (d_invalid && !d_starved)
|
|
d_except = EXCEPT_INSTR_ILLEGAL;
|
|
end
|
|
if (cir_lock_prev) begin
|
|
d_branchcond = BCOND_NEVER;
|
|
end
|
|
end
|
|
|
|
endmodule
|