/* Copyright 2019 Blue Liang, liangkangnan@163.com Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ `include "defines.v" // execute and writeback module module ex( input wire rst, // from id input wire[`InstBus] inst_i, // inst content input wire[`InstAddrBus] inst_addr_i, // inst addr input wire reg_we_i, input wire[`RegAddrBus] reg_waddr_i, input wire[`RegBus] reg1_rdata_i, // reg1 read data input wire[`RegBus] reg2_rdata_i, // reg2 read data input wire csr_we_i, input wire[`MemAddrBus] csr_waddr_i, input wire[`RegBus] csr_rdata_i, input wire int_assert_i, input wire[`InstAddrBus] int_addr_i, // from mem input wire[`MemBus] mem_rdata_i, // mem read data // from div input wire div_ready_i, input wire[`DoubleRegBus] div_result_i, input wire div_busy_i, input wire[2:0] div_op_i, input wire[`RegAddrBus] div_reg_waddr_i, // to mem output reg[`MemBus] mem_wdata_o, // mem write data output reg[`MemAddrBus] mem_raddr_o, // mem read addr output reg[`MemAddrBus] mem_waddr_o, // mem write addr output wire mem_we_o, // mem write enable output wire mem_req_o, // to regs output wire[`RegBus] reg_wdata_o, // reg write data output wire reg_we_o, // reg write enable output wire[`RegAddrBus] reg_waddr_o, // reg write addr // to csr reg output reg[`RegBus] csr_wdata_o, // reg write data output wire csr_we_o, // reg write enable output wire[`MemAddrBus] csr_waddr_o, // to div output reg div_start_o, output reg[`RegBus] div_dividend_o, output reg[`RegBus] div_divisor_o, output reg[2:0] div_op_o, output reg[`RegAddrBus] div_reg_waddr_o, // to ctrl output wire hold_flag_o, output wire jump_flag_o, // whether jump or not flag output wire[`InstAddrBus] jump_addr_o // jump dest addr ); wire[31:0] sign_extend_tmp; wire[4:0] shift_bits; wire[1:0] mem_raddr_index; wire[1:0] mem_waddr_index; wire[`DoubleRegBus] mul_temp; wire[`DoubleRegBus] mul_temp_invert; reg[`RegBus] mul_op1; reg[`RegBus] mul_op2; wire[6:0] opcode; wire[2:0] funct3; wire[6:0] funct7; wire[4:0] rd; wire[4:0] uimm; reg[`RegBus] reg_wdata; reg reg_we; reg[`RegAddrBus] reg_waddr; reg[`RegBus] div_wdata; reg div_we; reg[`RegAddrBus] div_waddr; reg div_hold_flag; reg div_jump_flag; reg[`InstAddrBus] div_jump_addr; reg hold_flag; reg jump_flag; reg[`InstAddrBus] jump_addr; reg mem_we; reg mem_req; assign opcode = inst_i[6:0]; assign funct3 = inst_i[14:12]; assign funct7 = inst_i[31:25]; assign rd = inst_i[11:7]; assign uimm = inst_i[19:15]; assign sign_extend_tmp = {{20{inst_i[31]}}, inst_i[31:20]}; assign shift_bits = inst_i[24:20]; assign mul_temp = mul_op1 * mul_op2; assign mul_temp_invert = ~mul_temp + 1; assign mem_raddr_index = ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) - ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 32'hfffffffc)) & 2'b11; assign mem_waddr_index = ((reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) - (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]} & 32'hfffffffc)) & 2'b11; assign reg_wdata_o = reg_wdata | div_wdata; assign reg_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: (reg_we || div_we); assign reg_waddr_o = reg_waddr | div_waddr; assign mem_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: mem_we; assign mem_req_o = (int_assert_i == `INT_ASSERT)? `RIB_NREQ: mem_req; assign hold_flag_o = hold_flag || div_hold_flag; assign jump_flag_o = jump_flag || div_jump_flag || ((int_assert_i == `INT_ASSERT)? `JumpEnable: `JumpDisable); assign jump_addr_o = (int_assert_i == `INT_ASSERT)? int_addr_i: (jump_addr | div_jump_addr); assign csr_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: csr_we_i; assign csr_waddr_o = csr_waddr_i; // handle mul always @ (*) begin if (rst == `RstEnable) begin mul_op1 <= `ZeroWord; mul_op2 <= `ZeroWord; end else begin if ((opcode == `INST_TYPE_R_M) && (funct7 == 7'b0000001)) begin case (funct3) `INST_MUL: begin mul_op1 <= reg1_rdata_i; mul_op2 <= reg2_rdata_i; end `INST_MULHU: begin mul_op1 <= reg1_rdata_i; mul_op2 <= reg2_rdata_i; end `INST_MULHSU: begin mul_op1 <= (reg1_rdata_i[31] == 1'b1)? (~reg1_rdata_i + 1): reg1_rdata_i; mul_op2 <= reg2_rdata_i; end `INST_MULH: begin mul_op1 <= (reg1_rdata_i[31] == 1'b1)? (~reg1_rdata_i + 1): reg1_rdata_i; mul_op2 <= (reg2_rdata_i[31] == 1'b1)? (~reg2_rdata_i + 1): reg2_rdata_i; end default: begin mul_op1 <= reg1_rdata_i; mul_op2 <= reg2_rdata_i; end endcase end else begin mul_op1 <= reg1_rdata_i; mul_op2 <= reg2_rdata_i; end end end // handle div always @ (*) begin if (rst == `RstEnable) begin div_dividend_o <= `ZeroWord; div_divisor_o <= `ZeroWord; div_op_o <= 3'b0; div_reg_waddr_o <= `ZeroWord; div_waddr <= `ZeroWord; div_hold_flag <= `HoldDisable; div_we <= `WriteDisable; div_wdata <= `ZeroWord; div_start_o <= `DivStop; div_jump_flag <= `JumpDisable; div_jump_addr <= `ZeroWord; end else begin div_dividend_o <= reg1_rdata_i; div_divisor_o <= reg2_rdata_i; div_op_o <= funct3; div_reg_waddr_o <= reg_waddr_i; if ((opcode == `INST_TYPE_R_M) && (funct7 == 7'b0000001)) begin div_we <= `WriteDisable; div_wdata <= `ZeroWord; div_waddr <= `ZeroWord; case (funct3) `INST_DIV: begin div_start_o <= `DivStart; div_jump_flag <= `JumpEnable; div_hold_flag <= `HoldEnable; div_jump_addr <= inst_addr_i + 4'h4; end `INST_DIVU: begin div_start_o <= `DivStart; div_jump_flag <= `JumpEnable; div_hold_flag <= `HoldEnable; div_jump_addr <= inst_addr_i + 4'h4; end `INST_REM: begin div_start_o <= `DivStart; div_jump_flag <= `JumpEnable; div_hold_flag <= `HoldEnable; div_jump_addr <= inst_addr_i + 4'h4; end `INST_REMU: begin div_start_o <= `DivStart; div_jump_flag <= `JumpEnable; div_hold_flag <= `HoldEnable; div_jump_addr <= inst_addr_i + 4'h4; end default: begin div_start_o <= `DivStop; div_jump_flag <= `JumpDisable; div_hold_flag <= `HoldDisable; div_jump_addr <= `ZeroWord; end endcase end else begin div_jump_flag <= `JumpDisable; div_jump_addr <= `ZeroWord; if (div_busy_i == `True) begin div_start_o <= `DivStart; div_we <= `WriteDisable; div_wdata <= `ZeroWord; div_waddr <= `ZeroWord; div_hold_flag <= `HoldEnable; end else begin div_start_o <= `DivStop; div_hold_flag <= `HoldDisable; if (div_ready_i == `DivResultReady) begin case (div_op_i) `INST_DIV: begin div_wdata <= div_result_i[31:0]; div_waddr <= div_reg_waddr_i; div_we <= `WriteEnable; end `INST_DIVU: begin div_wdata <= div_result_i[31:0]; div_waddr <= div_reg_waddr_i; div_we <= `WriteEnable; end `INST_REM: begin div_wdata <= div_result_i[63:32]; div_waddr <= div_reg_waddr_i; div_we <= `WriteEnable; end `INST_REMU: begin div_wdata <= div_result_i[63:32]; div_waddr <= div_reg_waddr_i; div_we <= `WriteEnable; end default: begin div_wdata <= `ZeroWord; div_waddr <= `ZeroWord; div_we <= `WriteDisable; end endcase end else begin div_we <= `WriteDisable; div_wdata <= `ZeroWord; div_waddr <= `ZeroWord; end end end end end always @ (*) begin if (rst == `RstEnable) begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; mem_req <= `RIB_NREQ; reg_wdata <= `ZeroWord; reg_we <= `WriteDisable; reg_waddr <= `ZeroWord; csr_wdata_o <= `ZeroWord; end else begin reg_we <= reg_we_i; reg_waddr <= reg_waddr_i; mem_req <= `RIB_NREQ; csr_wdata_o <= `ZeroWord; case (opcode) `INST_TYPE_I: begin case (funct3) `INST_ADDI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; end `INST_SLTI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b1) begin if (reg1_rdata_i < sign_extend_tmp) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end else if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b0) begin reg_wdata <= 32'h00000001; end else if (reg1_rdata_i[31] == 1'b0 && sign_extend_tmp[31] == 1'b1) begin reg_wdata <= 32'h00000000; end else begin if (reg1_rdata_i < sign_extend_tmp) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end end `INST_SLTIU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b1) begin if (reg1_rdata_i < sign_extend_tmp) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end else if (reg1_rdata_i[31] == 1'b1 && sign_extend_tmp[31] == 1'b0) begin reg_wdata <= 32'h00000000; end else if (reg1_rdata_i[31] == 1'b0 && sign_extend_tmp[31] == 1'b1) begin reg_wdata <= 32'h00000001; end else begin if (reg1_rdata_i < sign_extend_tmp) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end end `INST_XORI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i ^ {{20{inst_i[31]}}, inst_i[31:20]}; end `INST_ORI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i | {{20{inst_i[31]}}, inst_i[31:20]}; end `INST_ANDI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i & {{20{inst_i[31]}}, inst_i[31:20]}; end `INST_SLLI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i << shift_bits; end `INST_SRI: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (inst_i[30] == 1'b1) begin reg_wdata <= ({32{reg1_rdata_i[31]}} << (6'd32 - {1'b0, shift_bits})) | (reg1_rdata_i >> shift_bits); end else begin reg_wdata <= reg1_rdata_i >> shift_bits; end end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end `INST_TYPE_R_M: begin if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000)) begin case (funct3) `INST_ADD_SUB: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (inst_i[30] == 1'b0) begin reg_wdata <= reg1_rdata_i + reg2_rdata_i; end else begin reg_wdata <= reg1_rdata_i - reg2_rdata_i; end end `INST_SLL: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i << reg2_rdata_i[4:0]; end `INST_SLT: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i < reg2_rdata_i) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin reg_wdata <= 32'h00000001; end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin reg_wdata <= 32'h00000000; end else begin if (reg1_rdata_i < reg2_rdata_i) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end end `INST_SLTU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i < reg2_rdata_i) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin reg_wdata <= 32'h00000000; end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin reg_wdata <= 32'h00000001; end else begin if (reg1_rdata_i < reg2_rdata_i) begin reg_wdata <= 32'h00000001; end else begin reg_wdata <= 32'h00000000; end end end `INST_XOR: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i ^ reg2_rdata_i; end `INST_SR: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (inst_i[30] == 1'b1) begin reg_wdata <= ({32{reg1_rdata_i[31]}} << (6'd32 - {1'b0, reg2_rdata_i[4:0]})) | (reg1_rdata_i >> reg2_rdata_i[4:0]); end else begin reg_wdata <= reg1_rdata_i >> reg2_rdata_i[4:0]; end end `INST_OR: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i | reg2_rdata_i; end `INST_AND: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= reg1_rdata_i & reg2_rdata_i; end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end else if (funct7 == 7'b0000001) begin case (funct3) `INST_MUL: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= mul_temp[31:0]; end `INST_MULHU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= mul_temp[63:32]; end `INST_MULH: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if ((reg1_rdata_i[31] == 1'b0) && (reg2_rdata_i[31] == 1'b0)) begin reg_wdata <= mul_temp[63:32]; end else if ((reg1_rdata_i[31] == 1'b1) && (reg2_rdata_i[31] == 1'b1)) begin reg_wdata <= mul_temp[63:32]; end else if ((reg1_rdata_i[31] == 1'b1) && (reg2_rdata_i[31] == 1'b0)) begin reg_wdata <= mul_temp_invert[63:32]; end else begin reg_wdata <= mul_temp_invert[63:32]; end end `INST_MULHSU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; if (reg1_rdata_i[31] == 1'b1) begin reg_wdata <= mul_temp_invert[63:32]; end else begin reg_wdata <= mul_temp[63:32]; end end/* `INST_DIV: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end `INST_DIVU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end `INST_REM: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end `INST_REMU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end*/ default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end else begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end end `INST_TYPE_L: begin case (funct3) `INST_LB: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; //mem_req <= `RIB_REQ; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; if (mem_raddr_index == 2'b0) begin reg_wdata <= {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]}; end else if (mem_raddr_index == 2'b01) begin reg_wdata <= {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]}; end else if (mem_raddr_index == 2'b10) begin reg_wdata <= {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]}; end else begin reg_wdata <= {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]}; end end `INST_LH: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; //mem_req <= `RIB_REQ; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; if (mem_raddr_index == 2'b0) begin reg_wdata <= {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]}; end else begin reg_wdata <= {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]}; end end `INST_LW: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; //mem_req <= `RIB_REQ; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; reg_wdata <= mem_rdata_i; end `INST_LBU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; //mem_req <= `RIB_REQ; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; if (mem_raddr_index == 2'b0) begin reg_wdata <= {24'h0, mem_rdata_i[7:0]}; end else if (mem_raddr_index == 2'b01) begin reg_wdata <= {24'h0, mem_rdata_i[15:8]}; end else if (mem_raddr_index == 2'b10) begin reg_wdata <= {24'h0, mem_rdata_i[23:16]}; end else begin reg_wdata <= {24'h0, mem_rdata_i[31:24]}; end end `INST_LHU: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; //mem_req <= `RIB_REQ; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}; if (mem_raddr_index == 2'b0) begin reg_wdata <= {16'h0, mem_rdata_i[15:0]}; end else begin reg_wdata <= {16'h0, mem_rdata_i[31:16]}; end end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end `INST_TYPE_S: begin case (funct3) `INST_SB: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; reg_wdata <= `ZeroWord; mem_we <= `WriteEnable; mem_req <= `RIB_REQ; mem_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; if (mem_waddr_index == 2'b00) begin mem_wdata_o <= {mem_rdata_i[31:8], reg2_rdata_i[7:0]}; end else if (mem_waddr_index == 2'b01) begin mem_wdata_o <= {mem_rdata_i[31:16], reg2_rdata_i[7:0], mem_rdata_i[7:0]}; end else if (mem_waddr_index == 2'b10) begin mem_wdata_o <= {mem_rdata_i[31:24], reg2_rdata_i[7:0], mem_rdata_i[15:0]}; end else begin mem_wdata_o <= {reg2_rdata_i[7:0], mem_rdata_i[23:0]}; end end `INST_SH: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; reg_wdata <= `ZeroWord; mem_we <= `WriteEnable; mem_req <= `RIB_REQ; mem_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; if (mem_waddr_index == 2'b00) begin mem_wdata_o <= {mem_rdata_i[31:16], reg2_rdata_i[15:0]}; end else begin mem_wdata_o <= {reg2_rdata_i[15:0], mem_rdata_i[15:0]}; end end `INST_SW: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; reg_wdata <= `ZeroWord; mem_we <= `WriteEnable; mem_req <= `RIB_REQ; mem_waddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; mem_raddr_o <= reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}; mem_wdata_o <= reg2_rdata_i; end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end `INST_TYPE_B: begin case (funct3) `INST_BEQ: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i == reg2_rdata_i) begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end else begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end end `INST_BNE: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i != reg2_rdata_i) begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end else begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end end `INST_BLT: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i >= reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin if (reg1_rdata_i >= reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end end `INST_BGE: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i < reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin if (reg1_rdata_i < reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end end `INST_BLTU: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b0) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i >= reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin if (reg1_rdata_i >= reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end `INST_BGEU: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b1) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else if (reg1_rdata_i[31] == 1'b1 && reg2_rdata_i[31] == 1'b1) begin if (reg1_rdata_i < reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else if (reg1_rdata_i[31] == 1'b0 && reg2_rdata_i[31] == 1'b0) begin if (reg1_rdata_i < reg2_rdata_i) begin jump_flag <= `JumpDisable; jump_addr <= `ZeroWord; end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end else begin jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; end end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end `INST_JAL: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0}; reg_wdata <= inst_addr_i + 4'h4; end `INST_JALR: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; jump_flag <= `JumpEnable; jump_addr <= (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & (32'hfffffffe); reg_wdata <= inst_addr_i + 4'h4; end `INST_LUI: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; jump_addr <= `ZeroWord; jump_flag <= `JumpDisable; reg_wdata <= {inst_i[31:12], 12'b0}; end `INST_AUIPC: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; jump_addr <= `ZeroWord; jump_flag <= `JumpDisable; reg_wdata <= {inst_i[31:12], 12'b0} + inst_addr_i; end `INST_NOP: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end `INST_FENCE: begin hold_flag <= `HoldDisable; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; jump_flag <= `JumpEnable; jump_addr <= inst_addr_i + 4'h4; end `INST_CSR: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; case (funct3) `INST_CSRRW: begin csr_wdata_o <= reg1_rdata_i; reg_wdata <= csr_rdata_i; end `INST_CSRRS: begin csr_wdata_o <= reg1_rdata_i | csr_rdata_i; reg_wdata <= csr_rdata_i; end `INST_CSRRC: begin csr_wdata_o <= csr_rdata_i & (~reg1_rdata_i); reg_wdata <= csr_rdata_i; end `INST_CSRRWI: begin csr_wdata_o <= {27'h0, uimm}; reg_wdata <= csr_rdata_i; end `INST_CSRRSI: begin csr_wdata_o <= {27'h0, uimm} | csr_rdata_i; reg_wdata <= csr_rdata_i; end `INST_CSRRCI: begin csr_wdata_o <= (~{27'h0, uimm}) & csr_rdata_i; reg_wdata <= csr_rdata_i; end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end default: begin jump_flag <= `JumpDisable; hold_flag <= `HoldDisable; jump_addr <= `ZeroWord; mem_wdata_o <= `ZeroWord; mem_raddr_o <= `ZeroWord; mem_waddr_o <= `ZeroWord; mem_we <= `WriteDisable; reg_wdata <= `ZeroWord; end endcase end end endmodule