data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v
1: b'%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:31: Cannot find include file: jedro_1_defines.v\n`include "jedro_1_defines.v" \n         ^~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v.v\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v.sv\n             jedro_1_defines.v\n             jedro_1_defines.v.v\n             jedro_1_defines.v.sv\n             obj_dir/jedro_1_defines.v\n             obj_dir/jedro_1_defines.v.v\n             obj_dir/jedro_1_defines.v.sv\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:39: Define or directive not defined: \'`DATA_WIDTH\'\n  input  wire [`DATA_WIDTH-1:0] instr_i,         \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:40: Define or directive not defined: \'`DATA_WIDTH\'\n  input  wire [`DATA_WIDTH-1:0] instr_addr_i,\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:41: Define or directive not defined: \'`DATA_WIDTH\'\n  output reg  [`DATA_WIDTH-1:0] instr_addr_ro,\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:46: Define or directive not defined: \'`DATA_WIDTH\'\n  output reg  [`DATA_WIDTH-1:0] jmp_addr_ro,\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:56: Define or directive not defined: \'`ALU_OP_WIDTH\'\n  output reg  [`ALU_OP_WIDTH-1:0]    alu_sel_ro,          \n               ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:57: Define or directive not defined: \'`REG_ADDR_WIDTH\'\n  output reg  [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_ro,  \n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:59: Define or directive not defined: \'`DATA_WIDTH\'\n  input  wire [`DATA_WIDTH-1:0]      alu_res_i,           \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:63: Define or directive not defined: \'`REG_ADDR_WIDTH\'\n  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_a_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:64: Define or directive not defined: \'`REG_ADDR_WIDTH\'\n  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_b_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:67: Define or directive not defined: \'`DATA_WIDTH\'\n  output reg  [`DATA_WIDTH-1:0]      imm_ext_ro,   \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:71: Define or directive not defined: \'`LSU_CTRL_WIDTH\'\n  output reg  [`LSU_CTRL_WIDTH-1:0]  lsu_ctrl_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:72: Define or directive not defined: \'`REG_ADDR_WIDTH\'\n  output reg  [`REG_ADDR_WIDTH-1:0]  lsu_regdest_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:76: Define or directive not defined: \'`CSR_ADDR_WIDTH\'\n  output reg  [`CSR_ADDR_WIDTH-1:0]  csr_addr_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:78: Define or directive not defined: \'`DATA_WIDTH\'\n  input  wire [`DATA_WIDTH-1:0]      csr_data_i,\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:79: Define or directive not defined: \'`CSR_UIMM_WIDTH\'\n  output reg  [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_ro,\n               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:81: Define or directive not defined: \'`CSR_WMODE_WIDTH\'\n  output reg  [`CSR_WMODE_WIDTH-1:0] csr_wmode_ro,\n               ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:91: Define or directive not defined: \'`ALU_OP_WIDTH\'\nreg [`ALU_OP_WIDTH-1:0]    alu_sel_w;\n     ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:94: Define or directive not defined: \'`REG_ADDR_WIDTH\'\nreg [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_w;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:101: Define or directive not defined: \'`REG_ADDR_WIDTH\'\nreg [`REG_ADDR_WIDTH-1:0]  rf_addr_a_w;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:102: Define or directive not defined: \'`REG_ADDR_WIDTH\'\nreg [`REG_ADDR_WIDTH-1:0]  rf_addr_b_w;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:104: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0]      imm_ext_w;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:108: Define or directive not defined: \'`REG_ADDR_WIDTH\'\nreg [`REG_ADDR_WIDTH-1:0]  lsu_regdest_w;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:112: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0]      jmp_addr_w;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:114: Define or directive not defined: \'`CSR_ADDR_WIDTH\'\nreg [`CSR_ADDR_WIDTH-1:0]  csr_addr_w;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:116: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0]      csr_temp_r;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:117: Define or directive not defined: \'`CSR_UIMM_WIDTH\'\nreg [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_w; \n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:119: Define or directive not defined: \'`CSR_WMODE_WIDTH\'\nreg [`CSR_WMODE_WIDTH-1:0] csr_wmode_w;\n     ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:122: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0]      jmp_addr_save_r;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:125: Define or directive not defined: \'`DATA_WIDTH\'\nwire [`DATA_WIDTH-1:0] I_imm_sign_extended_w;\n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:126: Define or directive not defined: \'`DATA_WIDTH\'\nwire [`DATA_WIDTH-1:0] I_shift_imm_sign_extended_w;\n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:127: Define or directive not defined: \'`DATA_WIDTH\'\nwire [`DATA_WIDTH-1:0] J_imm_sign_extended_w;\n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:128: Define or directive not defined: \'`DATA_WIDTH\'\nwire [`DATA_WIDTH-1:0] B_imm_sign_extended_w;\n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:129: Define or directive not defined: \'`DATA_WIDTH\'\nwire [`DATA_WIDTH-1:0] S_imm_sign_extended_w;\n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:132: Define or directive not defined: \'`REG_ADDR_WIDTH\'\nreg [`REG_ADDR_WIDTH-1:0] prev_dest_addr;\n     ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:237: Define or directive not defined: \'`OPCODE_BRANCH\'\n       if (opcode == `OPCODE_BRANCH) begin\n                     ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:237: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n       if (opcode == `OPCODE_BRANCH) begin\n                                   ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:268: Define or directive not defined: \'`DATA_WIDTH\'\nsign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_I_inst (.in_i(imm11_0),\n                   ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:271: Define or directive not defined: \'`DATA_WIDTH\'\nsign_extender #(.N(`DATA_WIDTH), .M(5))  sign_extender_I_shift_inst(.in_i(imm11_0[24:20]),\n                   ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:274: Define or directive not defined: \'`DATA_WIDTH\'\nsign_extender #(.N(`DATA_WIDTH), .M(21)) sign_extender_J_inst (.in_i({instr_i[31], \n                   ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:283: Define or directive not defined: \'`DATA_WIDTH\'\nsign_extender #(.N(`DATA_WIDTH), .M(13)) sign_extender_B_inst (.in_i({instr_i[31], \n                   ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:291: Define or directive not defined: \'`DATA_WIDTH\'\nsign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_S_inst (.in_i({instr_i[31:25], \n                   ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:401: Define or directive not defined: \'`CSR_WMODE_NORMAL\'\n  csr_wmode_w         = `CSR_WMODE_NORMAL;\n                        ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:401: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n  csr_wmode_w         = `CSR_WMODE_NORMAL;\n                                         ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:406: Define or directive not defined: \'`OPCODE_LOAD\'\n    {1\'b1, `OPCODE_LOAD}: begin\n           ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:406: syntax error, unexpected \'}\', expecting TYPE-IDENTIFIER\n    {1\'b1, `OPCODE_LOAD}: begin\n                       ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:407: Define or directive not defined: \'`ALU_OP_ADD\'\n        alu_sel_w          = `ALU_OP_ADD;\n                             ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:447: syntax error, unexpected \'{\'\n    {1\'b1, `OPCODE_MISCMEM}: begin \n    ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:447: Define or directive not defined: \'`OPCODE_MISCMEM\'\n    {1\'b1, `OPCODE_MISCMEM}: begin \n           ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_decoder.v:452: Define or directive not defined: \'`OPCODE_OPIMM\'\n    {1\'b1, `OPCODE_OPIMM}: begin\n           ^~~~~~~~~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module jedro_1_decoder
(
  input wire clk_i,
  input wire rstn_i,


  input  wire [`DATA_WIDTH-1:0] instr_i,
  input  wire [`DATA_WIDTH-1:0] instr_addr_i,
  output reg  [`DATA_WIDTH-1:0] instr_addr_ro,
  input  wire                  instr_valid_i,
  output reg                   use_pc_ro,
  output reg                   ready_ro,
  output reg                   jmp_instr_ro,
  output reg  [`DATA_WIDTH-1:0] jmp_addr_ro,
  output reg                   use_alu_jmp_addr_ro,


  output reg illegal_instr_ro,
  output reg ecall_ro,
  output reg ebreak_ro,


  output reg                        is_alu_write_ro,
  output reg  [`ALU_OP_WIDTH-1:0]    alu_sel_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_ro,  
  output reg                        alu_wb_ro,
  input  wire [`DATA_WIDTH-1:0]      alu_res_i,
  input  wire                       alu_ops_eq_i,
  

  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_a_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_b_ro,
  
  output reg                        is_imm_ro,
  output reg  [`DATA_WIDTH-1:0]      imm_ext_ro,


  output reg                        lsu_ctrl_valid_ro, 
  output reg  [`LSU_CTRL_WIDTH-1:0]  lsu_ctrl_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  lsu_regdest_ro,
  input  wire                       lsu_read_complete_i,


  output reg  [`CSR_ADDR_WIDTH-1:0]  csr_addr_ro,
  output reg                        csr_we_ro,
  input  wire [`DATA_WIDTH-1:0]      csr_data_i,
  output reg  [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_ro,
  output reg                        csr_uimm_we_ro,
  output reg  [`CSR_WMODE_WIDTH-1:0] csr_wmode_ro,
  output reg                        csr_mret_ro
);


reg                        use_alu_jmp_addr_w;
reg                        use_pc_w;
reg                        is_alu_write_w;
reg [`ALU_OP_WIDTH-1:0]    alu_sel_w;
reg                        alu_op_a_w;
reg                        alu_op_b_w;
reg [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_w;
reg                        alu_wb_w;

reg                        illegal_instr_w;
reg                        ecall_w;
reg                        ebreak_w;

reg [`REG_ADDR_WIDTH-1:0]  rf_addr_a_w;
reg [`REG_ADDR_WIDTH-1:0]  rf_addr_b_w;

reg [`DATA_WIDTH-1:0]      imm_ext_w;

reg                        lsu_ctrl_valid_w;
reg [3:0]                  lsu_ctrl_w;
reg [`REG_ADDR_WIDTH-1:0]  lsu_regdest_w;

reg                        ready_w;
reg                        jmp_instr_w;
reg [`DATA_WIDTH-1:0]      jmp_addr_w;

reg [`CSR_ADDR_WIDTH-1:0]  csr_addr_w;
reg                        csr_we_w;
reg [`DATA_WIDTH-1:0]      csr_temp_r;
reg [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_w; 
reg                        csr_uimm_we_w;
reg [`CSR_WMODE_WIDTH-1:0] csr_wmode_w;
reg                        csr_mret_w;

reg [`DATA_WIDTH-1:0]      jmp_addr_save_r;


wire [`DATA_WIDTH-1:0] I_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] I_shift_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] J_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] B_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] S_imm_sign_extended_w;


reg [`REG_ADDR_WIDTH-1:0] prev_dest_addr;



localparam eOK                 = 41'b00000000000000000000000000000000000000001; 
localparam eSTALL              = 41'b00000000000000000000000000000000000000010;
localparam eJAL_JMP_ADDR_CALC  = 41'b00000000000000000000000000000000000000100;
localparam eJAL_WAIT_1         = 41'b00000000000000000000000000000000000001000;
localparam eJAL_WRITE_RF_JMP   = 41'b00000000000000000000000000000000000010000;
localparam eJAL_WAIT_2         = 41'b00000000000000000000000000000000000100000;
localparam eJALR_JMP_ADDR_CALC = 41'b00000000000000000000000000000000001000000;
localparam eJALR_WAIT_1        = 41'b00000000000000000000000000000000010000000;
localparam eJALR_PC_CALC       = 41'b00000000000000000000000000000000100000000;
localparam eJALR_JMP           = 41'b00000000000000000000000000000001000000000;
localparam eJALR_WAIT_2        = 41'b00000000000000000000000000000010000000000;
localparam eBRANCH_CALC_COND   = 41'b00000000000000000000000000000100000000000;
localparam eBRANCH_CALC_ADDR   = 41'b00000000000000000000000000001000000000000;
localparam eBRANCH_STALL       = 41'b00000000000000000000000000010000000000000;
localparam eBRANCH_JUMP        = 41'b00000000000000000000000000100000000000000;
localparam eBRANCH_STALL_2     = 41'b00000000000000000000000001000000000000000;
localparam eLSU_CALC_ADDR      = 41'b00000000000000000000000010000000000000000;
localparam eLSU_STORE          = 41'b00000000000000000000000100000000000000000;
localparam eLSU_LOAD_CALC_ADDR = 41'b00000000000000000000001000000000000000000;
localparam eLSU_LOAD           = 41'b00000000000000000000010000000000000000000;
localparam eLSU_LOAD_WAIT      = 41'b00000000000000000000100000000000000000000;
localparam eCSRRW_READ_CSR     = 41'b00000000000000000001000000000000000000000;
localparam eCSRRW_READ_WAIT_0  = 41'b00000000000000000010000000000000000000000;
localparam eCSRRW_READ_WAIT_1  = 41'b00000000000000000100000000000000000000000;
localparam eCSRRW_WRITE_CSR    = 41'b00000000000000001000000000000000000000000;
localparam eCSRRW_WRITE_RF     = 41'b00000000000000010000000000000000000000000;
localparam eCSRRSC_READ_CSR    = 41'b00000000000000100000000000000000000000000;
localparam eCSRRSC_READ_WAIT_0 = 41'b00000000000001000000000000000000000000000;
localparam eCSRRSC_READ_WAIT_1 = 41'b00000000000010000000000000000000000000000;
localparam eCSRRSC_WRITE_CSR   = 41'b00000000000100000000000000000000000000000;
localparam eCSRRSC_WRITE_RF    = 41'b00000000001000000000000000000000000000000;
localparam eMRET               = 41'b00000000010000000000000000000000000000000;
localparam eMRET_WAIT          = 41'b00000000100000000000000000000000000000000;
localparam eCALL_SET_ADDR      = 41'b00000001000000000000000000000000000000000;
localparam eCALL               = 41'b00000010000000000000000000000000000000000;
localparam eCALL_WAIT          = 41'b00000100000000000000000000000000000000000;
localparam eBREAK_SET_ADDR     = 41'b00001000000000000000000000000000000000000;
localparam eBREAK              = 41'b00010000000000000000000000000000000000000;
localparam eBREAK_WAIT         = 41'b00100000000000000000000000000000000000000;
localparam eERROR              = 41'b01000000000000000000000000000000000000000;
localparam eINSTR_NOT_VALID    = 41'b10000000000000000000000000000000000000000;

reg  [40:0] state, next;


wire [6:0]   opcode; 
wire [11:7]  regdest;  
wire [31:12] imm31_12;
wire [31:20] imm11_0;
wire [14:12] funct3;
wire [19:15] regs1;
wire [24:20] regs2;



assign opcode   = instr_i[6:0];
assign regdest  = instr_i[11:7];
assign imm31_12 = instr_i[31:12];
assign imm11_0  = instr_i[31:20];
assign funct3   = instr_i[14:12];
assign regs1    = instr_i[19:15];
assign regs2    = instr_i[24:20];



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        instr_addr_ro <= 32'b0;
    end
    else begin
        instr_addr_ro <= instr_addr_i;
    end
end



always@(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        state <= eOK;
    end
    else begin
        state <= next;
    end
end




always@(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        prev_dest_addr <= 5'b00000;
    end
    else begin
       if (opcode == `OPCODE_BRANCH) begin
            prev_dest_addr <= 5'b00000;
        end
        else begin
            prev_dest_addr <= regdest;
        end 
    end
end



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        jmp_addr_save_r <= 0;
    end
    else begin
        if (state == eJALR_WAIT_1) begin
            jmp_addr_save_r <= {alu_res_i[31:1], 1'b0};
        end
        else begin
            jmp_addr_save_r <= jmp_addr_save_r;
        end
    end
end



sign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_I_inst (.in_i(imm11_0),
                                                              .out_o(I_imm_sign_extended_w));

sign_extender #(.N(`DATA_WIDTH), .M(5))  sign_extender_I_shift_inst(.in_i(imm11_0[24:20]),
                                                                  .out_o(I_shift_imm_sign_extended_w));

sign_extender #(.N(`DATA_WIDTH), .M(21)) sign_extender_J_inst (.in_i({instr_i[31], 
                                                                     instr_i[19:12], 
                                                                     instr_i[20], 
                                                                     instr_i[30:21], 
                                                                     1'b0}),
                                                               .out_o(J_imm_sign_extended_w)
                                                             );


sign_extender #(.N(`DATA_WIDTH), .M(13)) sign_extender_B_inst (.in_i({instr_i[31], 
                                                                     instr_i[7], 
                                                                     instr_i[30:25], 
                                                                     instr_i[11:8], 
                                                                     1'b0}),
                                                              .out_o(B_imm_sign_extended_w));


sign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_S_inst (.in_i({instr_i[31:25], 
                                                                     instr_i[11:7]}),
                                                              .out_o(S_imm_sign_extended_w));



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        csr_temp_r <= 0;
    end
    else begin
        if (next == eCSRRW_READ_WAIT_1 || next == eCSRRSC_READ_WAIT_1) 
            csr_temp_r <= csr_data_i;
        else 
            csr_temp_r <= csr_temp_r;
    end
end


always@(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
    use_alu_jmp_addr_ro <= 0;
    use_pc_ro <= 0;
    illegal_instr_ro <= 0;
    ecall_ro <= 0;
    ebreak_ro <= 0;
    is_alu_write_ro <= 1'b1;
    alu_sel_ro <= 0;
    alu_dest_addr_ro <= 0;
    alu_wb_ro <= 0;
    rf_addr_a_ro <= 0;
    rf_addr_b_ro <= 0;
    is_imm_ro <= 0;
    imm_ext_ro <= 0;
    lsu_ctrl_valid_ro <= 0;
    lsu_ctrl_ro <= 0;
    lsu_regdest_ro <= 0;
    ready_ro <= 1'b1;
    jmp_instr_ro <= 1'b0;
    jmp_addr_ro <= 0;
    csr_addr_ro <= 0;
    csr_uimm_data_ro <= 0;
    csr_we_ro <= 0;
    csr_uimm_we_ro <= 0;
    csr_wmode_ro <= 0;
    csr_mret_ro <= 0;
  end
  else begin
    use_alu_jmp_addr_ro <= use_alu_jmp_addr_w;
    use_pc_ro <= use_pc_w;
    illegal_instr_ro <= illegal_instr_w;
    ecall_ro <= ecall_w;
    ebreak_ro <= ebreak_w;
    is_alu_write_ro <= is_alu_write_w;
    alu_sel_ro <= alu_sel_w;
    alu_dest_addr_ro <= alu_dest_addr_w;
    alu_wb_ro <= alu_wb_w;
    rf_addr_a_ro <= rf_addr_a_w;
    rf_addr_b_ro <= rf_addr_b_w;
    is_imm_ro <= ~(alu_op_a_w & alu_op_b_w);
    imm_ext_ro <= imm_ext_w;
    lsu_ctrl_valid_ro <= lsu_ctrl_valid_w;
    lsu_ctrl_ro <= lsu_ctrl_w;
    lsu_regdest_ro <= lsu_regdest_w;
    ready_ro <= ready_w;
    jmp_instr_ro <= jmp_instr_w;
    jmp_addr_ro <= jmp_addr_w;
    csr_addr_ro <= csr_addr_w;
    csr_uimm_data_ro <= csr_uimm_data_w;
    csr_we_ro <= csr_we_w;
    csr_uimm_we_ro <= csr_uimm_we_w;
    csr_wmode_ro <= csr_wmode_w;
    csr_mret_ro <= csr_mret_w;
  end
end



always@(*)
begin 
  use_alu_jmp_addr_w  = 1'b0;
  use_pc_w            = 1'b0;
  illegal_instr_w     = 1'b0;
  ecall_w             = 1'b0;
  ebreak_w            = 1'b0;
  is_alu_write_w      = 1'b0;
  alu_sel_w           = 4'b0000;
  alu_op_a_w          = 1'b0;
  alu_op_b_w          = 1'b0;
  alu_dest_addr_w     = 5'b0;
  alu_wb_w            = 1'b0; 
  rf_addr_a_w         = 5'b00000;
  rf_addr_b_w         = 5'b00000;
  imm_ext_w           = 0; 
  lsu_ctrl_valid_w    = 1'b0;
  lsu_ctrl_w          = 4'b0000;
  lsu_regdest_w       = 5'b00000;
  ready_w             = 1'b1;
  jmp_instr_w         = 1'b0;
  jmp_addr_w          = 0;
  csr_addr_w          = 0;
  csr_we_w            = 0;
  csr_uimm_data_w     = 0;
  csr_uimm_we_w       = 0;
  csr_wmode_w         = `CSR_WMODE_NORMAL;
  csr_mret_w          = 0;
  next                = eERROR;

  casez ({instr_valid_i, opcode})
    {1'b1, `OPCODE_LOAD}: begin
        alu_sel_w          = `ALU_OP_ADD;
        rf_addr_a_w        = regs1;
        lsu_ctrl_w         = {opcode[5], funct3};
        lsu_regdest_w      = regdest;
        if (regs1 == prev_dest_addr &&
            regs1 != 0 && 
            state != eSTALL &&
            state != eLSU_LOAD_CALC_ADDR &&
            state != eLSU_LOAD &&
            state != eLSU_LOAD_WAIT) begin
            next             = eSTALL;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            ready_w          = 1'b0;
        end
        else if((state != eLSU_LOAD_CALC_ADDR &&
                 state != eLSU_LOAD &&
                 state != eLSU_LOAD_WAIT) ||
                 (state == eLSU_LOAD_WAIT &&
                  ready_ro && instr_valid_i)) begin
            next             = eLSU_LOAD_CALC_ADDR;
            alu_op_a_w       = 1'b1;
            imm_ext_w        = I_imm_sign_extended_w;
            ready_w          = 1'b0;
        end
        else if (state == eLSU_LOAD_CALC_ADDR) begin
            next             = eLSU_LOAD;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b1;
            ready_w          = 1'b0;
        end
        else begin
            next             = eLSU_LOAD_WAIT;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            ready_w          = lsu_read_complete_i;
        end
    end

    {1'b1, `OPCODE_MISCMEM}: begin 
        next = eOK;
        ready_w = 1'b1;
    end

    {1'b1, `OPCODE_OPIMM}: begin
        is_alu_write_w     = 1'b1;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        rf_addr_a_w        = regs1;
        if (funct3 == `FUNCT3_SHIFT_INSTR && 
           (imm11_0[31:25] == 0 || imm11_0[31:25] == 7'b0100000)) begin
            imm_ext_w = I_shift_imm_sign_extended_w;
            alu_sel_w = {instr_i[30], funct3};
        end
        else begin
            imm_ext_w = I_imm_sign_extended_w;
            alu_sel_w = {1'b0, funct3};
        end
        if (regs1 == prev_dest_addr && regs1 != 0 && state != eSTALL) begin
            next     = eSTALL;
            alu_wb_w = 1'b0; 
            ready_w  = 1'b0;
        end
        else begin
            next     = eOK;
            alu_wb_w = 1'b1; 
            ready_w  = 1'b1;
        end
    end

    {1'b1, `OPCODE_AUIPC}: begin
        use_pc_w           = 1'b1;
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        alu_wb_w           = 1'b1; 
        imm_ext_w          = {imm31_12, 12'b0000_0000_0000};
        ready_w            = 1'b1;
        next               = eOK;
    end

    {1'b1, `OPCODE_STORE}: begin
        alu_sel_w          = `ALU_OP_ADD;
        rf_addr_a_w        = regs1;
        rf_addr_b_w        = regs2;
        if (((regs1 == prev_dest_addr && regs1 != 0) ||
             (regs2 == prev_dest_addr && regs2 != 0)) && 
              (state != eSTALL && 
              state != eLSU_CALC_ADDR)) begin
            next             = eSTALL;
            alu_op_a_w       = 1'b0;
            alu_op_b_w       = 1'b0;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b0;
            lsu_ctrl_w       = 4'b0000;
            ready_w          = 1'b0;
        end
        else if (state != eLSU_CALC_ADDR) begin
            next             = eLSU_CALC_ADDR;
            alu_op_a_w       = 1'b1;
            alu_op_b_w       = 1'b0;
            imm_ext_w        = S_imm_sign_extended_w;
            lsu_ctrl_valid_w = 1'b0;
            lsu_ctrl_w       = 4'b0000;
            ready_w          = 1'b0;
        end
        else begin
            next             = eLSU_STORE;
            alu_op_a_w       = 1'b0;
            alu_op_b_w       = 1'b1;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b1;
            lsu_ctrl_w       = {opcode[5], funct3};
            ready_w          = 1'b1;
        end
    end
    
    {1'b1, `OPCODE_OP}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = {instr_i[30], funct3};
        alu_op_a_w         = 1'b1;
        alu_op_b_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        rf_addr_a_w        = regs1;
        rf_addr_b_w        = regs2;
        if (((regs1 == prev_dest_addr && regs1 != 0 ) || 
            (regs2 == prev_dest_addr && regs2 != 0 )) &&
             state != eSTALL) begin
            next = eSTALL;
            alu_wb_w   = 1'b0;
            ready_w    = 1'b0; 
        end
        else begin
            next = eOK;
            alu_wb_w   = 1'b1; 
            ready_w    = 1'b1; 
        end
    end

    {1'b1, `OPCODE_LUI}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        alu_wb_w           = 1'b1; 
        imm_ext_w          = {imm31_12, 12'b0000_0000_0000};
        ready_w            = 1'b1;
        next               = eOK;
    end

    {1'b1, `OPCODE_BRANCH}: begin




        if (((regs1 == prev_dest_addr && regs1 != 0 ) || 
            (regs2 == prev_dest_addr && regs2 != 0 )) &&
             state != eBRANCH_CALC_COND &&
             state != eBRANCH_CALC_ADDR &&
             state != eBRANCH_STALL &&
             state != eBRANCH_JUMP &&
             state != eBRANCH_STALL_2 &&
             state != eSTALL) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0;
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eSTALL;
        end
        else if (state != eBRANCH_CALC_COND &&
                 state != eBRANCH_CALC_ADDR &&
                 state != eBRANCH_STALL &&
                 state != eBRANCH_JUMP &&
                 state != eBRANCH_STALL_2) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0;
            alu_sel_w          = {2'b00, funct3[14:13]};
            alu_op_a_w         = 1'b1;
            alu_op_b_w         = 1'b1;
            if (funct3[12] == 1'b0) begin 
                rf_addr_a_w = regs1;
                rf_addr_b_w = regs2;
            end
            else begin
                rf_addr_a_w = regs2;
                rf_addr_b_w = regs1;
            end
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eBRANCH_CALC_COND;
        end
        else if (state == eBRANCH_CALC_COND) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b1;
            alu_sel_w          = `ALU_OP_ADD;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = regs1;
            rf_addr_b_w        = regs2;
            imm_ext_w          = B_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eBRANCH_CALC_ADDR;
        end
        else if (state == eBRANCH_CALC_ADDR) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b1;
            alu_sel_w          = `ALU_OP_ADD;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = regs1;
            rf_addr_b_w        = regs2;
            imm_ext_w          = B_imm_sign_extended_w; 
            ready_w            = 1'b0; 
            if (funct3 != 3'b000 && funct3 != 3'b001 && alu_res_i == 1 ||
               ((funct3 == 3'b101 || funct3 == 3'b111) && alu_ops_eq_i == 1'b1) ||
               (funct3 == 3'b000 && alu_ops_eq_i == 1'b1) ||
               (funct3 == 3'b001 && alu_ops_eq_i == 1'b0)) begin
                next = eBRANCH_STALL;
            end
            else begin
                next = eBRANCH_STALL_2;
            end
        end
        else if (state == eBRANCH_STALL) begin
            use_alu_jmp_addr_w = 1'b1;
            use_pc_w           = 1'b0; 
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eBRANCH_JUMP;
        end
        else begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0; 
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b1; 
            next               = eBRANCH_STALL_2;
        end
    end

    {1'b1, `OPCODE_JALR}: begin




        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        if ((regs1 == prev_dest_addr && regs1 != 0) &&
             state != eJALR_JMP_ADDR_CALC &&
             state != eJALR_WAIT_1 &&
             state != eJALR_PC_CALC &&
             state != eJALR_JMP &&
             state != eJALR_WAIT_2 &&
             state != eSTALL) begin
            use_pc_w           = 1'b0;
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eSTALL;
        end
        else if (state != eJALR_JMP_ADDR_CALC &&
            state != eJALR_WAIT_1 &&
            state != eJALR_PC_CALC &&
            state != eJALR_JMP &&
            state != eJALR_WAIT_2) begin
            use_pc_w           = 1'b0; 
            alu_op_a_w         = 1'b1;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = regs1;
            imm_ext_w          = I_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eJALR_JMP_ADDR_CALC;
        end
        else if (state == eJALR_JMP_ADDR_CALC) begin
            ready_w = 1'b0;
            next    = eJALR_WAIT_1;
        end
        else if (state == eJALR_WAIT_1) begin
            use_pc_w           = 1'b1;
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = regdest;
            alu_wb_w           = ~alu_res_i[1];
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = 32'b00000000_00000000_00000000_00000100;
            ready_w            = 1'b0; 
            next               = eJALR_PC_CALC;
        end
        else if (state == eJALR_PC_CALC) begin
            jmp_instr_w        = 1'b1;
            jmp_addr_w         = jmp_addr_save_r;
            use_pc_w           = 1'b0; 
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = I_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eJALR_JMP;
        end
        else begin
            ready_w = 0;
            next = eJALR_WAIT_2;
        end
    end

    {1'b1, `OPCODE_JAL}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        use_pc_w           = 1'b1;
        if (state != eJAL_JMP_ADDR_CALC &&
            state != eJAL_WAIT_1 &&
            state != eJAL_WRITE_RF_JMP &&
            state != eJAL_WAIT_2) begin
            imm_ext_w = J_imm_sign_extended_w;  
            alu_wb_w  = 1'b1;
            ready_w   = 1'b0;
            next      = eJAL_JMP_ADDR_CALC;
        end
        else if (state == eJAL_JMP_ADDR_CALC) begin
            ready_w = 1'b0;
            next = eJAL_WAIT_1;
        end
        else if (state == eJAL_WAIT_1) begin
            alu_wb_w        = ~alu_res_i[1];
            imm_ext_w       = 32'b00000000_00000000_00000000_00000100;  
            alu_dest_addr_w = regdest;
            jmp_instr_w     = 1'b1;
            jmp_addr_w      = {alu_res_i[31:1],1'b0};
            ready_w         = 1'b0;
            next            = eJAL_WRITE_RF_JMP;
        end
        else begin
            ready_w = 1'b1;
            next = eJAL_WAIT_2;
        end
    end

    {1'b1, `OPCODE_SYSTEM}: begin
        if (funct3 != 3'b000) begin
            if (funct3 == `CSRRW_INSTR_FUNCT3  |
                funct3 == `CSRRWI_INSTR_FUNCT3) begin
                csr_addr_w = imm11_0;
                if (state != eCSRRW_READ_CSR &&
                    state != eCSRRW_READ_WAIT_0 &&
                    state != eCSRRW_READ_WAIT_1 &&
                    state != eCSRRW_WRITE_CSR &&
                    regdest != 5'b00000) begin
                    next = eCSRRW_READ_CSR;
                    ready_w    = 1'b0;
                end
                else if (state == eCSRRW_READ_CSR) begin
                    next = eCSRRW_READ_WAIT_0;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRW_READ_WAIT_0) begin

                    next = eCSRRW_READ_WAIT_1;
                    ready_w = 1'b0;
                end
                else if (regdest == 5'b00000 &&
                         prev_dest_addr == regs1) begin
                    next = eSTALL;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRW_READ_WAIT_1 ||
                         regdest == 5'b00000) begin
                    if (funct3 == `CSRRW_INSTR_FUNCT3) begin
                        rf_addr_a_w = regs1;
                        alu_op_a_w = 1'b1;
                        csr_we_w   = 1'b1;
                    end
                    else begin
                        csr_uimm_data_w = regs1;
                        csr_uimm_we_w   = 1'b1;
                    end
                    next = eCSRRW_WRITE_CSR;
                    if (regdest == 5'b00000)
                        ready_w = 1'b1;
                    else
                        ready_w = 1'b0;
                end
                else begin
                    alu_op_a_w  = 1'b1;
                    rf_addr_a_w = 5'b00000;                                   
                    is_alu_write_w  = 1'b1;
                    alu_sel_w       = `ALU_OP_ADD;
                    alu_dest_addr_w = regdest;
                    alu_wb_w        = 1'b1;
                    imm_ext_w       = csr_temp_r;
                    next            = eCSRRW_WRITE_RF;
                    ready_w         = 1'b1;
                end

            end
            else begin
                csr_addr_w = imm11_0;
                if (state != eCSRRSC_READ_CSR &&
                    state != eCSRRSC_READ_WAIT_0 &&
                    state != eCSRRSC_READ_WAIT_1 &&
                    state != eCSRRSC_WRITE_CSR) begin
                    next = eCSRRSC_READ_CSR;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_CSR) begin
                    next = eCSRRSC_READ_WAIT_0;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_WAIT_0) begin
                    next = eCSRRSC_READ_WAIT_1;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_WAIT_1 &&
                         regs1 != 5'b00000) begin
                    if (funct3[12] == 1'b0)
                        csr_wmode_w = `CSR_WMODE_SET_BITS;
                    else
                        csr_wmode_w = `CSR_WMODE_CLEAR_BITS;
                    
                    if (funct3[14] == 1'b0) begin
                        alu_op_a_w = 1'b1;
                        rf_addr_a_w = regs1;
                        csr_we_w = 1'b1;
                    end
                    else begin
                        csr_uimm_data_w = regs1;
                        csr_uimm_we_w = 1'b1;
                    end
                    next = eCSRRSC_WRITE_CSR;
                    ready_w = 1'b0;
                end 
                else begin
                    alu_op_a_w  = 1'b1;
                    rf_addr_a_w = 5'b00000;
                    is_alu_write_w  = 1'b1;
                    alu_sel_w       = `ALU_OP_ADD;
                    alu_dest_addr_w = regdest;
                    alu_wb_w        = 1'b1;
                    imm_ext_w       = csr_temp_r;
                    next            = eCSRRSC_WRITE_RF;
                    ready_w         = 1'b1;
                end 
            end
        end
        else begin
            if (instr_i == `MRET_INSTR) begin
                if (state != eMRET && state != eMRET_WAIT) begin
                    csr_mret_w = 1'b1;
                    ready_w    = 1'b0;
                    next       = eMRET;
                end
                else begin
                    csr_mret_w = 1'b0;
                    ready_w    = 1'b1;
                    next       = eMRET_WAIT;
                end
            end
            else if (instr_i == `ECALL_INSTR) begin
                if (state != eCALL_SET_ADDR &&
                    state != eCALL &&
                    state != eCALL_WAIT) begin
                    ready_w = 0;
                    next = eCALL_SET_ADDR;
                end
                else if (state == eCALL_SET_ADDR) begin
                    ecall_w = 1;
                    ready_w = 0;
                    next    = eCALL;
                end
                else begin
                    ready_w = 0;
                    next    = eCALL_WAIT;
                end
            end
            else if (instr_i == `EBREAK_INSTR) begin
                if (state != eBREAK_SET_ADDR &&
                    state != eBREAK &&
                    state != eBREAK_WAIT) begin
                    ready_w = 0;
                    next = eBREAK_SET_ADDR;
                end
                else if (state == eBREAK_SET_ADDR) begin
                    ebreak_w = 1;
                    ready_w = 0;
                    next = eBREAK;
                end
                else begin
                    ready_w = 0;
                    next = eBREAK_WAIT;
                end
            end
            else if (instr_i == `WFI_INSTR) begin
                ready_w = 1'b1;
                next = eOK;
            end
            else begin
                ready_w         = 1'b0;
                illegal_instr_w = 1'b1;
                next            = eERROR;
            end
        end
    end

    {1'b0, 7'b???????}: begin
        ready_w            = 1'b1;
        illegal_instr_w    = 1'b0;
        next               = eINSTR_NOT_VALID;
    end 

    default: begin
        use_alu_jmp_addr_w = 1'b0;
        use_pc_w           = 1'b0;
        illegal_instr_w    = 1'b1;
        is_alu_write_w     = 1'b0;
        alu_sel_w          = 4'b0000;
        alu_op_a_w         = 1'b0;
        alu_op_b_w         = 1'b0;
        alu_dest_addr_w    = 5'b0;
        alu_wb_w           = 1'b0; 
        rf_addr_a_w        = 5'b00000;
        rf_addr_b_w        = 5'b00000;
        imm_ext_w          = 0;   
        lsu_ctrl_valid_w   = 1'b0;
        lsu_ctrl_w         = 4'b0000;
        lsu_regdest_w      = 5'b00000;
        csr_mret_w         = 0;
        ready_w            = 1'b0;
        jmp_instr_w        = 1'b0;
        jmp_addr_w         = 0;
        next               = eERROR;
    end
  endcase
end

endmodule
module jedro_1_decoder
(
  input wire clk_i,
  input wire rstn_i,


  input  wire [`DATA_WIDTH-1:0] instr_i,
  input  wire [`DATA_WIDTH-1:0] instr_addr_i,
  output reg  [`DATA_WIDTH-1:0] instr_addr_ro,
  input  wire                  instr_valid_i,
  output reg                   use_pc_ro,
  output reg                   ready_ro,
  output reg                   jmp_instr_ro,
  output reg  [`DATA_WIDTH-1:0] jmp_addr_ro,
  output reg                   use_alu_jmp_addr_ro,


  output reg illegal_instr_ro,
  output reg ecall_ro,
  output reg ebreak_ro,


  output reg                        is_alu_write_ro,
  output reg  [`ALU_OP_WIDTH-1:0]    alu_sel_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_ro,  
  output reg                        alu_wb_ro,
  input  wire [`DATA_WIDTH-1:0]      alu_res_i,
  input  wire                       alu_ops_eq_i,
  

  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_a_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  rf_addr_b_ro,
  
  output reg                        is_imm_ro,
  output reg  [`DATA_WIDTH-1:0]      imm_ext_ro,


  output reg                        lsu_ctrl_valid_ro, 
  output reg  [`LSU_CTRL_WIDTH-1:0]  lsu_ctrl_ro,
  output reg  [`REG_ADDR_WIDTH-1:0]  lsu_regdest_ro,
  input  wire                       lsu_read_complete_i,


  output reg  [`CSR_ADDR_WIDTH-1:0]  csr_addr_ro,
  output reg                        csr_we_ro,
  input  wire [`DATA_WIDTH-1:0]      csr_data_i,
  output reg  [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_ro,
  output reg                        csr_uimm_we_ro,
  output reg  [`CSR_WMODE_WIDTH-1:0] csr_wmode_ro,
  output reg                        csr_mret_ro
);



reg                        use_alu_jmp_addr_w;
reg                        use_pc_w;
reg                        is_alu_write_w;
reg [`ALU_OP_WIDTH-1:0]    alu_sel_w;
reg                        alu_op_a_w;
reg                        alu_op_b_w;
reg [`REG_ADDR_WIDTH-1:0]  alu_dest_addr_w;
reg                        alu_wb_w;

reg                        illegal_instr_w;
reg                        ecall_w;
reg                        ebreak_w;

reg [`REG_ADDR_WIDTH-1:0]  rf_addr_a_w;
reg [`REG_ADDR_WIDTH-1:0]  rf_addr_b_w;

reg [`DATA_WIDTH-1:0]      imm_ext_w;

reg                        lsu_ctrl_valid_w;
reg [3:0]                  lsu_ctrl_w;
reg [`REG_ADDR_WIDTH-1:0]  lsu_regdest_w;

reg                        ready_w;
reg                        jmp_instr_w;
reg [`DATA_WIDTH-1:0]      jmp_addr_w;

reg [`CSR_ADDR_WIDTH-1:0]  csr_addr_w;
reg                        csr_we_w;
reg [`DATA_WIDTH-1:0]      csr_temp_r;
reg [`CSR_UIMM_WIDTH-1:0]  csr_uimm_data_w; 
reg                        csr_uimm_we_w;
reg [`CSR_WMODE_WIDTH-1:0] csr_wmode_w;
reg                        csr_mret_w;

reg [`DATA_WIDTH-1:0]      jmp_addr_save_r;


wire [`DATA_WIDTH-1:0] I_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] I_shift_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] J_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] B_imm_sign_extended_w;
wire [`DATA_WIDTH-1:0] S_imm_sign_extended_w;


reg [`REG_ADDR_WIDTH-1:0] prev_dest_addr;



localparam eOK                 = 41'b00000000000000000000000000000000000000001; 
localparam eSTALL              = 41'b00000000000000000000000000000000000000010;
localparam eJAL_JMP_ADDR_CALC  = 41'b00000000000000000000000000000000000000100;
localparam eJAL_WAIT_1         = 41'b00000000000000000000000000000000000001000;
localparam eJAL_WRITE_RF_JMP   = 41'b00000000000000000000000000000000000010000;
localparam eJAL_WAIT_2         = 41'b00000000000000000000000000000000000100000;
localparam eJALR_JMP_ADDR_CALC = 41'b00000000000000000000000000000000001000000;
localparam eJALR_WAIT_1        = 41'b00000000000000000000000000000000010000000;
localparam eJALR_PC_CALC       = 41'b00000000000000000000000000000000100000000;
localparam eJALR_JMP           = 41'b00000000000000000000000000000001000000000;
localparam eJALR_WAIT_2        = 41'b00000000000000000000000000000010000000000;
localparam eBRANCH_CALC_COND   = 41'b00000000000000000000000000000100000000000;
localparam eBRANCH_CALC_ADDR   = 41'b00000000000000000000000000001000000000000;
localparam eBRANCH_STALL       = 41'b00000000000000000000000000010000000000000;
localparam eBRANCH_JUMP        = 41'b00000000000000000000000000100000000000000;
localparam eBRANCH_STALL_2     = 41'b00000000000000000000000001000000000000000;
localparam eLSU_CALC_ADDR      = 41'b00000000000000000000000010000000000000000;
localparam eLSU_STORE          = 41'b00000000000000000000000100000000000000000;
localparam eLSU_LOAD_CALC_ADDR = 41'b00000000000000000000001000000000000000000;
localparam eLSU_LOAD           = 41'b00000000000000000000010000000000000000000;
localparam eLSU_LOAD_WAIT      = 41'b00000000000000000000100000000000000000000;
localparam eCSRRW_READ_CSR     = 41'b00000000000000000001000000000000000000000;
localparam eCSRRW_READ_WAIT_0  = 41'b00000000000000000010000000000000000000000;
localparam eCSRRW_READ_WAIT_1  = 41'b00000000000000000100000000000000000000000;
localparam eCSRRW_WRITE_CSR    = 41'b00000000000000001000000000000000000000000;
localparam eCSRRW_WRITE_RF     = 41'b00000000000000010000000000000000000000000;
localparam eCSRRSC_READ_CSR    = 41'b00000000000000100000000000000000000000000;
localparam eCSRRSC_READ_WAIT_0 = 41'b00000000000001000000000000000000000000000;
localparam eCSRRSC_READ_WAIT_1 = 41'b00000000000010000000000000000000000000000;
localparam eCSRRSC_WRITE_CSR   = 41'b00000000000100000000000000000000000000000;
localparam eCSRRSC_WRITE_RF    = 41'b00000000001000000000000000000000000000000;
localparam eMRET               = 41'b00000000010000000000000000000000000000000;
localparam eMRET_WAIT          = 41'b00000000100000000000000000000000000000000;
localparam eCALL_SET_ADDR      = 41'b00000001000000000000000000000000000000000;
localparam eCALL               = 41'b00000010000000000000000000000000000000000;
localparam eCALL_WAIT          = 41'b00000100000000000000000000000000000000000;
localparam eBREAK_SET_ADDR     = 41'b00001000000000000000000000000000000000000;
localparam eBREAK              = 41'b00010000000000000000000000000000000000000;
localparam eBREAK_WAIT         = 41'b00100000000000000000000000000000000000000;
localparam eERROR              = 41'b01000000000000000000000000000000000000000;
localparam eINSTR_NOT_VALID    = 41'b10000000000000000000000000000000000000000;

reg  [40:0] state, next;


wire [6:0]   opcode; 
wire [11:7]  regdest;  
wire [31:12] imm31_12;
wire [31:20] imm11_0;
wire [14:12] funct3;
wire [19:15] regs1;
wire [24:20] regs2;



assign opcode   = instr_i[6:0];
assign regdest  = instr_i[11:7];
assign imm31_12 = instr_i[31:12];
assign imm11_0  = instr_i[31:20];
assign funct3   = instr_i[14:12];
assign regs1    = instr_i[19:15];
assign regs2    = instr_i[24:20];



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        instr_addr_ro <= 32'b0;
    end
    else begin
        instr_addr_ro <= instr_addr_i;
    end
end



always@(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        state <= eOK;
    end
    else begin
        state <= next;
    end
end




always@(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        prev_dest_addr <= 5'b00000;
    end
    else begin
       if (opcode == `OPCODE_BRANCH) begin
            prev_dest_addr <= 5'b00000;
        end
        else begin
            prev_dest_addr <= regdest;
        end 
    end
end



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        jmp_addr_save_r <= 0;
    end
    else begin
        if (state == eJALR_WAIT_1) begin
            jmp_addr_save_r <= {alu_res_i[31:1], 1'b0};
        end
        else begin
            jmp_addr_save_r <= jmp_addr_save_r;
        end
    end
end



sign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_I_inst (.in_i(imm11_0),
                                                              .out_o(I_imm_sign_extended_w));

sign_extender #(.N(`DATA_WIDTH), .M(5))  sign_extender_I_shift_inst(.in_i(imm11_0[24:20]),
                                                                  .out_o(I_shift_imm_sign_extended_w));

sign_extender #(.N(`DATA_WIDTH), .M(21)) sign_extender_J_inst (.in_i({instr_i[31], 
                                                                     instr_i[19:12], 
                                                                     instr_i[20], 
                                                                     instr_i[30:21], 
                                                                     1'b0}),
                                                               .out_o(J_imm_sign_extended_w)
                                                             );


sign_extender #(.N(`DATA_WIDTH), .M(13)) sign_extender_B_inst (.in_i({instr_i[31], 
                                                                     instr_i[7], 
                                                                     instr_i[30:25], 
                                                                     instr_i[11:8], 
                                                                     1'b0}),
                                                              .out_o(B_imm_sign_extended_w));


sign_extender #(.N(`DATA_WIDTH), .M(12)) sign_extender_S_inst (.in_i({instr_i[31:25], 
                                                                     instr_i[11:7]}),
                                                              .out_o(S_imm_sign_extended_w));



always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        csr_temp_r <= 0;
    end
    else begin
        if (next == eCSRRW_READ_WAIT_1 || next == eCSRRSC_READ_WAIT_1) 
            csr_temp_r <= csr_data_i;
        else 
            csr_temp_r <= csr_temp_r;
    end
end


always@(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
    use_alu_jmp_addr_ro <= 0;
    use_pc_ro <= 0;
    illegal_instr_ro <= 0;
    ecall_ro <= 0;
    ebreak_ro <= 0;
    is_alu_write_ro <= 1'b1;
    alu_sel_ro <= 0;
    alu_dest_addr_ro <= 0;
    alu_wb_ro <= 0;
    rf_addr_a_ro <= 0;
    rf_addr_b_ro <= 0;
    is_imm_ro <= 0;
    imm_ext_ro <= 0;
    lsu_ctrl_valid_ro <= 0;
    lsu_ctrl_ro <= 0;
    lsu_regdest_ro <= 0;
    ready_ro <= 1'b1;
    jmp_instr_ro <= 1'b0;
    jmp_addr_ro <= 0;
    csr_addr_ro <= 0;
    csr_uimm_data_ro <= 0;
    csr_we_ro <= 0;
    csr_uimm_we_ro <= 0;
    csr_wmode_ro <= 0;
    csr_mret_ro <= 0;
  end
  else begin
    use_alu_jmp_addr_ro <= use_alu_jmp_addr_w;
    use_pc_ro <= use_pc_w;
    illegal_instr_ro <= illegal_instr_w;
    ecall_ro <= ecall_w;
    ebreak_ro <= ebreak_w;
    is_alu_write_ro <= is_alu_write_w;
    alu_sel_ro <= alu_sel_w;
    alu_dest_addr_ro <= alu_dest_addr_w;
    alu_wb_ro <= alu_wb_w;
    rf_addr_a_ro <= rf_addr_a_w;
    rf_addr_b_ro <= rf_addr_b_w;
    is_imm_ro <= ~(alu_op_a_w & alu_op_b_w);
    imm_ext_ro <= imm_ext_w;
    lsu_ctrl_valid_ro <= lsu_ctrl_valid_w;
    lsu_ctrl_ro <= lsu_ctrl_w;
    lsu_regdest_ro <= lsu_regdest_w;
    ready_ro <= ready_w;
    jmp_instr_ro <= jmp_instr_w;
    jmp_addr_ro <= jmp_addr_w;
    csr_addr_ro <= csr_addr_w;
    csr_uimm_data_ro <= csr_uimm_data_w;
    csr_we_ro <= csr_we_w;
    csr_uimm_we_ro <= csr_uimm_we_w;
    csr_wmode_ro <= csr_wmode_w;
    csr_mret_ro <= csr_mret_w;
  end
end



always@(*)
begin 
  use_alu_jmp_addr_w  = 1'b0;
  use_pc_w            = 1'b0;
  illegal_instr_w     = 1'b0;
  ecall_w             = 1'b0;
  ebreak_w            = 1'b0;
  is_alu_write_w      = 1'b0;
  alu_sel_w           = 4'b0000;
  alu_op_a_w          = 1'b0;
  alu_op_b_w          = 1'b0;
  alu_dest_addr_w     = 5'b0;
  alu_wb_w            = 1'b0; 
  rf_addr_a_w         = 5'b00000;
  rf_addr_b_w         = 5'b00000;
  imm_ext_w           = 0; 
  lsu_ctrl_valid_w    = 1'b0;
  lsu_ctrl_w          = 4'b0000;
  lsu_regdest_w       = 5'b00000;
  ready_w             = 1'b1;
  jmp_instr_w         = 1'b0;
  jmp_addr_w          = 0;
  csr_addr_w          = 0;
  csr_we_w            = 0;
  csr_uimm_data_w     = 0;
  csr_uimm_we_w       = 0;
  csr_wmode_w         = `CSR_WMODE_NORMAL;
  csr_mret_w          = 0;
  next                = eERROR;

  casez ({instr_valid_i, opcode})
    {1'b1, `OPCODE_LOAD}: begin
        alu_sel_w          = `ALU_OP_ADD;
        rf_addr_a_w        = regs1;
        lsu_ctrl_w         = {opcode[5], funct3};
        lsu_regdest_w      = regdest;
        if (regs1 == prev_dest_addr &&
            regs1 != 0 && 
            state != eSTALL &&
            state != eLSU_LOAD_CALC_ADDR &&
            state != eLSU_LOAD &&
            state != eLSU_LOAD_WAIT) begin
            next             = eSTALL;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            ready_w          = 1'b0;
        end
        else if((state != eLSU_LOAD_CALC_ADDR &&
                 state != eLSU_LOAD &&
                 state != eLSU_LOAD_WAIT) ||
                 (state == eLSU_LOAD_WAIT &&
                  ready_ro && instr_valid_i)) begin
            next             = eLSU_LOAD_CALC_ADDR;
            alu_op_a_w       = 1'b1;
            imm_ext_w        = I_imm_sign_extended_w;
            ready_w          = 1'b0;
        end
        else if (state == eLSU_LOAD_CALC_ADDR) begin
            next             = eLSU_LOAD;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b1;
            ready_w          = 1'b0;
        end
        else begin
            next             = eLSU_LOAD_WAIT;
            alu_op_a_w       = 1'b0;
            imm_ext_w        = 0;
            ready_w          = lsu_read_complete_i;
        end
    end

    {1'b1, `OPCODE_MISCMEM}: begin 
        next = eOK;
        ready_w = 1'b1;
    end

    {1'b1, `OPCODE_OPIMM}: begin
        is_alu_write_w     = 1'b1;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        rf_addr_a_w        = regs1;
        if (funct3 == `FUNCT3_SHIFT_INSTR && 
           (imm11_0[31:25] == 0 || imm11_0[31:25] == 7'b0100000)) begin
            imm_ext_w = I_shift_imm_sign_extended_w;
            alu_sel_w = {instr_i[30], funct3};
        end
        else begin
            imm_ext_w = I_imm_sign_extended_w;
            alu_sel_w = {1'b0, funct3};
        end
        if (regs1 == prev_dest_addr && regs1 != 0 && state != eSTALL) begin
            next     = eSTALL;
            alu_wb_w = 1'b0; 
            ready_w  = 1'b0;
        end
        else begin
            next     = eOK;
            alu_wb_w = 1'b1; 
            ready_w  = 1'b1;
        end
    end

    {1'b1, `OPCODE_AUIPC}: begin
        use_pc_w           = 1'b1;
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        alu_wb_w           = 1'b1; 
        imm_ext_w          = {imm31_12, 12'b0000_0000_0000};
        ready_w            = 1'b1;
        next               = eOK;
    end

    {1'b1, `OPCODE_STORE}: begin
        alu_sel_w          = `ALU_OP_ADD;
        rf_addr_a_w        = regs1;
        rf_addr_b_w        = regs2;
        if (((regs1 == prev_dest_addr && regs1 != 0) ||
             (regs2 == prev_dest_addr && regs2 != 0)) && 
              (state != eSTALL && 
              state != eLSU_CALC_ADDR)) begin
            next             = eSTALL;
            alu_op_a_w       = 1'b0;
            alu_op_b_w       = 1'b0;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b0;
            lsu_ctrl_w       = 4'b0000;
            ready_w          = 1'b0;
        end
        else if (state != eLSU_CALC_ADDR) begin
            next             = eLSU_CALC_ADDR;
            alu_op_a_w       = 1'b1;
            alu_op_b_w       = 1'b0;
            imm_ext_w        = S_imm_sign_extended_w;
            lsu_ctrl_valid_w = 1'b0;
            lsu_ctrl_w       = 4'b0000;
            ready_w          = 1'b0;
        end
        else begin
            next             = eLSU_STORE;
            alu_op_a_w       = 1'b0;
            alu_op_b_w       = 1'b1;
            imm_ext_w        = 0;
            lsu_ctrl_valid_w = 1'b1;
            lsu_ctrl_w       = {opcode[5], funct3};
            ready_w          = 1'b1;
        end
    end
    
    {1'b1, `OPCODE_OP}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = {instr_i[30], funct3};
        alu_op_a_w         = 1'b1;
        alu_op_b_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        rf_addr_a_w        = regs1;
        rf_addr_b_w        = regs2;
        if (((regs1 == prev_dest_addr && regs1 != 0 ) || 
            (regs2 == prev_dest_addr && regs2 != 0 )) &&
             state != eSTALL) begin
            next = eSTALL;
            alu_wb_w   = 1'b0;
            ready_w    = 1'b0; 
        end
        else begin
            next = eOK;
            alu_wb_w   = 1'b1; 
            ready_w    = 1'b1; 
        end
    end

    {1'b1, `OPCODE_LUI}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        alu_op_a_w         = 1'b1;
        alu_dest_addr_w    = regdest;
        alu_wb_w           = 1'b1; 
        imm_ext_w          = {imm31_12, 12'b0000_0000_0000};
        ready_w            = 1'b1;
        next               = eOK;
    end

    {1'b1, `OPCODE_BRANCH}: begin




        if (((regs1 == prev_dest_addr && regs1 != 0 ) || 
            (regs2 == prev_dest_addr && regs2 != 0 )) &&
             state != eBRANCH_CALC_COND &&
             state != eBRANCH_CALC_ADDR &&
             state != eBRANCH_STALL &&
             state != eBRANCH_JUMP &&
             state != eBRANCH_STALL_2 &&
             state != eSTALL) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0;
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eSTALL;
        end
        else if (state != eBRANCH_CALC_COND &&
                 state != eBRANCH_CALC_ADDR &&
                 state != eBRANCH_STALL &&
                 state != eBRANCH_JUMP &&
                 state != eBRANCH_STALL_2) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0;
            alu_sel_w          = {2'b00, funct3[14:13]};
            alu_op_a_w         = 1'b1;
            alu_op_b_w         = 1'b1;
            if (funct3[12] == 1'b0) begin 
                rf_addr_a_w = regs1;
                rf_addr_b_w = regs2;
            end
            else begin
                rf_addr_a_w = regs2;
                rf_addr_b_w = regs1;
            end
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eBRANCH_CALC_COND;
        end
        else if (state == eBRANCH_CALC_COND) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b1;
            alu_sel_w          = `ALU_OP_ADD;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = regs1;
            rf_addr_b_w        = regs2;
            imm_ext_w          = B_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eBRANCH_CALC_ADDR;
        end
        else if (state == eBRANCH_CALC_ADDR) begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b1;
            alu_sel_w          = `ALU_OP_ADD;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = regs1;
            rf_addr_b_w        = regs2;
            imm_ext_w          = B_imm_sign_extended_w; 
            ready_w            = 1'b0; 
            if (funct3 != 3'b000 && funct3 != 3'b001 && alu_res_i == 1 ||
               ((funct3 == 3'b101 || funct3 == 3'b111) && alu_ops_eq_i == 1'b1) ||
               (funct3 == 3'b000 && alu_ops_eq_i == 1'b1) ||
               (funct3 == 3'b001 && alu_ops_eq_i == 1'b0)) begin
                next = eBRANCH_STALL;
            end
            else begin
                next = eBRANCH_STALL_2;
            end
        end
        else if (state == eBRANCH_STALL) begin
            use_alu_jmp_addr_w = 1'b1;
            use_pc_w           = 1'b0; 
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eBRANCH_JUMP;
        end
        else begin
            use_alu_jmp_addr_w = 1'b0;
            use_pc_w           = 1'b0; 
            alu_sel_w          = 4'b0000;
            alu_op_a_w         = 1'b0;
            alu_op_b_w         = 1'b0;
            rf_addr_a_w        = 5'b00000;
            rf_addr_b_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b1; 
            next               = eBRANCH_STALL_2;
        end
    end

    {1'b1, `OPCODE_JALR}: begin




        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        if ((regs1 == prev_dest_addr && regs1 != 0) &&
             state != eJALR_JMP_ADDR_CALC &&
             state != eJALR_WAIT_1 &&
             state != eJALR_PC_CALC &&
             state != eJALR_JMP &&
             state != eJALR_WAIT_2 &&
             state != eSTALL) begin
            use_pc_w           = 1'b0;
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = 0;   
            ready_w            = 1'b0; 
            next               = eSTALL;
        end
        else if (state != eJALR_JMP_ADDR_CALC &&
            state != eJALR_WAIT_1 &&
            state != eJALR_PC_CALC &&
            state != eJALR_JMP &&
            state != eJALR_WAIT_2) begin
            use_pc_w           = 1'b0; 
            alu_op_a_w         = 1'b1;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = regs1;
            imm_ext_w          = I_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eJALR_JMP_ADDR_CALC;
        end
        else if (state == eJALR_JMP_ADDR_CALC) begin
            ready_w = 1'b0;
            next    = eJALR_WAIT_1;
        end
        else if (state == eJALR_WAIT_1) begin
            use_pc_w           = 1'b1;
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = regdest;
            alu_wb_w           = ~alu_res_i[1];
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = 32'b00000000_00000000_00000000_00000100;
            ready_w            = 1'b0; 
            next               = eJALR_PC_CALC;
        end
        else if (state == eJALR_PC_CALC) begin
            jmp_instr_w        = 1'b1;
            jmp_addr_w         = jmp_addr_save_r;
            use_pc_w           = 1'b0; 
            alu_op_a_w         = 1'b0;
            alu_dest_addr_w    = 5'b00000;
            alu_wb_w           = 1'b0; 
            rf_addr_a_w        = 5'b00000;
            imm_ext_w          = I_imm_sign_extended_w;   
            ready_w            = 1'b0; 
            next               = eJALR_JMP;
        end
        else begin
            ready_w = 0;
            next = eJALR_WAIT_2;
        end
    end

    {1'b1, `OPCODE_JAL}: begin
        is_alu_write_w     = 1'b1;
        alu_sel_w          = `ALU_OP_ADD;
        use_pc_w           = 1'b1;
        if (state != eJAL_JMP_ADDR_CALC &&
            state != eJAL_WAIT_1 &&
            state != eJAL_WRITE_RF_JMP &&
            state != eJAL_WAIT_2) begin
            imm_ext_w = J_imm_sign_extended_w;  
            alu_wb_w  = 1'b1;
            ready_w   = 1'b0;
            next      = eJAL_JMP_ADDR_CALC;
        end
        else if (state == eJAL_JMP_ADDR_CALC) begin
            ready_w = 1'b0;
            next = eJAL_WAIT_1;
        end
        else if (state == eJAL_WAIT_1) begin
            alu_wb_w        = ~alu_res_i[1];
            imm_ext_w       = 32'b00000000_00000000_00000000_00000100;  
            alu_dest_addr_w = regdest;
            jmp_instr_w     = 1'b1;
            jmp_addr_w      = {alu_res_i[31:1],1'b0};
            ready_w         = 1'b0;
            next            = eJAL_WRITE_RF_JMP;
        end
        else begin
            ready_w = 1'b1;
            next = eJAL_WAIT_2;
        end
    end

    {1'b1, `OPCODE_SYSTEM}: begin
        if (funct3 != 3'b000) begin
            if (funct3 == `CSRRW_INSTR_FUNCT3  |
                funct3 == `CSRRWI_INSTR_FUNCT3) begin
                csr_addr_w = imm11_0;
                if (state != eCSRRW_READ_CSR &&
                    state != eCSRRW_READ_WAIT_0 &&
                    state != eCSRRW_READ_WAIT_1 &&
                    state != eCSRRW_WRITE_CSR &&
                    regdest != 5'b00000) begin
                    next = eCSRRW_READ_CSR;
                    ready_w    = 1'b0;
                end
                else if (state == eCSRRW_READ_CSR) begin
                    next = eCSRRW_READ_WAIT_0;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRW_READ_WAIT_0) begin

                    next = eCSRRW_READ_WAIT_1;
                    ready_w = 1'b0;
                end
                else if (regdest == 5'b00000 &&
                         prev_dest_addr == regs1) begin
                    next = eSTALL;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRW_READ_WAIT_1 ||
                         regdest == 5'b00000) begin
                    if (funct3 == `CSRRW_INSTR_FUNCT3) begin
                        rf_addr_a_w = regs1;
                        alu_op_a_w = 1'b1;
                        csr_we_w   = 1'b1;
                    end
                    else begin
                        csr_uimm_data_w = regs1;
                        csr_uimm_we_w   = 1'b1;
                    end
                    next = eCSRRW_WRITE_CSR;
                    if (regdest == 5'b00000)
                        ready_w = 1'b1;
                    else
                        ready_w = 1'b0;
                end
                else begin
                    alu_op_a_w  = 1'b1;
                    rf_addr_a_w = 5'b00000;                                   
                    is_alu_write_w  = 1'b1;
                    alu_sel_w       = `ALU_OP_ADD;
                    alu_dest_addr_w = regdest;
                    alu_wb_w        = 1'b1;
                    imm_ext_w       = csr_temp_r;
                    next            = eCSRRW_WRITE_RF;
                    ready_w         = 1'b1;
                end

            end
            else begin
                csr_addr_w = imm11_0;
                if (state != eCSRRSC_READ_CSR &&
                    state != eCSRRSC_READ_WAIT_0 &&
                    state != eCSRRSC_READ_WAIT_1 &&
                    state != eCSRRSC_WRITE_CSR) begin
                    next = eCSRRSC_READ_CSR;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_CSR) begin
                    next = eCSRRSC_READ_WAIT_0;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_WAIT_0) begin
                    next = eCSRRSC_READ_WAIT_1;
                    ready_w = 1'b0;
                end
                else if (state == eCSRRSC_READ_WAIT_1 &&
                         regs1 != 5'b00000) begin
                    if (funct3[12] == 1'b0)
                        csr_wmode_w = `CSR_WMODE_SET_BITS;
                    else
                        csr_wmode_w = `CSR_WMODE_CLEAR_BITS;
                    
                    if (funct3[14] == 1'b0) begin
                        alu_op_a_w = 1'b1;
                        rf_addr_a_w = regs1;
                        csr_we_w = 1'b1;
                    end
                    else begin
                        csr_uimm_data_w = regs1;
                        csr_uimm_we_w = 1'b1;
                    end
                    next = eCSRRSC_WRITE_CSR;
                    ready_w = 1'b0;
                end 
                else begin
                    alu_op_a_w  = 1'b1;
                    rf_addr_a_w = 5'b00000;
                    is_alu_write_w  = 1'b1;
                    alu_sel_w       = `ALU_OP_ADD;
                    alu_dest_addr_w = regdest;
                    alu_wb_w        = 1'b1;
                    imm_ext_w       = csr_temp_r;
                    next            = eCSRRSC_WRITE_RF;
                    ready_w         = 1'b1;
                end 
            end
        end
        else begin
            if (instr_i == `MRET_INSTR) begin
                if (state != eMRET && state != eMRET_WAIT) begin
                    csr_mret_w = 1'b1;
                    ready_w    = 1'b0;
                    next       = eMRET;
                end
                else begin
                    csr_mret_w = 1'b0;
                    ready_w    = 1'b1;
                    next       = eMRET_WAIT;
                end
            end
            else if (instr_i == `ECALL_INSTR) begin
                if (state != eCALL_SET_ADDR &&
                    state != eCALL &&
                    state != eCALL_WAIT) begin
                    ready_w = 0;
                    next = eCALL_SET_ADDR;
                end
                else if (state == eCALL_SET_ADDR) begin
                    ecall_w = 1;
                    ready_w = 0;
                    next    = eCALL;
                end
                else begin
                    ready_w = 0;
                    next    = eCALL_WAIT;
                end
            end
            else if (instr_i == `EBREAK_INSTR) begin
                if (state != eBREAK_SET_ADDR &&
                    state != eBREAK &&
                    state != eBREAK_WAIT) begin
                    ready_w = 0;
                    next = eBREAK_SET_ADDR;
                end
                else if (state == eBREAK_SET_ADDR) begin
                    ebreak_w = 1;
                    ready_w = 0;
                    next = eBREAK;
                end
                else begin
                    ready_w = 0;
                    next = eBREAK_WAIT;
                end
            end
            else if (instr_i == `WFI_INSTR) begin
                ready_w = 1'b1;
                next = eOK;
            end
            else begin
                ready_w         = 1'b0;
                illegal_instr_w = 1'b1;
                next            = eERROR;
            end
        end
    end

    {1'b0, 7'b???????}: begin
        ready_w            = 1'b1;
        illegal_instr_w    = 1'b0;
        next               = eINSTR_NOT_VALID;
    end 

    default: begin
        use_alu_jmp_addr_w = 1'b0;
        use_pc_w           = 1'b0;
        illegal_instr_w    = 1'b1;
        is_alu_write_w     = 1'b0;
        alu_sel_w          = 4'b0000;
        alu_op_a_w         = 1'b0;
        alu_op_b_w         = 1'b0;
        alu_dest_addr_w    = 5'b0;
        alu_wb_w           = 1'b0; 
        rf_addr_a_w        = 5'b00000;
        rf_addr_b_w        = 5'b00000;
        imm_ext_w          = 0;   
        lsu_ctrl_valid_w   = 1'b0;
        lsu_ctrl_w         = 4'b0000;
        lsu_regdest_w      = 5'b00000;
        csr_mret_w         = 0;
        ready_w            = 1'b0;
        jmp_instr_w        = 1'b0;
        jmp_addr_w         = 0;
        next               = eERROR;
    end
  endcase
end

endmodule