data/full_repos/permissive/531012469/verilog/rtl/main.v
1: b'%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:368: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s LT generates 1 bits.\n                                                                           : ... In instance rvcorep.p.alu0\n            1 : r_result =  in1 <  in2;\n                         ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:369: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s LTS generates 1 bits.\n                                                                           : ... In instance rvcorep.p.alu0\n            2 : r_result = sin1 < sin2;\n                         ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:256: Operator EQ expects 13 bits on the LHS, but LHS\'s VARREF \'cnt_start\' generates 12 bits.\n                                                                           : ... In instance rvcorep.ploader.serc\n          stage <= (cnt_start == (waitcnt >> 1)) ? \'d1 : stage;\n                              ^~\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:484: Logical Operator COND expects 1 bit on the Conditional Test, but Conditional Test\'s VARREF \'ExMa_b_rslt\' generates 7 bits.\n                                                                           : ... In instance rvcorep.p\n    wire w_bmis = ExMa_b & (ExMa_b_rslt ? ExMa_b_rslt_t1 : ExMa_b_rslt_t2);\n                                        ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:485: Logical Operator COND expects 1 bit on the Conditional Test, but Conditional Test\'s VARREF \'ExMa_b_rslt\' generates 7 bits.\n                                                                           : ... In instance rvcorep.p\n    wire [17:0] w_pc_true = {((ExMa_b_rslt) ? ExMa_tkn_pc[17:2]: ExMa_npc[17:2]), 2\'b00};\n                                            ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:491: Operator ASSIGNW expects 32 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 18 bits.\n                                                                           : ... In instance rvcorep.p\n    assign I_ADDR = {w_npc, 2\'b00};\n                  ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:623: Operator ADD expects 32 bits on the LHS, but LHS\'s VARREF \'IfId_pc\' generates 18 bits.\n                                                                           : ... In instance rvcorep.p\n                             (IfId_im_s[1]) ? IfId_pc + {IfId_ir[31:12], 12\'b0} :   \n                                                      ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:624: Operator ADD expects 32 bits on the LHS, but LHS\'s VARREF \'IfId_pc\' generates 18 bits.\n                                                                           : ... In instance rvcorep.p\n                             (IfId_im_s[2]) ? IfId_pc + 4                       : 0;\n                                                      ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:638: Operator ADD expects 32 bits on the LHS, but LHS\'s VARREF \'IdEx_pc\' generates 18 bits.\n                                                                           : ... In instance rvcorep.p\n    assign w_tkn_pc = (IdEx_JALR) ? Ex_rrs1+IdEx_imm : IdEx_pc+IdEx_imm;  \n                                                              ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:638: Operator ASSIGNW expects 18 bits on the Assign RHS, but Assign RHS\'s COND generates 32 bits.\n                                                                           : ... In instance rvcorep.p\n    assign w_tkn_pc = (IdEx_JALR) ? Ex_rrs1+IdEx_imm : IdEx_pc+IdEx_imm;  \n                    ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:711: Operator ASSIGNW expects 8 bits on the Assign RHS, but Assign RHS\'s SHIFTR generates 32 bits.\n                                                                           : ... In instance rvcorep.p\n    wire [7:0]  w_lb_t = D_IN >> ({w_adr, 3\'d0});\n                       ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:760: Operator COND expects 32 bits on the Conditional True, but Conditional True\'s VARREF \'MaWb_pc\' generates 18 bits.\n                                                                           : ... In instance rvcorep.p\n        else r_rout <= (MaWb_v) ? MaWb_pc : r_rout;  \n                                ^\n%Warning-WIDTH: data/full_repos/permissive/531012469/verilog/rtl/main.v:58: Logical Operator COND expects 1 bit on the Conditional Test, but Conditional Test\'s VARREF \'initwe\' generates 4 bits.\n                                                                          : ... In instance rvcorep\n        initaddr <= (r_rst) ? 0 : (initwe)   ? initaddr + 4 : initaddr;\n                                             ^\n%Error: Exiting due to 13 warning(s)\n'
module RVCore(CLK, RST_X, r_rout, r_halt, I_ADDR, D_ADDR, I_IN, D_IN, D_OUT, D_WE);
    input  wire        CLK, RST_X;
    output reg  [31:0] r_rout;
    output reg         r_halt;
    output wire [31:0] I_ADDR, D_ADDR;
    input  wire [31:0] I_IN, D_IN;
    output wire [31:0] D_OUT;
    output wire  [3:0] D_WE;


    reg [17:0] r_pc          ;
    
    reg        IfId_v        ;
    reg [31:0] IfId_ir       ;
    reg [17:0] IfId_pc       ;
    reg [17:0] IfId_pc_n     ;
    reg [ 6:0] IfId_op       ;
    reg [ 2:0] IfId_funct3   ;
    reg [ 4:0] IfId_rs1      ;
    reg [ 4:0] IfId_rs2      ;
    reg [ 4:0] IfId_rd       ;
    reg        IfId_mem_we   ;
    reg        IfId_reg_we   ;
    reg        IfId_op_ld    ;
    reg        IfId_op_im    ;
    reg        IfId_s1       ;
    reg        IfId_s2       ;
    reg [2:0]  IfId_im_s     ;

    reg        IdEx_v        ;
    reg [17:0] IdEx_pc       ;
    reg [17:0] IdEx_pc_n     ;
    reg [ 6:0] IdEx_op       ;
    reg [ 2:0] IdEx_funct3   ;
    reg [ 4:0] IdEx_rd       ;
    reg [31:0] IdEx_imm      ;
    reg        IdEx_mem_we   ;
    reg        IdEx_reg_we   ;
    reg        IdEx_op_ld    ;
    reg [10:0] IdEx_alu_ctrl ;
    reg [ 6:0] IdEx_bru_ctrl ;
    reg [31:0] IdEx_rrs1     ;
    reg [31:0] IdEx_rrs2     ;
    reg [31:0] IdEx_alu_imm  ;
    reg [31:0] IdEx_ir       ;
    reg [31:0] IdEx_s1       ;
    reg [31:0] IdEx_s2       ;
    reg [31:0] IdEx_u1       ;
    reg [31:0] IdEx_u2       ;
    reg        IdEx_luse     ;
    reg        IdEx_luse_x   ;
    reg        IdEx_JALR     ;
    reg [2:0]  IdEx_st_we    ;
    
    reg        ExMa_v        ;
    reg [17:0] ExMa_pc       ;
    reg [17:0] ExMa_pc_n     ;
    reg [ 6:0] ExMa_op       ;
    reg [ 4:0] ExMa_rd       ;
    reg        ExMa_reg_we   ;
    reg        ExMa_op_ld    ;
    reg [31:0] ExMa_rslt     ;
    reg [ 6:0] ExMa_b_rslt   ;
    reg [17:0] ExMa_tkn_pc   ;
    reg [ 1:0] ExMa_addr     ;
    reg        ExMa_b        ;
    reg [31:0] ExMa_wdata    ;
    reg [31:0] ExMa_ir       ;
    reg [17:0] ExMa_npc      ;
    reg [17:0] ExMa_ppc      ;
    reg        ExMa_b_rslt_t1;
    reg        ExMa_b_rslt_t2;
    reg [ 6:0] ExMa_bru_ctrl ;
    reg [ 4:0] ExMa_lds      ;
    reg  [2:0] ExMa_funct3   ;
    
    reg        MaWb_v        ;
    reg [ 4:0] MaWb_rd       ;
    reg [31:0] MaWb_rslt     ;
    reg [17:0] MaWb_pc       ;
    reg [31:0] MaWb_wdata    ;
    reg [31:0] MaWb_ir       ;


    reg r_rst;
    always @(posedge CLK) r_rst <= !RST_X | r_halt;


    wire [31:0]  w_ir   = I_IN;
    wire w_stall = IdEx_luse;

    wire w_bmis = ExMa_b & (ExMa_b_rslt ? ExMa_b_rslt_t1 : ExMa_b_rslt_t2);
    wire [17:0] w_pc_true = {((ExMa_b_rslt) ? ExMa_tkn_pc[17:2]: ExMa_npc[17:2]), 2'b00};

    wire [15:0] w_npc = (w_bmis) ? w_pc_true[17:2] : (w_stall) ? r_pc[17:2] : r_pc[17:2]+1;
    
    always @(posedge CLK) if(r_rst) r_pc <= 0; else r_pc <= {w_npc, 2'b00};
    
    assign I_ADDR = {w_npc, 2'b00};


    wire [ 4:0]  If_rd;
    wire [ 4:0]  If_rs1;
    wire [ 4:0]  If_rs2;
    wire [31:0]  w_rrs1;
    wire [31:0]  w_rrs2;
    wire         w_mem_we;
    wire         w_reg_we;
    wire         w_op_ld;
    wire         w_op_im;
    decoder_if dec_if0(w_ir, If_rd, If_rs1, If_rs2, w_mem_we, w_reg_we, w_op_ld, w_op_im);

    always @(posedge CLK) begin
        if(r_rst) begin
            IfId_v        <= 0;
            IfId_mem_we   <= 0;
            IfId_reg_we   <= 0;
            IfId_rd       <= 0;
            IfId_op_ld    <= 0;
            IfId_s1       <= 0;
            IfId_s2       <= 0;
            IfId_rs1      <= 0;
            IfId_rs2      <= 0;
            IfId_op       <= 0;
            IfId_pc       <= 0;
            IfId_pc_n     <= 0;
            IfId_ir       <= 0;
            IfId_funct3   <= 0;
            IfId_op_im    <= 0;
            IfId_im_s     <= 0;          
        end
        else begin
            IfId_v        <= (w_bmis) ? 0 : (w_stall) ? IfId_v      : 1;
            IfId_mem_we   <= (w_bmis) ? 0 : (w_stall) ? IfId_mem_we : w_mem_we;
            IfId_reg_we   <= (w_bmis) ? 0 : (w_stall) ? IfId_reg_we : w_reg_we;
            IfId_rd       <= (w_bmis) ? 0 : (w_stall) ? IfId_rd     : If_rd;
            IfId_op_ld    <= (w_bmis) ? 0 : (w_stall) ? IfId_op_ld  : w_op_ld;
            IfId_s1       <= (w_bmis | w_stall) ? 0 : ((If_rs1==IfId_rd) & IfId_reg_we);
            IfId_s2       <= (w_bmis | w_stall) ? 0 : ((If_rs2==IfId_rd) & IfId_reg_we);
            if(!w_stall) begin
                IfId_rs1    <= If_rs1;
                IfId_rs2    <= If_rs2;
                IfId_op     <= w_ir[6:0];
                IfId_pc     <= r_pc;
                IfId_pc_n   <= {w_npc, 2'b00};
                IfId_ir     <= w_ir;
                IfId_funct3 <= w_ir[14:12];
                IfId_op_im  <= w_op_im;
                IfId_im_s   <= (w_ir[6:2]==5'b01101) ? 3'b001 :
                               (w_ir[6:2]==5'b00101) ? 3'b010 :
                               (w_ir[6:2]==5'b11001) ? 3'b100 :
                               (w_ir[6:2]==5'b11011) ? 3'b100 : 0;
            end
        end
    end


    wire [9:0]  Id_alu_ctrl;
    wire [6:0]  Id_bru_ctrl;
    wire [31:0] Id_imm;
    wire [31:0] imm_t;
    decoder_id dec_id0(IfId_ir, Id_alu_ctrl, Id_bru_ctrl, Id_imm);
    
    regfile regs0(CLK, IfId_rs1, IfId_rs2, w_rrs1, w_rrs2, 1'b1, MaWb_rd, MaWb_rslt);
    

    wire w_fwd_s1 = (IfId_rs1==ExMa_rd) & (ExMa_reg_we);
    wire w_fwd_s2 = (IfId_rs2==ExMa_rd) & (ExMa_reg_we);

    wire Id_s1 = (IfId_rs1==IdEx_rd) & (IdEx_reg_we);
    wire Id_s2 = (IfId_rs2==IdEx_rd) & (IdEx_reg_we);
         
    wire Id_luse = r_rst | !IdEx_luse &
         (IfId_op_ld) & ((w_ir[19:15]==IfId_rd) | (w_ir[24:20]==IfId_rd));

                   
    always @(posedge CLK) begin
        if(r_rst) begin
            IdEx_v        <= 0;
            IdEx_op_ld    <= 0;
            IdEx_mem_we   <= 0;
            IdEx_reg_we   <= 0;
            IdEx_luse     <= 1;
            IdEx_luse_x   <= 0;
            IdEx_op       <= 0;
            IdEx_pc       <= 0;
            IdEx_pc_n     <= 0;
            IdEx_rd       <= 0;
            IdEx_ir       <= 0;
            IdEx_funct3   <= 0;
            IdEx_imm      <= 0;
            IdEx_alu_ctrl <= 0;
            IdEx_bru_ctrl <= 0;
            IdEx_JALR     <= 0;
            IdEx_st_we[0] <= 0;
            IdEx_st_we[1] <= 0;
            IdEx_st_we[2] <= 0;
            IdEx_s1       <= 0;
            IdEx_s2       <= 0;
            IdEx_u1       <= 0;
            IdEx_u2       <= 0;
            IdEx_alu_imm  <= 0;
            IdEx_rrs1     <= 0;
            IdEx_rrs2     <= 0;
        end
        else begin
            IdEx_v        <= (w_bmis | w_stall) ? 0 : IfId_v;
            IdEx_op_ld    <= (w_bmis | w_stall) ? 0 : IfId_op_ld;
            IdEx_mem_we   <= (w_bmis | w_stall) ? 0 :IfId_mem_we;
            IdEx_reg_we   <= (w_bmis | w_stall) ? 0 :IfId_reg_we;
            IdEx_luse     <= Id_luse;
            IdEx_luse_x   <= !Id_luse;
            IdEx_op       <= IfId_op;
            IdEx_pc       <= IfId_pc;
            IdEx_pc_n     <= IfId_pc_n;
            IdEx_rd       <= IfId_rd;
            IdEx_ir       <= IfId_ir;
            IdEx_funct3   <= IfId_funct3;
            IdEx_imm      <= Id_imm;
            IdEx_alu_ctrl <= {(Id_alu_ctrl[9] |Id_alu_ctrl[8]), Id_alu_ctrl};
            IdEx_bru_ctrl <= Id_bru_ctrl;
            IdEx_JALR     <= (IfId_op[6:2]==5'b11001);
            IdEx_st_we[0] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & (IfId_funct3[1:0]==0);
            IdEx_st_we[1] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & IfId_funct3[0];
            IdEx_st_we[2] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & IfId_funct3[1];
            IdEx_s1       <= {32{Id_s1}};
            IdEx_s2       <= {32{Id_s2}};
            IdEx_u1       <= {32{!Id_s1 & w_fwd_s1}};
            IdEx_u2       <= {32{!Id_s2 & w_fwd_s2}};
            IdEx_alu_imm  <= (IfId_im_s[0]) ? {IfId_ir[31:12], 12'b0}           :   
                             (IfId_im_s[1]) ? IfId_pc + {IfId_ir[31:12], 12'b0} :   
                             (IfId_im_s[2]) ? IfId_pc + 4                       : 0;
            IdEx_rrs1     <= (Id_s1 | w_fwd_s1) ? 0 : w_rrs1;
            IdEx_rrs2     <= (Id_s2 | w_fwd_s2) ? 0 : (IfId_op_im) ? Id_imm : w_rrs2;
        end
    end
    

    wire [31:0] Ex_rrs1 = ((IdEx_s1) & ExMa_rslt) ^ ((IdEx_u1) & MaWb_rslt) ^ IdEx_rrs1;
    wire [31:0] Ex_rrs2 = ((IdEx_s2) & ExMa_rslt) ^ ((IdEx_u2) & MaWb_rslt) ^ IdEx_rrs2;
    
    wire    [6:0]  w_b_rslt;
    wire    [31:0] w_a_rslt;
    wire    [17:0] w_tkn_pc;

    assign w_tkn_pc = (IdEx_JALR) ? Ex_rrs1+IdEx_imm : IdEx_pc+IdEx_imm;
    assign D_ADDR = Ex_rrs1 + IdEx_imm;
    assign D_OUT  = (IdEx_funct3[0]) ? {2{Ex_rrs2[15:0]}} :
                    (IdEx_funct3[1]) ? Ex_rrs2 : {4{Ex_rrs2[7:0]}};
    
    m_ALU alu0(Ex_rrs1, Ex_rrs2, IdEx_alu_imm, IdEx_alu_ctrl, w_a_rslt, 
               IdEx_bru_ctrl, w_b_rslt);

    always @(posedge CLK) begin
        if(r_rst) begin
            ExMa_v        <= 0;
            ExMa_reg_we   <= 0;
            ExMa_b        <= 0;
            ExMa_rslt     <= 0;
            ExMa_b_rslt   <= 0;
            ExMa_ir       <= 0;
            ExMa_pc       <= 0;
            ExMa_ppc      <= 0;
            ExMa_npc      <= 0;
            ExMa_pc_n     <= 0;
            ExMa_tkn_pc   <= 0;
            ExMa_op       <= 0;
            ExMa_rd       <= 0;
            ExMa_op_ld    <= 0;
            ExMa_addr     <= 0;
            ExMa_wdata    <= 0;
            ExMa_b_rslt_t1<= 0;
            ExMa_b_rslt_t2<= 0;
            ExMa_bru_ctrl <= 0;
            ExMa_funct3   <= 0;
        end
            else begin
            ExMa_v        <= (w_bmis) ? 0 : IdEx_v;
            ExMa_reg_we   <= (w_bmis) ? 0 : IdEx_reg_we;
            ExMa_b        <= (!RST_X || w_bmis || IdEx_v==0) ? 0 : (IdEx_bru_ctrl!=0);
            ExMa_rslt     <= w_a_rslt;
            ExMa_b_rslt   <= w_b_rslt;
            ExMa_ir       <= IdEx_ir;
            ExMa_pc       <= IdEx_pc;
            ExMa_ppc      <= IdEx_pc-4;
            ExMa_npc      <= IdEx_pc+4;
            ExMa_pc_n     <= IdEx_pc_n;
            ExMa_tkn_pc   <= w_tkn_pc;
            ExMa_op       <= IdEx_op;
            ExMa_rd       <= IdEx_rd;
            ExMa_op_ld    <= IdEx_op_ld;
            ExMa_addr     <= D_ADDR[1:0];
            ExMa_wdata    <= D_OUT;
            ExMa_b_rslt_t1<= (w_tkn_pc   !=IdEx_pc_n);
            ExMa_b_rslt_t2<= ((IdEx_pc+4)!=IdEx_pc_n);
            ExMa_bru_ctrl <= IdEx_bru_ctrl;
            ExMa_funct3   <= IdEx_funct3;
        end
    end


    wire [3:0] w_we_sb = (IdEx_st_we[0]) ? (4'b0001 << D_ADDR[1:0])       : 0;
    wire [3:0] w_we_sh = (IdEx_st_we[1]) ? (4'b0011 << {D_ADDR[1], 1'b0}) : 0;
    wire [3:0] w_we_sw = (IdEx_st_we[2]) ? 4'b1111                        : 0;
    assign D_WE = {4{!w_bmis}} & (w_we_sh ^ w_we_sw ^ w_we_sb);
    
    always @(posedge CLK) begin
        if(r_rst) ExMa_lds <= 0;
        else ExMa_lds <= (!IdEx_op_ld) ? 0 :
                        (IdEx_funct3==3'b000) ? 5'b01001 :
                        (IdEx_funct3==3'b001) ? 5'b01010 :
                        (IdEx_funct3==3'b010) ? 5'b00100 :
                        (IdEx_funct3==3'b100) ? 5'b00001 :
                                                5'b00010 ;
    end
    

    wire [1:0]  w_adr  = ExMa_addr;
    wire [7:0]  w_lb_t = D_IN >> ({w_adr, 3'd0});
    wire [15:0] w_lh_t = (w_adr[1]) ? D_IN[31:16] : D_IN[15:0];

    wire [31:0] w_ld_lb  = {{24{w_lb_t[7]}},  w_lb_t[7:0]};
    wire [31:0] w_ld_lbu = {24'd0,            w_lb_t[7:0]};
    wire [31:0] w_ld_lh  = {{16{w_lh_t[15]}}, w_lh_t[15:0]};
    wire [31:0] w_ld_lhu = {16'd0,            w_lh_t[15:0]};
    wire [31:0] w_ld_lw  = D_IN;

    reg [31:0] r_ld=0;
    always @(*) begin
        case(ExMa_funct3)
            3'b000 : r_ld = w_ld_lb;
            3'b001 : r_ld = w_ld_lh;
            3'b010 : r_ld = w_ld_lw;
            3'b100 : r_ld = w_ld_lbu;
            3'b101 : r_ld = w_ld_lhu;
            default: r_ld = 0;
        endcase
    end
    wire [31:0] Ma_rslt = (ExMa_op_ld) ? r_ld : ExMa_rslt;
    
    always @(posedge CLK) begin
        if(r_rst) begin
            MaWb_v     <= 0;
            MaWb_pc    <= 0;
            MaWb_ir    <= 0;
            MaWb_wdata <= 0;
            MaWb_rd    <= 0;
            MaWb_rslt  <= 0;           
        end
        else begin
            MaWb_v     <= ExMa_v;
            MaWb_pc    <= ExMa_pc;
            MaWb_ir    <= ExMa_ir;
            MaWb_wdata <= ExMa_wdata;
            MaWb_rd    <= (ExMa_v) ? ExMa_rd : 0;
            MaWb_rslt  <= Ma_rslt;
        end
    end


    always @(posedge CLK) begin
        if(r_rst) r_halt <= 0;
        else if (ExMa_op==`OPCODE_HALT____) r_halt <= 1;
    end
    
    always @(posedge CLK) begin
        if(r_rst) r_rout <= 0;
        else r_rout <= (MaWb_v) ? MaWb_pc : r_rout;
    end
endmodule
module RVCore(CLK, RST_X, r_rout, r_halt, I_ADDR, D_ADDR, I_IN, D_IN, D_OUT, D_WE);

    input  wire        CLK, RST_X;
    output reg  [31:0] r_rout;
    output reg         r_halt;
    output wire [31:0] I_ADDR, D_ADDR;
    input  wire [31:0] I_IN, D_IN;
    output wire [31:0] D_OUT;
    output wire  [3:0] D_WE;


    reg [17:0] r_pc          ;
    
    reg        IfId_v        ;
    reg [31:0] IfId_ir       ;
    reg [17:0] IfId_pc       ;
    reg [17:0] IfId_pc_n     ;
    reg [ 6:0] IfId_op       ;
    reg [ 2:0] IfId_funct3   ;
    reg [ 4:0] IfId_rs1      ;
    reg [ 4:0] IfId_rs2      ;
    reg [ 4:0] IfId_rd       ;
    reg        IfId_mem_we   ;
    reg        IfId_reg_we   ;
    reg        IfId_op_ld    ;
    reg        IfId_op_im    ;
    reg        IfId_s1       ;
    reg        IfId_s2       ;
    reg [2:0]  IfId_im_s     ;

    reg        IdEx_v        ;
    reg [17:0] IdEx_pc       ;
    reg [17:0] IdEx_pc_n     ;
    reg [ 6:0] IdEx_op       ;
    reg [ 2:0] IdEx_funct3   ;
    reg [ 4:0] IdEx_rd       ;
    reg [31:0] IdEx_imm      ;
    reg        IdEx_mem_we   ;
    reg        IdEx_reg_we   ;
    reg        IdEx_op_ld    ;
    reg [10:0] IdEx_alu_ctrl ;
    reg [ 6:0] IdEx_bru_ctrl ;
    reg [31:0] IdEx_rrs1     ;
    reg [31:0] IdEx_rrs2     ;
    reg [31:0] IdEx_alu_imm  ;
    reg [31:0] IdEx_ir       ;
    reg [31:0] IdEx_s1       ;
    reg [31:0] IdEx_s2       ;
    reg [31:0] IdEx_u1       ;
    reg [31:0] IdEx_u2       ;
    reg        IdEx_luse     ;
    reg        IdEx_luse_x   ;
    reg        IdEx_JALR     ;
    reg [2:0]  IdEx_st_we    ;
    
    reg        ExMa_v        ;
    reg [17:0] ExMa_pc       ;
    reg [17:0] ExMa_pc_n     ;
    reg [ 6:0] ExMa_op       ;
    reg [ 4:0] ExMa_rd       ;
    reg        ExMa_reg_we   ;
    reg        ExMa_op_ld    ;
    reg [31:0] ExMa_rslt     ;
    reg [ 6:0] ExMa_b_rslt   ;
    reg [17:0] ExMa_tkn_pc   ;
    reg [ 1:0] ExMa_addr     ;
    reg        ExMa_b        ;
    reg [31:0] ExMa_wdata    ;
    reg [31:0] ExMa_ir       ;
    reg [17:0] ExMa_npc      ;
    reg [17:0] ExMa_ppc      ;
    reg        ExMa_b_rslt_t1;
    reg        ExMa_b_rslt_t2;
    reg [ 6:0] ExMa_bru_ctrl ;
    reg [ 4:0] ExMa_lds      ;
    reg  [2:0] ExMa_funct3   ;
    
    reg        MaWb_v        ;
    reg [ 4:0] MaWb_rd       ;
    reg [31:0] MaWb_rslt     ;
    reg [17:0] MaWb_pc       ;
    reg [31:0] MaWb_wdata    ;
    reg [31:0] MaWb_ir       ;


    reg r_rst;
    always @(posedge CLK) r_rst <= !RST_X | r_halt;


    wire [31:0]  w_ir   = I_IN;
    wire w_stall = IdEx_luse;

    wire w_bmis = ExMa_b & (ExMa_b_rslt ? ExMa_b_rslt_t1 : ExMa_b_rslt_t2);
    wire [17:0] w_pc_true = {((ExMa_b_rslt) ? ExMa_tkn_pc[17:2]: ExMa_npc[17:2]), 2'b00};

    wire [15:0] w_npc = (w_bmis) ? w_pc_true[17:2] : (w_stall) ? r_pc[17:2] : r_pc[17:2]+1;
    
    always @(posedge CLK) if(r_rst) r_pc <= 0; else r_pc <= {w_npc, 2'b00};
    
    assign I_ADDR = {w_npc, 2'b00};


    wire [ 4:0]  If_rd;
    wire [ 4:0]  If_rs1;
    wire [ 4:0]  If_rs2;
    wire [31:0]  w_rrs1;
    wire [31:0]  w_rrs2;
    wire         w_mem_we;
    wire         w_reg_we;
    wire         w_op_ld;
    wire         w_op_im;
    decoder_if dec_if0(w_ir, If_rd, If_rs1, If_rs2, w_mem_we, w_reg_we, w_op_ld, w_op_im);

    always @(posedge CLK) begin
        if(r_rst) begin
            IfId_v        <= 0;
            IfId_mem_we   <= 0;
            IfId_reg_we   <= 0;
            IfId_rd       <= 0;
            IfId_op_ld    <= 0;
            IfId_s1       <= 0;
            IfId_s2       <= 0;
            IfId_rs1      <= 0;
            IfId_rs2      <= 0;
            IfId_op       <= 0;
            IfId_pc       <= 0;
            IfId_pc_n     <= 0;
            IfId_ir       <= 0;
            IfId_funct3   <= 0;
            IfId_op_im    <= 0;
            IfId_im_s     <= 0;          
        end
        else begin
            IfId_v        <= (w_bmis) ? 0 : (w_stall) ? IfId_v      : 1;
            IfId_mem_we   <= (w_bmis) ? 0 : (w_stall) ? IfId_mem_we : w_mem_we;
            IfId_reg_we   <= (w_bmis) ? 0 : (w_stall) ? IfId_reg_we : w_reg_we;
            IfId_rd       <= (w_bmis) ? 0 : (w_stall) ? IfId_rd     : If_rd;
            IfId_op_ld    <= (w_bmis) ? 0 : (w_stall) ? IfId_op_ld  : w_op_ld;
            IfId_s1       <= (w_bmis | w_stall) ? 0 : ((If_rs1==IfId_rd) & IfId_reg_we);
            IfId_s2       <= (w_bmis | w_stall) ? 0 : ((If_rs2==IfId_rd) & IfId_reg_we);
            if(!w_stall) begin
                IfId_rs1    <= If_rs1;
                IfId_rs2    <= If_rs2;
                IfId_op     <= w_ir[6:0];
                IfId_pc     <= r_pc;
                IfId_pc_n   <= {w_npc, 2'b00};
                IfId_ir     <= w_ir;
                IfId_funct3 <= w_ir[14:12];
                IfId_op_im  <= w_op_im;
                IfId_im_s   <= (w_ir[6:2]==5'b01101) ? 3'b001 :
                               (w_ir[6:2]==5'b00101) ? 3'b010 :
                               (w_ir[6:2]==5'b11001) ? 3'b100 :
                               (w_ir[6:2]==5'b11011) ? 3'b100 : 0;
            end
        end
    end


    wire [9:0]  Id_alu_ctrl;
    wire [6:0]  Id_bru_ctrl;
    wire [31:0] Id_imm;
    wire [31:0] imm_t;
    decoder_id dec_id0(IfId_ir, Id_alu_ctrl, Id_bru_ctrl, Id_imm);
    
    regfile regs0(CLK, IfId_rs1, IfId_rs2, w_rrs1, w_rrs2, 1'b1, MaWb_rd, MaWb_rslt);
    

    wire w_fwd_s1 = (IfId_rs1==ExMa_rd) & (ExMa_reg_we);
    wire w_fwd_s2 = (IfId_rs2==ExMa_rd) & (ExMa_reg_we);

    wire Id_s1 = (IfId_rs1==IdEx_rd) & (IdEx_reg_we);
    wire Id_s2 = (IfId_rs2==IdEx_rd) & (IdEx_reg_we);
         
    wire Id_luse = r_rst | !IdEx_luse &
         (IfId_op_ld) & ((w_ir[19:15]==IfId_rd) | (w_ir[24:20]==IfId_rd));

                   
    always @(posedge CLK) begin
        if(r_rst) begin
            IdEx_v        <= 0;
            IdEx_op_ld    <= 0;
            IdEx_mem_we   <= 0;
            IdEx_reg_we   <= 0;
            IdEx_luse     <= 1;
            IdEx_luse_x   <= 0;
            IdEx_op       <= 0;
            IdEx_pc       <= 0;
            IdEx_pc_n     <= 0;
            IdEx_rd       <= 0;
            IdEx_ir       <= 0;
            IdEx_funct3   <= 0;
            IdEx_imm      <= 0;
            IdEx_alu_ctrl <= 0;
            IdEx_bru_ctrl <= 0;
            IdEx_JALR     <= 0;
            IdEx_st_we[0] <= 0;
            IdEx_st_we[1] <= 0;
            IdEx_st_we[2] <= 0;
            IdEx_s1       <= 0;
            IdEx_s2       <= 0;
            IdEx_u1       <= 0;
            IdEx_u2       <= 0;
            IdEx_alu_imm  <= 0;
            IdEx_rrs1     <= 0;
            IdEx_rrs2     <= 0;
        end
        else begin
            IdEx_v        <= (w_bmis | w_stall) ? 0 : IfId_v;
            IdEx_op_ld    <= (w_bmis | w_stall) ? 0 : IfId_op_ld;
            IdEx_mem_we   <= (w_bmis | w_stall) ? 0 :IfId_mem_we;
            IdEx_reg_we   <= (w_bmis | w_stall) ? 0 :IfId_reg_we;
            IdEx_luse     <= Id_luse;
            IdEx_luse_x   <= !Id_luse;
            IdEx_op       <= IfId_op;
            IdEx_pc       <= IfId_pc;
            IdEx_pc_n     <= IfId_pc_n;
            IdEx_rd       <= IfId_rd;
            IdEx_ir       <= IfId_ir;
            IdEx_funct3   <= IfId_funct3;
            IdEx_imm      <= Id_imm;
            IdEx_alu_ctrl <= {(Id_alu_ctrl[9] |Id_alu_ctrl[8]), Id_alu_ctrl};
            IdEx_bru_ctrl <= Id_bru_ctrl;
            IdEx_JALR     <= (IfId_op[6:2]==5'b11001);
            IdEx_st_we[0] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & (IfId_funct3[1:0]==0);
            IdEx_st_we[1] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & IfId_funct3[0];
            IdEx_st_we[2] <= ((w_bmis | w_stall) ? 0 :IfId_mem_we) & IfId_funct3[1];
            IdEx_s1       <= {32{Id_s1}};
            IdEx_s2       <= {32{Id_s2}};
            IdEx_u1       <= {32{!Id_s1 & w_fwd_s1}};
            IdEx_u2       <= {32{!Id_s2 & w_fwd_s2}};
            IdEx_alu_imm  <= (IfId_im_s[0]) ? {IfId_ir[31:12], 12'b0}           :   
                             (IfId_im_s[1]) ? IfId_pc + {IfId_ir[31:12], 12'b0} :   
                             (IfId_im_s[2]) ? IfId_pc + 4                       : 0;
            IdEx_rrs1     <= (Id_s1 | w_fwd_s1) ? 0 : w_rrs1;
            IdEx_rrs2     <= (Id_s2 | w_fwd_s2) ? 0 : (IfId_op_im) ? Id_imm : w_rrs2;
        end
    end
    

    wire [31:0] Ex_rrs1 = ((IdEx_s1) & ExMa_rslt) ^ ((IdEx_u1) & MaWb_rslt) ^ IdEx_rrs1;
    wire [31:0] Ex_rrs2 = ((IdEx_s2) & ExMa_rslt) ^ ((IdEx_u2) & MaWb_rslt) ^ IdEx_rrs2;
    
    wire    [6:0]  w_b_rslt;
    wire    [31:0] w_a_rslt;
    wire    [17:0] w_tkn_pc;

    assign w_tkn_pc = (IdEx_JALR) ? Ex_rrs1+IdEx_imm : IdEx_pc+IdEx_imm;
    assign D_ADDR = Ex_rrs1 + IdEx_imm;
    assign D_OUT  = (IdEx_funct3[0]) ? {2{Ex_rrs2[15:0]}} :
                    (IdEx_funct3[1]) ? Ex_rrs2 : {4{Ex_rrs2[7:0]}};
    
    m_ALU alu0(Ex_rrs1, Ex_rrs2, IdEx_alu_imm, IdEx_alu_ctrl, w_a_rslt, 
               IdEx_bru_ctrl, w_b_rslt);

    always @(posedge CLK) begin
        if(r_rst) begin
            ExMa_v        <= 0;
            ExMa_reg_we   <= 0;
            ExMa_b        <= 0;
            ExMa_rslt     <= 0;
            ExMa_b_rslt   <= 0;
            ExMa_ir       <= 0;
            ExMa_pc       <= 0;
            ExMa_ppc      <= 0;
            ExMa_npc      <= 0;
            ExMa_pc_n     <= 0;
            ExMa_tkn_pc   <= 0;
            ExMa_op       <= 0;
            ExMa_rd       <= 0;
            ExMa_op_ld    <= 0;
            ExMa_addr     <= 0;
            ExMa_wdata    <= 0;
            ExMa_b_rslt_t1<= 0;
            ExMa_b_rslt_t2<= 0;
            ExMa_bru_ctrl <= 0;
            ExMa_funct3   <= 0;
        end
            else begin
            ExMa_v        <= (w_bmis) ? 0 : IdEx_v;
            ExMa_reg_we   <= (w_bmis) ? 0 : IdEx_reg_we;
            ExMa_b        <= (!RST_X || w_bmis || IdEx_v==0) ? 0 : (IdEx_bru_ctrl!=0);
            ExMa_rslt     <= w_a_rslt;
            ExMa_b_rslt   <= w_b_rslt;
            ExMa_ir       <= IdEx_ir;
            ExMa_pc       <= IdEx_pc;
            ExMa_ppc      <= IdEx_pc-4;
            ExMa_npc      <= IdEx_pc+4;
            ExMa_pc_n     <= IdEx_pc_n;
            ExMa_tkn_pc   <= w_tkn_pc;
            ExMa_op       <= IdEx_op;
            ExMa_rd       <= IdEx_rd;
            ExMa_op_ld    <= IdEx_op_ld;
            ExMa_addr     <= D_ADDR[1:0];
            ExMa_wdata    <= D_OUT;
            ExMa_b_rslt_t1<= (w_tkn_pc   !=IdEx_pc_n);
            ExMa_b_rslt_t2<= ((IdEx_pc+4)!=IdEx_pc_n);
            ExMa_bru_ctrl <= IdEx_bru_ctrl;
            ExMa_funct3   <= IdEx_funct3;
        end
    end


    wire [3:0] w_we_sb = (IdEx_st_we[0]) ? (4'b0001 << D_ADDR[1:0])       : 0;
    wire [3:0] w_we_sh = (IdEx_st_we[1]) ? (4'b0011 << {D_ADDR[1], 1'b0}) : 0;
    wire [3:0] w_we_sw = (IdEx_st_we[2]) ? 4'b1111                        : 0;
    assign D_WE = {4{!w_bmis}} & (w_we_sh ^ w_we_sw ^ w_we_sb);
    
    always @(posedge CLK) begin
        if(r_rst) ExMa_lds <= 0;
        else ExMa_lds <= (!IdEx_op_ld) ? 0 :
                        (IdEx_funct3==3'b000) ? 5'b01001 :
                        (IdEx_funct3==3'b001) ? 5'b01010 :
                        (IdEx_funct3==3'b010) ? 5'b00100 :
                        (IdEx_funct3==3'b100) ? 5'b00001 :
                                                5'b00010 ;
    end
    

    wire [1:0]  w_adr  = ExMa_addr;
    wire [7:0]  w_lb_t = D_IN >> ({w_adr, 3'd0});
    wire [15:0] w_lh_t = (w_adr[1]) ? D_IN[31:16] : D_IN[15:0];

    wire [31:0] w_ld_lb  = {{24{w_lb_t[7]}},  w_lb_t[7:0]};
    wire [31:0] w_ld_lbu = {24'd0,            w_lb_t[7:0]};
    wire [31:0] w_ld_lh  = {{16{w_lh_t[15]}}, w_lh_t[15:0]};
    wire [31:0] w_ld_lhu = {16'd0,            w_lh_t[15:0]};
    wire [31:0] w_ld_lw  = D_IN;

    reg [31:0] r_ld=0;
    always @(*) begin
        case(ExMa_funct3)
            3'b000 : r_ld = w_ld_lb;
            3'b001 : r_ld = w_ld_lh;
            3'b010 : r_ld = w_ld_lw;
            3'b100 : r_ld = w_ld_lbu;
            3'b101 : r_ld = w_ld_lhu;
            default: r_ld = 0;
        endcase
    end
    wire [31:0] Ma_rslt = (ExMa_op_ld) ? r_ld : ExMa_rslt;
    
    always @(posedge CLK) begin
        if(r_rst) begin
            MaWb_v     <= 0;
            MaWb_pc    <= 0;
            MaWb_ir    <= 0;
            MaWb_wdata <= 0;
            MaWb_rd    <= 0;
            MaWb_rslt  <= 0;           
        end
        else begin
            MaWb_v     <= ExMa_v;
            MaWb_pc    <= ExMa_pc;
            MaWb_ir    <= ExMa_ir;
            MaWb_wdata <= ExMa_wdata;
            MaWb_rd    <= (ExMa_v) ? ExMa_rd : 0;
            MaWb_rslt  <= Ma_rslt;
        end
    end


    always @(posedge CLK) begin
        if(r_rst) r_halt <= 0;
        else if (ExMa_op==`OPCODE_HALT____) r_halt <= 1;
    end
    
    always @(posedge CLK) begin
        if(r_rst) r_rout <= 0;
        else r_rout <= (MaWb_v) ? MaWb_pc : r_rout;
    end
endmodule