data/full_repos/permissive/507312280/rtl/core/idex.v
1: b'%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:1: Cannot find include file: defines.v\n`include "defines.v" \n         ^~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/507312280/rtl/core,data/full_repos/permissive/507312280/defines.v\n             data/full_repos/permissive/507312280/rtl/core,data/full_repos/permissive/507312280/defines.v.v\n             data/full_repos/permissive/507312280/rtl/core,data/full_repos/permissive/507312280/defines.v.sv\n             defines.v\n             defines.v.v\n             defines.v.sv\n             obj_dir/defines.v\n             obj_dir/defines.v.v\n             obj_dir/defines.v.sv\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:9: Define or directive not defined: \'`InstBus\'\n    input wire[`InstBus] inst_i,             \n               ^~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:9: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    input wire[`InstBus] inst_i,             \n                       ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:10: Define or directive not defined: \'`InstAddrBus\'\n    input wire[`InstAddrBus] pc_i,           \n               ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:12: Define or directive not defined: \'`RegBus\'\n    input wire[`RegBus] reg_rdata1_i,        \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:13: Define or directive not defined: \'`RegBus\'\n    input wire[`RegBus] reg_rdata2_i,        \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:15: Define or directive not defined: \'`RegBus\'\n    input wire[`RegBus] csr_rdata_i,         \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:17: Define or directive not defined: \'`MemBus\'\n    input wire[`MemBus] mem_rdata_i,         \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:19: Define or directive not defined: \'`RegBus\'\n    output reg[`RegBus] dividend_o,          \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:20: Define or directive not defined: \'`RegBus\'\n    output reg[`RegBus] divisor_o,           \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:22: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg div_start_o,                  \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:23: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input wire[`RegBus] div_result_i,        \n    ^~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:23: Define or directive not defined: \'`RegBus\'\n    input wire[`RegBus] div_result_i,        \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:29: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg[`RegAddrBus] reg_raddr1_o,    \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:29: Define or directive not defined: \'`RegAddrBus\'\n    output reg[`RegAddrBus] reg_raddr1_o,    \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:30: Define or directive not defined: \'`RegAddrBus\'\n    output reg[`RegAddrBus] reg_raddr2_o,    \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:31: Define or directive not defined: \'`RegBus\'\n    output reg[`RegBus] reg_wdata_o,         \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:33: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg[`RegAddrBus] reg_waddr_o,     \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:33: Define or directive not defined: \'`RegAddrBus\'\n    output reg[`RegAddrBus] reg_waddr_o,     \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:35: Define or directive not defined: \'`RegBus\'\n    output reg[`RegBus] csr_wdata_o,         \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:37: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg[`CsrAddrBus] csr_addr_o,      \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:37: Define or directive not defined: \'`CsrAddrBus\'\n    output reg[`CsrAddrBus] csr_addr_o,      \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:39: Define or directive not defined: \'`MemBus\'\n    output reg[`MemBus] mem_wdata_o,         \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:40: Define or directive not defined: \'`MemAddrBus\'\n    output reg[`MemAddrBus] mem_addr_o,      \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:42: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg[3:0] mem_wem_o,               \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:43: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg mem_en_o,                     \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:45: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg[`InstAddrBus] pc_n_o,         \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:45: Define or directive not defined: \'`InstAddrBus\'\n    output reg[`InstAddrBus] pc_n_o,         \n               ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:48: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg ebreak_o,                     \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:49: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg wfi_o,                        \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:50: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg inst_err_o,                   \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:51: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg idex_mret_o,                  \n    ^~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:53: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input wire[`RegBus] mepc                 \n    ^~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:53: Define or directive not defined: \'`RegBus\'\n    input wire[`RegBus] mepc                 \n               ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:62: Define or directive not defined: \'`RegBus\'\nwire [`RegBus] zimm = {27\'h0 , inst_i[19:15]}; \n      ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:62: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire [`RegBus] zimm = {27\'h0 , inst_i[19:15]}; \n             ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:63: Define or directive not defined: \'`RegBus\'\nwire signed[`RegBus] imm12i= {{20{inst_i[31]}} , inst_i[31:20]}; \n            ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:63: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire signed[`RegBus] imm12i= {{20{inst_i[31]}} , inst_i[31:20]}; \n                   ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:64: Define or directive not defined: \'`RegBus\'\nwire signed[`RegBus] imm12s= {{20{inst_i[31]}} , inst_i[31:25] , inst_i[11:7]}; \n            ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:64: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire signed[`RegBus] imm12s= {{20{inst_i[31]}} , inst_i[31:25] , inst_i[11:7]}; \n                   ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:65: Define or directive not defined: \'`RegBus\'\nwire signed[`RegBus] imm12b= {{20{inst_i[31]}} , inst_i[7], inst_i[30:25], inst_i[11:8], 1\'b0}; \n            ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:65: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire signed[`RegBus] imm12b= {{20{inst_i[31]}} , inst_i[7], inst_i[30:25], inst_i[11:8], 1\'b0}; \n                   ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:66: Define or directive not defined: \'`RegBus\'\nwire [`RegBus] imm20u= {inst_i[31:12] , 12\'h0}; \n      ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:66: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire [`RegBus] imm20u= {inst_i[31:12] , 12\'h0}; \n             ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:67: Define or directive not defined: \'`RegBus\'\nwire signed[`RegBus] imm20j= {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1\'b0}; \n            ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:67: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nwire signed[`RegBus] imm20j= {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1\'b0}; \n                   ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:72: Define or directive not defined: \'`RegBus\'\nreg [`RegBus] add1_in1; \n     ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:72: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nreg [`RegBus] add1_in1; \n            ^\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:73: Define or directive not defined: \'`RegBus\'\nreg [`RegBus] add1_in2; \n     ^~~~~~~\n%Error: data/full_repos/permissive/507312280/rtl/core/idex.v:73: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\nreg [`RegBus] add1_in2; \n            ^\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module idex(
    input wire clk,


    input wire[`InstBus] inst_i,
    input wire[`InstAddrBus] pc_i,

    input wire[`RegBus] reg_rdata1_i,
    input wire[`RegBus] reg_rdata2_i,

    input wire[`RegBus] csr_rdata_i,

    input wire[`MemBus] mem_rdata_i,

    output reg[`RegBus] dividend_o,
    output reg[`RegBus] divisor_o,
    output reg[2:0] div_op_o,
    output reg div_start_o,
    input wire[`RegBus] div_result_i,

    output reg mult_inst_o,



    output reg[`RegAddrBus] reg_raddr1_o,
    output reg[`RegAddrBus] reg_raddr2_o,
    output reg[`RegBus] reg_wdata_o,
    output reg reg_we_o,
    output reg[`RegAddrBus] reg_waddr_o,

    output reg[`RegBus] csr_wdata_o,
    output reg csr_we_o,
    output reg[`CsrAddrBus] csr_addr_o,

    output reg[`MemBus] mem_wdata_o,
    output reg[`MemAddrBus] mem_addr_o,
    output reg mem_we_o,
    output reg[3:0] mem_wem_o,
    output reg mem_en_o,

    output reg[`InstAddrBus] pc_n_o,

    output reg ecall_o,
    output reg ebreak_o,
    output reg wfi_o,
    output reg inst_err_o,
    output reg idex_mret_o,

    input wire[`RegBus] mepc

);


wire [6:0] opcode = inst_i[6:0];
wire [2:0] funct3 = inst_i[14:12];
wire [6:0] funct7 = inst_i[31:25];
wire [4:0] rd = inst_i[11:7];
wire [`RegBus] zimm = {27'h0 , inst_i[19:15]};
wire signed[`RegBus] imm12i= {{20{inst_i[31]}} , inst_i[31:20]};
wire signed[`RegBus] imm12s= {{20{inst_i[31]}} , inst_i[31:25] , inst_i[11:7]};
wire signed[`RegBus] imm12b= {{20{inst_i[31]}} , inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
wire [`RegBus] imm20u= {inst_i[31:12] , 12'h0};
wire signed[`RegBus] imm20j= {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
wire [4:0]shamt = inst_i[24:20];



reg [`RegBus] add1_in1;
reg [`RegBus] add1_in2;
wire [`RegBus] add1_res = add1_in1 + add1_in2;
reg [`RegBus] add2_in1;
reg [`RegBus] add2_in2;
wire [`RegBus] add2_res = add2_in1 + add2_in2;

reg signed[32:0] mul_in1,mul_in1r;
reg signed[32:0] mul_in2,mul_in2r;
wire signed[65:0]mul_res;
assign mul_res=mul_in1r*mul_in2r;
always @(posedge clk) begin
    mul_in1r <= mul_in1;
    mul_in2r <= mul_in2;
end

wire [`RegBus]mul_resl=mul_res[31: 0];
wire [`RegBus]mul_resh=mul_res[63:32];

reg [`RegBus] opr_in1;
reg [`RegBus] opr_in2;
wire opr_sres = $signed(opr_in1) >= $signed(opr_in2);
wire opr_ures = opr_in1 >= opr_in2;
wire opr_eres = (opr_in1 == opr_in2);

reg [`RegBus] opi_in1;
reg [`RegBus] opi_in2;
wire opi_sres = $signed(opi_in1) >= $signed(opi_in2);
wire opi_ures = opi_in1 >= opi_in2;

wire [`InstAddrBus] pc_n4 = pc_i + 4;

wire [`InstAddrBus] pc_n12b = pc_i + imm12b;


always @ (*) begin

    dividend_o = reg_rdata1_i;
    divisor_o = reg_rdata2_i;
    div_op_o = funct3;
    div_start_o = 0;
    reg_wdata_o = {32{1'bx}};
    reg_we_o = 0;
    reg_waddr_o = {5{1'bx}};
    csr_wdata_o = {32{1'bx}};
    csr_we_o = 0;
    csr_addr_o = {12{1'bx}};
    mem_wdata_o = {32{1'bx}};
    mem_addr_o = {32{1'bx}};
    mem_we_o = 0;
    mem_wem_o = 4'h0;
    mem_en_o = 0;
    pc_n_o = 0;
    ecall_o = 0;
    ebreak_o = 0;
    wfi_o = 0;
    inst_err_o = 0;
    idex_mret_o = 0;
    mult_inst_o = 0;

    add1_in1 = {32{1'bx}};
    add1_in2 = {32{1'bx}};
    add2_in1 = {32{1'bx}};
    add2_in2 = {32{1'bx}};
    opr_in1 = reg_rdata1_i;
    opr_in2 = reg_rdata2_i;
    opi_in1 = reg_rdata1_i;
    opi_in2 = imm12i;

    reg_raddr1_o = inst_i[19:15];
    reg_raddr2_o = inst_i[24:20];
    case (opcode)
        `INST_TYPE_I: begin
            case (funct3)
                `INST_ADDI: begin
                    add1_in1 = reg_rdata1_i;
                    add1_in2 = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = add1_res;
                    pc_n_o = pc_n4;
                end
                `INST_SLTI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = {31'h0 , (~opi_sres)};
                    pc_n_o = pc_n4;
                end
                `INST_SLTIU: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = {31'h0 , (~opi_ures)};
                    pc_n_o = pc_n4;
                end
                `INST_XORI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i ^ imm12i;
                    pc_n_o = pc_n4;
                end
                `INST_ORI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i | imm12i;

                    pc_n_o = pc_n4;
                end
                `INST_ANDI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i & imm12i;
                    pc_n_o = pc_n4;
                end
                `INST_SLLI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i << imm12i[4:0];
                    pc_n_o = pc_n4;
                end
                `INST_SRI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (inst_i[30] == 1'b1) begin
                        reg_wdata_o = (reg_rdata1_i >> shamt) | ({32{reg_rdata1_i[31]}} & (~(32'hffffffff >> shamt)));
                    end else begin
                        reg_wdata_o = reg_rdata1_i >> shamt;
                    end
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_R_M: begin
            case (funct7)
                7'b0000000: begin
                    case (funct3)
                        `INST_ADD: begin
                            add1_in1 = reg_rdata1_i;
                            add1_in2 = reg_rdata2_i;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = add1_res;
                            pc_n_o = pc_n4;
                        end
                        `INST_SLL: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i << reg_rdata2_i[4:0];
                            pc_n_o = pc_n4;
                        end
                        `INST_SLT: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = {31'h0 , (~opr_sres)};
                            pc_n_o = pc_n4;
                        end
                        `INST_SLTU: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = {31'h0 , (~opr_ures)};
                            pc_n_o = pc_n4;
                        end
                        `INST_XOR: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i ^ reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_SRL: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i >> reg_rdata2_i[4:0];
                            pc_n_o = pc_n4;
                        end
                        `INST_OR: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i | reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_AND: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i & reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        default: begin
                            inst_err_o = 1;
                        end
                    endcase
                end
                7'b0100000: begin
                    case (funct3)
                        `INST_SUB: begin
                            add1_in1 = reg_rdata1_i;
                            add1_in2 = reg_rdata2_i;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i - reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_SRA: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = (reg_rdata1_i >> reg_rdata2_i[4:0]) | ({32{reg_rdata1_i[31]}} & (~(32'hffffffff >> reg_rdata2_i[4:0])));
                            pc_n_o = pc_n4;
                        end
                    endcase
                end
`ifdef RV32_M_ISA
                7'b0000001: begin
                    case (funct3)
                        `INST_MUL: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resl;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULHU: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULH: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULHSU: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_DIV: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_DIVU: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_REM: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_REMU: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        default: begin
                            inst_err_o = 1;
                        end
                    endcase
                end
`endif
                default: inst_err_o = 1;
            endcase
        end

        `INST_TYPE_L: begin
            case (funct3)
                `INST_LB: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            reg_wdata_o = {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]};
                        end
                        2'b01: begin
                            reg_wdata_o = {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]};
                        end
                        2'b10: begin
                            reg_wdata_o = {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]};
                        end
                        default: begin
                            reg_wdata_o = {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]};
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_LH: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (mem_addr_o[1:0] == 2'b0) begin
                        reg_wdata_o = {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]};
                    end else begin
                        reg_wdata_o = {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]};
                    end
                    pc_n_o = pc_n4;
                end
                `INST_LW: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = mem_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_LBU: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[7:0]};
                        end
                        2'b01: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[15:8]};
                        end
                        2'b10: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[23:16]};
                        end
                        default: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[31:24]};
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_LHU: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (mem_addr_o[1:0] == 2'b0) begin
                        reg_wdata_o = {16'h0, mem_rdata_i[15:0]};
                    end else begin
                        reg_wdata_o = {16'h0, mem_rdata_i[31:16]};
                    end
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_S: begin
            case (funct3)
                `INST_SB: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            mem_wdata_o = {24'h0, reg_rdata2_i[7:0]};
                            mem_wem_o = 4'b0001;
                        end
                        2'b01: begin
                            mem_wdata_o = {16'h0, reg_rdata2_i[7:0] , 8'h0};
                            mem_wem_o = 4'b0010;
                        end
                        2'b10: begin
                            mem_wdata_o = {8'h0, reg_rdata2_i[7:0] , 16'h0};
                            mem_wem_o = 4'b0100;
                        end
                        2'b11: begin
                            mem_wdata_o = {reg_rdata2_i[7:0] , 24'h0};
                            mem_wem_o = 4'b1000;
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_SH: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    if (mem_addr_o[1:0]==2'b00) begin
                            mem_wdata_o = {16'h0, reg_rdata2_i[15:0]};
                            mem_wem_o = 4'b0011;
                    end else begin
                            mem_wdata_o = {reg_rdata2_i[15:0],16'h0};
                            mem_wem_o = 4'b1100;
                    end
                    pc_n_o = pc_n4;
                end
                `INST_SW: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    mem_wdata_o = reg_rdata2_i;
                    mem_wem_o = 4'b1111;
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_B: begin
            case (funct3)
                `INST_BEQ: begin
                    pc_n_o = opr_eres? pc_n12b : pc_n4;
                end
                `INST_BNE: begin
                    pc_n_o = (~opr_eres)? pc_n12b : pc_n4;
                end
                `INST_BLT: begin
                    pc_n_o = (~opr_sres)? pc_n12b : pc_n4;
                end
                `INST_BGE: begin
                    pc_n_o = opr_sres? pc_n12b : pc_n4;
                end
                `INST_BLTU: begin
                    pc_n_o = (~opr_ures)? pc_n12b : pc_n4;
                end
                `INST_BGEU: begin
                    pc_n_o = opr_ures? pc_n12b : pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end
        `INST_JAL: begin
            add1_in1 = pc_i;
            add1_in2 = 4;
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = add1_res;
            add2_in1 = pc_i;
            add2_in2 = imm20j;
            pc_n_o = add2_res;
        end
        `INST_JALR: begin
            add1_in1 = pc_i;
            add1_in2 = 4;
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = add1_res;
            add2_in1 = reg_rdata1_i;
            add2_in2 = imm12i;
            pc_n_o = add2_res;
        end
        `INST_LUI: begin
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = imm20u;
            pc_n_o = pc_n4;
        end
        `INST_AUIPC: begin
            reg_we_o = 1;
            reg_waddr_o = rd;
            add1_in1 = pc_i;
            add1_in2 = imm20u;
            reg_wdata_o = add1_res;
            pc_n_o = pc_n4;
        end
        `INST_NOP_OP: begin
            pc_n_o = pc_n4;
        end
        `INST_FENCE: begin
            pc_n_o = pc_n4;
        end

        `INST_SYS: begin
            case (funct3)
                `INST_CSRRW: begin
                    csr_wdata_o = reg_rdata1_i;
                    csr_we_o = 1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRS: begin
                    csr_wdata_o = reg_rdata1_i | csr_rdata_i;
                    csr_we_o = (reg_raddr1_o==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRC: begin
                    csr_wdata_o = (~reg_rdata1_i) & csr_rdata_i;
                    csr_we_o = (reg_raddr1_o==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRWI: begin
                    csr_wdata_o = zimm;
                    csr_we_o = 1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRSI: begin
                    csr_wdata_o = zimm | csr_rdata_i;
                    csr_we_o = (zimm[4:0]==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRCI: begin
                    csr_wdata_o = (~zimm) & csr_rdata_i;
                    csr_we_o = (zimm[4:0]==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_SI: begin
                    case (inst_i[31:15])
                        `INST_ECALL: begin
                            ecall_o = 1;
                            pc_n_o = pc_i;
                        end
                        `INST_EBREAK: begin
                            ebreak_o = 1;
                            pc_n_o = pc_i;
                        end
                        `INST_MRET: begin
                            csr_wdata_o = {csr_rdata_i[31:8],1'b0,csr_rdata_i[6:4],csr_rdata_i[7],csr_rdata_i[2:0]};
                            csr_we_o = 1;
                            csr_addr_o = `CSR_MSTATUS;
                            pc_n_o = mepc;
                            idex_mret_o = 1;
                        end
                        `INST_WFI: begin
                            wfi_o = 1;
                            pc_n_o = pc_i;
                        end
                        default : inst_err_o = 1;
                    endcase
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end
        default: begin
            inst_err_o = 1;
        end
    endcase
end

always @(*) begin
    case (funct3)
`ifdef RV32_M_ISA
        `INST_MUL: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {reg_rdata2_i[31] , reg_rdata2_i};
        end
        `INST_MULHU: begin
            mul_in1 = {1'b0 , reg_rdata1_i};
            mul_in2 = {1'b0 , reg_rdata2_i};
        end
        `INST_MULH: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {reg_rdata2_i[31] , reg_rdata2_i};
        end
        `INST_MULHSU: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {1'b0 , reg_rdata2_i};
        end 
`endif
        default: begin
            mul_in1 = 0;
            mul_in2 = 0;
        end
    endcase

end
endmodule
module idex(
    input wire clk,


    input wire[`InstBus] inst_i,
    input wire[`InstAddrBus] pc_i,

    input wire[`RegBus] reg_rdata1_i,
    input wire[`RegBus] reg_rdata2_i,

    input wire[`RegBus] csr_rdata_i,

    input wire[`MemBus] mem_rdata_i,

    output reg[`RegBus] dividend_o,
    output reg[`RegBus] divisor_o,
    output reg[2:0] div_op_o,
    output reg div_start_o,
    input wire[`RegBus] div_result_i,

    output reg mult_inst_o,



    output reg[`RegAddrBus] reg_raddr1_o,
    output reg[`RegAddrBus] reg_raddr2_o,
    output reg[`RegBus] reg_wdata_o,
    output reg reg_we_o,
    output reg[`RegAddrBus] reg_waddr_o,

    output reg[`RegBus] csr_wdata_o,
    output reg csr_we_o,
    output reg[`CsrAddrBus] csr_addr_o,

    output reg[`MemBus] mem_wdata_o,
    output reg[`MemAddrBus] mem_addr_o,
    output reg mem_we_o,
    output reg[3:0] mem_wem_o,
    output reg mem_en_o,

    output reg[`InstAddrBus] pc_n_o,

    output reg ecall_o,
    output reg ebreak_o,
    output reg wfi_o,
    output reg inst_err_o,
    output reg idex_mret_o,

    input wire[`RegBus] mepc

);



wire [6:0] opcode = inst_i[6:0];
wire [2:0] funct3 = inst_i[14:12];
wire [6:0] funct7 = inst_i[31:25];
wire [4:0] rd = inst_i[11:7];
wire [`RegBus] zimm = {27'h0 , inst_i[19:15]};
wire signed[`RegBus] imm12i= {{20{inst_i[31]}} , inst_i[31:20]};
wire signed[`RegBus] imm12s= {{20{inst_i[31]}} , inst_i[31:25] , inst_i[11:7]};
wire signed[`RegBus] imm12b= {{20{inst_i[31]}} , inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
wire [`RegBus] imm20u= {inst_i[31:12] , 12'h0};
wire signed[`RegBus] imm20j= {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
wire [4:0]shamt = inst_i[24:20];



reg [`RegBus] add1_in1;
reg [`RegBus] add1_in2;
wire [`RegBus] add1_res = add1_in1 + add1_in2;
reg [`RegBus] add2_in1;
reg [`RegBus] add2_in2;
wire [`RegBus] add2_res = add2_in1 + add2_in2;

reg signed[32:0] mul_in1,mul_in1r;
reg signed[32:0] mul_in2,mul_in2r;
wire signed[65:0]mul_res;
assign mul_res=mul_in1r*mul_in2r;
always @(posedge clk) begin
    mul_in1r <= mul_in1;
    mul_in2r <= mul_in2;
end

wire [`RegBus]mul_resl=mul_res[31: 0];
wire [`RegBus]mul_resh=mul_res[63:32];

reg [`RegBus] opr_in1;
reg [`RegBus] opr_in2;
wire opr_sres = $signed(opr_in1) >= $signed(opr_in2);
wire opr_ures = opr_in1 >= opr_in2;
wire opr_eres = (opr_in1 == opr_in2);

reg [`RegBus] opi_in1;
reg [`RegBus] opi_in2;
wire opi_sres = $signed(opi_in1) >= $signed(opi_in2);
wire opi_ures = opi_in1 >= opi_in2;

wire [`InstAddrBus] pc_n4 = pc_i + 4;

wire [`InstAddrBus] pc_n12b = pc_i + imm12b;


always @ (*) begin

    dividend_o = reg_rdata1_i;
    divisor_o = reg_rdata2_i;
    div_op_o = funct3;
    div_start_o = 0;
    reg_wdata_o = {32{1'bx}};
    reg_we_o = 0;
    reg_waddr_o = {5{1'bx}};
    csr_wdata_o = {32{1'bx}};
    csr_we_o = 0;
    csr_addr_o = {12{1'bx}};
    mem_wdata_o = {32{1'bx}};
    mem_addr_o = {32{1'bx}};
    mem_we_o = 0;
    mem_wem_o = 4'h0;
    mem_en_o = 0;
    pc_n_o = 0;
    ecall_o = 0;
    ebreak_o = 0;
    wfi_o = 0;
    inst_err_o = 0;
    idex_mret_o = 0;
    mult_inst_o = 0;

    add1_in1 = {32{1'bx}};
    add1_in2 = {32{1'bx}};
    add2_in1 = {32{1'bx}};
    add2_in2 = {32{1'bx}};
    opr_in1 = reg_rdata1_i;
    opr_in2 = reg_rdata2_i;
    opi_in1 = reg_rdata1_i;
    opi_in2 = imm12i;

    reg_raddr1_o = inst_i[19:15];
    reg_raddr2_o = inst_i[24:20];
    case (opcode)
        `INST_TYPE_I: begin
            case (funct3)
                `INST_ADDI: begin
                    add1_in1 = reg_rdata1_i;
                    add1_in2 = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = add1_res;
                    pc_n_o = pc_n4;
                end
                `INST_SLTI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = {31'h0 , (~opi_sres)};
                    pc_n_o = pc_n4;
                end
                `INST_SLTIU: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = {31'h0 , (~opi_ures)};
                    pc_n_o = pc_n4;
                end
                `INST_XORI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i ^ imm12i;
                    pc_n_o = pc_n4;
                end
                `INST_ORI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i | imm12i;

                    pc_n_o = pc_n4;
                end
                `INST_ANDI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i & imm12i;
                    pc_n_o = pc_n4;
                end
                `INST_SLLI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = reg_rdata1_i << imm12i[4:0];
                    pc_n_o = pc_n4;
                end
                `INST_SRI: begin
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (inst_i[30] == 1'b1) begin
                        reg_wdata_o = (reg_rdata1_i >> shamt) | ({32{reg_rdata1_i[31]}} & (~(32'hffffffff >> shamt)));
                    end else begin
                        reg_wdata_o = reg_rdata1_i >> shamt;
                    end
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_R_M: begin
            case (funct7)
                7'b0000000: begin
                    case (funct3)
                        `INST_ADD: begin
                            add1_in1 = reg_rdata1_i;
                            add1_in2 = reg_rdata2_i;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = add1_res;
                            pc_n_o = pc_n4;
                        end
                        `INST_SLL: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i << reg_rdata2_i[4:0];
                            pc_n_o = pc_n4;
                        end
                        `INST_SLT: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = {31'h0 , (~opr_sres)};
                            pc_n_o = pc_n4;
                        end
                        `INST_SLTU: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = {31'h0 , (~opr_ures)};
                            pc_n_o = pc_n4;
                        end
                        `INST_XOR: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i ^ reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_SRL: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i >> reg_rdata2_i[4:0];
                            pc_n_o = pc_n4;
                        end
                        `INST_OR: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i | reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_AND: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i & reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        default: begin
                            inst_err_o = 1;
                        end
                    endcase
                end
                7'b0100000: begin
                    case (funct3)
                        `INST_SUB: begin
                            add1_in1 = reg_rdata1_i;
                            add1_in2 = reg_rdata2_i;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = reg_rdata1_i - reg_rdata2_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_SRA: begin
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = (reg_rdata1_i >> reg_rdata2_i[4:0]) | ({32{reg_rdata1_i[31]}} & (~(32'hffffffff >> reg_rdata2_i[4:0])));
                            pc_n_o = pc_n4;
                        end
                    endcase
                end
`ifdef RV32_M_ISA
                7'b0000001: begin
                    case (funct3)
                        `INST_MUL: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resl;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULHU: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULH: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_MULHSU: begin
                            mult_inst_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = mul_resh;
                            pc_n_o = pc_n4;
                        end
                        `INST_DIV: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_DIVU: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_REM: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        `INST_REMU: begin
                            div_start_o = 1;
                            reg_we_o = 1;
                            reg_waddr_o = rd;
                            reg_wdata_o = div_result_i;
                            pc_n_o = pc_n4;
                        end
                        default: begin
                            inst_err_o = 1;
                        end
                    endcase
                end
`endif
                default: inst_err_o = 1;
            endcase
        end

        `INST_TYPE_L: begin
            case (funct3)
                `INST_LB: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            reg_wdata_o = {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]};
                        end
                        2'b01: begin
                            reg_wdata_o = {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]};
                        end
                        2'b10: begin
                            reg_wdata_o = {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]};
                        end
                        default: begin
                            reg_wdata_o = {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]};
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_LH: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (mem_addr_o[1:0] == 2'b0) begin
                        reg_wdata_o = {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]};
                    end else begin
                        reg_wdata_o = {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]};
                    end
                    pc_n_o = pc_n4;
                end
                `INST_LW: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = mem_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_LBU: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[7:0]};
                        end
                        2'b01: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[15:8]};
                        end
                        2'b10: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[23:16]};
                        end
                        default: begin
                            reg_wdata_o = {24'h0, mem_rdata_i[31:24]};
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_LHU: begin
                    mem_addr_o = reg_rdata1_i + imm12i;
                    mem_we_o = 0;
                    mem_en_o = 1;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    if (mem_addr_o[1:0] == 2'b0) begin
                        reg_wdata_o = {16'h0, mem_rdata_i[15:0]};
                    end else begin
                        reg_wdata_o = {16'h0, mem_rdata_i[31:16]};
                    end
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_S: begin
            case (funct3)
                `INST_SB: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    case (mem_addr_o[1:0])
                        2'b00: begin
                            mem_wdata_o = {24'h0, reg_rdata2_i[7:0]};
                            mem_wem_o = 4'b0001;
                        end
                        2'b01: begin
                            mem_wdata_o = {16'h0, reg_rdata2_i[7:0] , 8'h0};
                            mem_wem_o = 4'b0010;
                        end
                        2'b10: begin
                            mem_wdata_o = {8'h0, reg_rdata2_i[7:0] , 16'h0};
                            mem_wem_o = 4'b0100;
                        end
                        2'b11: begin
                            mem_wdata_o = {reg_rdata2_i[7:0] , 24'h0};
                            mem_wem_o = 4'b1000;
                        end
                    endcase
                    pc_n_o = pc_n4;
                end
                `INST_SH: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    if (mem_addr_o[1:0]==2'b00) begin
                            mem_wdata_o = {16'h0, reg_rdata2_i[15:0]};
                            mem_wem_o = 4'b0011;
                    end else begin
                            mem_wdata_o = {reg_rdata2_i[15:0],16'h0};
                            mem_wem_o = 4'b1100;
                    end
                    pc_n_o = pc_n4;
                end
                `INST_SW: begin
                    mem_addr_o = reg_rdata1_i + imm12s;
                    mem_we_o = 1;
                    mem_en_o = 1;
                    mem_wdata_o = reg_rdata2_i;
                    mem_wem_o = 4'b1111;
                    pc_n_o = pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end

        `INST_TYPE_B: begin
            case (funct3)
                `INST_BEQ: begin
                    pc_n_o = opr_eres? pc_n12b : pc_n4;
                end
                `INST_BNE: begin
                    pc_n_o = (~opr_eres)? pc_n12b : pc_n4;
                end
                `INST_BLT: begin
                    pc_n_o = (~opr_sres)? pc_n12b : pc_n4;
                end
                `INST_BGE: begin
                    pc_n_o = opr_sres? pc_n12b : pc_n4;
                end
                `INST_BLTU: begin
                    pc_n_o = (~opr_ures)? pc_n12b : pc_n4;
                end
                `INST_BGEU: begin
                    pc_n_o = opr_ures? pc_n12b : pc_n4;
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end
        `INST_JAL: begin
            add1_in1 = pc_i;
            add1_in2 = 4;
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = add1_res;
            add2_in1 = pc_i;
            add2_in2 = imm20j;
            pc_n_o = add2_res;
        end
        `INST_JALR: begin
            add1_in1 = pc_i;
            add1_in2 = 4;
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = add1_res;
            add2_in1 = reg_rdata1_i;
            add2_in2 = imm12i;
            pc_n_o = add2_res;
        end
        `INST_LUI: begin
            reg_we_o = 1;
            reg_waddr_o = rd;
            reg_wdata_o = imm20u;
            pc_n_o = pc_n4;
        end
        `INST_AUIPC: begin
            reg_we_o = 1;
            reg_waddr_o = rd;
            add1_in1 = pc_i;
            add1_in2 = imm20u;
            reg_wdata_o = add1_res;
            pc_n_o = pc_n4;
        end
        `INST_NOP_OP: begin
            pc_n_o = pc_n4;
        end
        `INST_FENCE: begin
            pc_n_o = pc_n4;
        end

        `INST_SYS: begin
            case (funct3)
                `INST_CSRRW: begin
                    csr_wdata_o = reg_rdata1_i;
                    csr_we_o = 1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRS: begin
                    csr_wdata_o = reg_rdata1_i | csr_rdata_i;
                    csr_we_o = (reg_raddr1_o==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRC: begin
                    csr_wdata_o = (~reg_rdata1_i) & csr_rdata_i;
                    csr_we_o = (reg_raddr1_o==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRWI: begin
                    csr_wdata_o = zimm;
                    csr_we_o = 1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRSI: begin
                    csr_wdata_o = zimm | csr_rdata_i;
                    csr_we_o = (zimm[4:0]==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_CSRRCI: begin
                    csr_wdata_o = (~zimm) & csr_rdata_i;
                    csr_we_o = (zimm[4:0]==5'h0)?0:1;
                    csr_addr_o = imm12i;
                    reg_we_o = 1;
                    reg_waddr_o = rd;
                    reg_wdata_o = csr_rdata_i;
                    pc_n_o = pc_n4;
                end
                `INST_SI: begin
                    case (inst_i[31:15])
                        `INST_ECALL: begin
                            ecall_o = 1;
                            pc_n_o = pc_i;
                        end
                        `INST_EBREAK: begin
                            ebreak_o = 1;
                            pc_n_o = pc_i;
                        end
                        `INST_MRET: begin
                            csr_wdata_o = {csr_rdata_i[31:8],1'b0,csr_rdata_i[6:4],csr_rdata_i[7],csr_rdata_i[2:0]};
                            csr_we_o = 1;
                            csr_addr_o = `CSR_MSTATUS;
                            pc_n_o = mepc;
                            idex_mret_o = 1;
                        end
                        `INST_WFI: begin
                            wfi_o = 1;
                            pc_n_o = pc_i;
                        end
                        default : inst_err_o = 1;
                    endcase
                end
                default: begin
                    inst_err_o = 1;
                end
            endcase
        end
        default: begin
            inst_err_o = 1;
        end
    endcase
end

always @(*) begin
    case (funct3)
`ifdef RV32_M_ISA
        `INST_MUL: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {reg_rdata2_i[31] , reg_rdata2_i};
        end
        `INST_MULHU: begin
            mul_in1 = {1'b0 , reg_rdata1_i};
            mul_in2 = {1'b0 , reg_rdata2_i};
        end
        `INST_MULH: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {reg_rdata2_i[31] , reg_rdata2_i};
        end
        `INST_MULHSU: begin
            mul_in1 = {reg_rdata1_i[31] , reg_rdata1_i};
            mul_in2 = {1'b0 , reg_rdata2_i};
        end 
`endif
        default: begin
            mul_in1 = 0;
            mul_in2 = 0;
        end
    endcase

end
endmodule