data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v
1: b'%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:7: Cannot find include file: define.vh\n`include "define.vh" \n         ^~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src,data/full_repos/permissive/413020148/define.vh\n             data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src,data/full_repos/permissive/413020148/define.vh.v\n             data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src,data/full_repos/permissive/413020148/define.vh.sv\n             define.vh\n             define.vh.v\n             define.vh.sv\n             obj_dir/define.vh\n             obj_dir/define.vh.v\n             obj_dir/define.vh.sv\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:76: Define or directive not defined: \'`D_START_PC\'\n    reg  [31:0] pc             = `D_START_PC;   \n                                 ^~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:76: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n    reg  [31:0] pc             = `D_START_PC;   \n                                            ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:101: Define or directive not defined: \'`PRIV_M\'\n    reg   [1:0] priv           = `PRIV_M;       \n                                 ^~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:101: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n    reg   [1:0] priv           = `PRIV_M;       \n                                        ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:169: Define or directive not defined: \'`S_INI\'\n    always@(posedge CLK) r_init_stage <= (w_state==`S_INI);\n                                                   ^~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:169: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    always@(posedge CLK) r_init_stage <= (w_state==`S_INI);\n                                                         ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:180: Define or directive not defined: \'`S_IF\'\n        if(state==`S_IF && r_if_state==1 && !w_busy) r_if_irl <= w_insn_data[31:16];\n                  ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:180: syntax error, unexpected &&, expecting TYPE-IDENTIFIER\n        if(state==`S_IF && r_if_state==1 && !w_busy) r_if_irl <= w_insn_data[31:16];\n                        ^~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:181: Define or directive not defined: \'`S_IF\'\n        if(state==`S_IF && w_pagefault==~0) begin r_cpc <= pc; end\n                  ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:181: syntax error, unexpected &&, expecting TYPE-IDENTIFIER\n        if(state==`S_IF && w_pagefault==~0) begin r_cpc <= pc; end\n                        ^~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:184: Define or directive not defined: \'`S_IF\'\n    wire [1:0] w_if_state = ((!(state==`S_IF || state==`S_CVT)) || w_pagefault!=~0) ? 0 :\n                                       ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:184: Define or directive not defined: \'`S_CVT\'\n    wire [1:0] w_if_state = ((!(state==`S_IF || state==`S_CVT)) || w_pagefault!=~0) ? 0 :\n                                                       ^~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:209: Define or directive not defined: \'`OPCODE_OP_FP___\'\n    wire w_nop = (w_ir_t[6:0]==`OPCODE_OP_FP___ ||  \n                               ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:209: syntax error, unexpected ||, expecting TYPE-IDENTIFIER\n    wire w_nop = (w_ir_t[6:0]==`OPCODE_OP_FP___ ||  \n                                                ^~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:210: Define or directive not defined: \'`OPCODE_LOAD_FP_\'\n                  w_ir_t[6:0]==`OPCODE_LOAD_FP_ ||  w_ir_t[6:0]==`OPCODE_STORE_FP);\n                               ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:210: Define or directive not defined: \'`OPCODE_STORE_FP\'\n                  w_ir_t[6:0]==`OPCODE_LOAD_FP_ ||  w_ir_t[6:0]==`OPCODE_STORE_FP);\n                                                                 ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:212: Define or directive not defined: \'`RV32_NOP\'\n    wire [31:0] w_ir = (w_nop) ? `RV32_NOP : (w_cinsn) ? w_ir_t : w_ir_org;  \n                                 ^~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:212: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n    wire [31:0] w_ir = (w_nop) ? `RV32_NOP : (w_cinsn) ? w_ir_t : w_ir_org;  \n                                           ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:213: Define or directive not defined: \'`S_CVT\'\n    always@(posedge CLK) if(state == `S_CVT) begin \n                                     ^~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:213: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    always@(posedge CLK) if(state == `S_CVT) begin \n                                           ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:216: syntax error, unexpected <=, expecting IDENTIFIER\n        if(!w_busy) r_ir16  <= w_ir_org[31:16];\n                            ^~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:227: Define or directive not defined: \'`S_WB\'\n    wire w_regfile_we = (w_wb_r_enable && state==`S_WB);\n                                                 ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:227: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    wire w_regfile_we = (w_wb_r_enable && state==`S_WB);\n                                                      ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:230: Define or directive not defined: \'`S_ID\'\n    always @(posedge CLK) if(state == `S_ID) begin\n                                      ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:230: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    always @(posedge CLK) if(state == `S_ID) begin\n                                           ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:244: Define or directive not defined: \'`OPCODE_SYSTEM__\'\n    wire w_op_priv = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]==`FUNCT3_PRIV__);\n                                   ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:244: Define or directive not defined: \'`FUNCT3_PRIV__\'\n    wire w_op_priv = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]==`FUNCT3_PRIV__);\n                                                                    ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:245: Define or directive not defined: \'`OPCODE_SYSTEM__\'\n    wire w_op_csr  = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]!=`FUNCT3_PRIV__);\n                                   ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:245: syntax error, unexpected &&, expecting TYPE-IDENTIFIER\n    wire w_op_csr  = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]!=`FUNCT3_PRIV__);\n                                                    ^~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:245: Define or directive not defined: \'`FUNCT3_PRIV__\'\n    wire w_op_csr  = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]!=`FUNCT3_PRIV__);\n                                                                    ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:246: Define or directive not defined: \'`S_ID\'\n    always @(posedge CLK) if(state == `S_ID) begin       \n                                      ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:246: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    always @(posedge CLK) if(state == `S_ID) begin       \n                                           ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:247: Define or directive not defined: \'`FUNCT5_AMO_SC__\'\n        r_op_AMO_SC   <= (r_ir[31:27]==`FUNCT5_AMO_SC__);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:248: Define or directive not defined: \'`FUNCT5_AMO_LR__\'\n        r_op_AMO_LR   <= (r_ir[31:27]==`FUNCT5_AMO_LR__);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:249: Define or directive not defined: \'`OPCODE_LOAD____\'\n        r_op_LOAD     <= (r_ir[ 6: 0]==`OPCODE_LOAD____);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:250: Define or directive not defined: \'`OPCODE_STORE___\'\n        r_op_STORE    <= (r_ir[ 6: 0]==`OPCODE_STORE___);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:251: Define or directive not defined: \'`OPCODE_AMO_____\'\n        r_op_AMO      <= (r_ir[ 6: 0]==`OPCODE_AMO_____);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:252: Define or directive not defined: \'`OPCODE_SYSTEM__\'\n        r_op_SYS      <= (r_ir[ 6: 0]==`OPCODE_SYSTEM__);  \n                                       ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:253: Define or directive not defined: \'`FUNCT12_ECALL_\'\n        r_op_ECALL    <= (w_op_priv && r_ir[31:20]==`FUNCT12_ECALL_);\n                                                    ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:254: Define or directive not defined: \'`FUNCT12_SRET__\'\n        r_op_SRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_SRET__);\n                                                    ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:255: Define or directive not defined: \'`FUNCT12_MRET__\'\n        r_op_MRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_MRET__);\n                                                    ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:256: Define or directive not defined: \'`CSR_MSTATUS\'\n        r_op_CSR_MSTA <= (w_op_csr  && r_ir[31:20]==`CSR_MSTATUS);\n                                                    ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:257: Define or directive not defined: \'`CSR_SSTATUS\'\n        r_op_CSR_SSTA <= (w_op_csr  && r_ir[31:20]==`CSR_SSTATUS);\n                                                    ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:273: Define or directive not defined: \'`S_OF\'\n    always @(posedge CLK) if(state == `S_OF) begin\n                                      ^~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:273: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    always @(posedge CLK) if(state == `S_OF) begin\n                                           ^\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:279: Define or directive not defined: \'`OPCODE_OP_IMM__\'\n        r_alu_in2  <= (r_opcode==`OPCODE_OP_IMM__) ? r_imm : w_rrs2;\n                                 ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:280: Define or directive not defined: \'`OPCODE_OP_IMM__\'\n        r_alu_f7   <= (r_opcode==`OPCODE_OP_IMM__) ?\n                                 ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:281: Define or directive not defined: \'`FUNCT3_ADD___\'\n                      ((r_funct3==`FUNCT3_ADD___) ? 0 : r_funct7 & 7\'h20) : r_funct7;;\n                                  ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/413020148/verilog/rtl/cores/RVsoc/src/rvcorem.v:288: Define or directive not defined: \'`S_EX1\'\n    wire        w_ex1 = (state == `S_EX1);\n                                  ^~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module m_RVCoreM(CLK, RST_X, w_stall, r_halt, w_insn_addr, w_data_addr, w_insn_data, w_data_data,
                w_data_wdata, w_data_we, w_data_ctrl, w_priv, w_satp, w_mstatus, w_mtime,
                w_mtimecmp, w_wmtimecmp, w_clint_we, w_mip, w_wmip, w_plic_we, w_busy, w_pagefault,
                w_tlb_req, w_tlb_flush, w_core_pc, w_core_ir, w_core_odata, w_init_stage);
    input  wire         CLK, RST_X, w_stall;
    input  wire [31:0]  w_insn_data, w_data_data;
    input  wire [63:0]  w_wmtimecmp;
    input  wire         w_clint_we;
    input  wire [31:0]  w_wmip;
    input  wire         w_plic_we;
    input  wire         w_busy;
    input  wire [31:0]  w_pagefault;

    output reg          r_halt;
    output wire [31:0]  w_core_odata;
    output wire [31:0]  w_data_wdata;
    output wire [31:0]  w_insn_addr;
    output wire [2:0]   w_data_ctrl;
    output wire [31:0]  w_data_addr;
    output wire [63:0]  w_mtime;
    output wire [63:0]  w_mtimecmp;
    output wire [31:0]  w_priv;
    output wire [31:0]  w_satp;
    output wire [31:0]  w_mstatus;
    output wire [31:0]  w_mip;
    output wire [31:0]  w_core_pc;
    output wire [31:0]  w_core_ir;
    output wire         w_init_stage;
    output wire  [1:0]  w_tlb_req;
    output wire         w_data_we;
    output wire         w_tlb_flush;


    reg   [3:0] state          = 0;
    reg  [31:0] pc             = `D_START_PC;

    reg  [31:0] mstatus        = 0;
    reg  [31:0] mtvec          = 0;
    reg  [31:0] mscratch       = 0;
    reg  [31:0] mepc           = 0;
    reg  [31:0] mcause         = 0;
    reg  [31:0] mtval          = 0;
    reg  [31:0] mhartid        = 0;
    reg  [31:0] misa           = 32'h00141105;
    reg  [31:0] mie            = 0;
    reg  [31:0] mip            = 0;
    reg  [31:0] medeleg        = 0;
    reg  [31:0] mideleg        = 0;
    reg  [31:0] mcounteren     = 0;
    reg  [31:0] stvec          = 0;
    reg  [31:0] sscratch       = 0;
    reg  [31:0] sepc           = 0;
    reg  [31:0] scause         = 0;
    reg  [31:0] stval          = 0;
    reg  [31:0] satp           = 0;
    reg  [31:0] scounteren     = 0;
    
    reg  [31:0] load_res       = 0;
    reg         reserved       = 0;
    reg   [1:0] priv           = `PRIV_M;
    reg  [63:0] mtime          = 1;
    reg  [63:0] mtimecmp       = 1;
    reg  [31:0] pending_tval   = 0;
    reg  [31:0] pending_exception = ~0;


    reg  [31:0] r_cpc          = 0;
    reg  [31:0] r_ir_org       = 0;

    reg         r_cinsn        = 0;
    reg  [31:0] r_ir           = 0;
    reg  [15:0] r_ir16         = 0;
    reg         r_ir16_v       = 0;

    reg   [6:0] r_opcode       = 0;
    reg   [4:0] r_rd           = 0;
    reg   [4:0] r_rs1          = 0;
    reg   [4:0] r_rs2          = 0;
    reg   [2:0] r_funct3       = 0;
    reg   [4:0] r_funct5       = 0;
    reg   [6:0] r_funct7       = 0;
    reg  [11:0] r_funct12      = 0;
    reg  [31:0] r_imm          = 0;
    reg         r_op_AMO_SC    = 0;
    reg         r_op_AMO_LR    = 0;
    reg         r_op_LOAD      = 0;
    reg         r_op_STORE     = 0;
    reg         r_op_AMO       = 0;
    reg         r_op_SYS       = 0;
    reg         r_op_ECALL     = 0;
    reg         r_op_SRET      = 0;
    reg         r_op_MRET      = 0;
    reg         r_op_CSR_MSTA  = 0;
    reg         r_op_CSR_SSTA  = 0; 

    reg  [31:0] r_rrs1         = 0;
    reg  [31:0] r_rrs2         = 0;
    reg  [31:0] r_rcsr         = 0;
    reg  [31:0] r_alu_in2      = 0;
    reg   [6:0] r_alu_f7       = 0;

    reg         r_tkn          = 0;
    reg  [31:0] r_jmp_pc       = 0;
    reg  [31:0] r_mem_addr     = 0;
    reg  [31:0] r_wb_data      = 0;
    reg  [31:0] r_wb_data_csr  = 0;

    reg  [31:0] r_mem_rdata    = 0;
    reg  [31:0] r_atom_wdata   = 0;


    reg  [63:0] e_icount    = 1;
    reg         r_if_done   = 0;
    reg  [15:0] r_if_irl    = 0;
    reg  [31:0] r_rcsr_t    = 0;
    reg  [31:0] irq_num     = 0;
    reg   [1:0] r_if_state  = 0;


    wire [31:0] w_wb_r_data;
    wire        w_wb_r_enable;
    wire [31:0] w_interrupt_mask;
    wire [31:0] w_irq_t;
    wire [3:0]  w_state;
    

    reg r_init_stage=0;
    always@(posedge CLK) r_init_stage <= (w_state==`S_INI);
                                        
    assign w_init_stage = r_init_stage;


    wire [31:0] w_vadr1 = {pc[31:2], 2'b0};
    wire [31:0] w_vadr2 = pc + 2;
    wire        w_nalign4 = (pc[3:1]==3'b111);
    wire        w_usestate = (w_nalign4 && !r_ir16_v);

    always@(posedge CLK) begin
        if(state==`S_IF && r_if_state==1 && !w_busy) r_if_irl <= w_insn_data[31:16];
        if(state==`S_IF && w_pagefault==~0) begin r_cpc <= pc; end
    end

    wire [1:0] w_if_state = ((!(state==`S_IF || state==`S_CVT)) || w_pagefault!=~0) ? 0 :
                            (r_if_state==0 && w_nalign4 && !w_busy)                 ? (r_ir16_v) ? 3 : 1 :
                            (r_if_state==1 &&              !w_busy)                 ? 2 :
                            (r_if_state==2 &&              !w_busy)                 ? 3 : r_if_state;
    
    always@(posedge CLK) r_if_state <= w_if_state;

    reg [31:0] r_insn_addr=0;
    always@(posedge CLK) begin
        r_insn_addr <=  (w_nalign4 && r_ir16_v) ? w_vadr2 :
                        (w_if_state==2 || w_if_state==3) ? w_vadr2 :
                        (w_usestate) ? w_vadr1 : pc;
    end
    assign w_insn_addr = r_insn_addr;
      
    wire [31:0] w_ir_org = (r_if_state == 3) ? (r_ir16_v) ? {w_insn_data[15:0], r_ir16} :
                                                            {w_insn_data[15:0], r_if_irl} :
                                                w_insn_data;


    wire w_cinsn = (w_ir_org[1:0] != 2'b11);
    
    wire [31:0] w_ir_t;
    m_decomp decomp0(w_ir_org, w_ir_t);
    
    wire w_nop = (w_ir_t[6:0]==`OPCODE_OP_FP___ ||  
                  w_ir_t[6:0]==`OPCODE_LOAD_FP_ ||  w_ir_t[6:0]==`OPCODE_STORE_FP);

    wire [31:0] w_ir = (w_nop) ? `RV32_NOP : (w_cinsn) ? w_ir_t : w_ir_org;
    always@(posedge CLK) if(state == `S_CVT) begin 
        r_ir    <= w_ir;
        r_cinsn <= w_cinsn;
        if(!w_busy) r_ir16  <= w_ir_org[31:16];
    end


    wire [31:0] w_imm;
    m_imm_gen imm_gen0(r_ir, w_imm);

    wire [4:0] w_rs1 = r_ir[19:15];
    wire [4:0] w_rs2 = r_ir[24:20];
                      
    wire [31:0] w_rrs1, w_rrs2;
    wire w_regfile_we = (w_wb_r_enable && state==`S_WB);
    m_regfile regs(CLK, w_rs1, w_rs2, w_rrs1, w_rrs2, w_regfile_we, r_rd, w_wb_r_data);

    always @(posedge CLK) if(state == `S_ID) begin
        r_rrs1    <= w_rrs1;
        r_rrs2    <= w_rrs2;
        r_opcode  <= r_ir[ 6: 0];
        r_rd      <= r_ir[11: 7];
        r_rs1     <= r_ir[19:15];
        r_rs2     <= r_ir[24:20];
        r_funct3  <= r_ir[14:12];
        r_funct5  <= r_ir[31:27];
        r_funct7  <= r_ir[31:25];
        r_funct12 <= r_ir[31:20];
        r_imm     <= w_imm;
    end

    wire w_op_priv = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]==`FUNCT3_PRIV__);
    wire w_op_csr  = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]!=`FUNCT3_PRIV__);
    always @(posedge CLK) if(state == `S_ID) begin
        r_op_AMO_SC   <= (r_ir[31:27]==`FUNCT5_AMO_SC__);
        r_op_AMO_LR   <= (r_ir[31:27]==`FUNCT5_AMO_LR__);
        r_op_LOAD     <= (r_ir[ 6: 0]==`OPCODE_LOAD____);
        r_op_STORE    <= (r_ir[ 6: 0]==`OPCODE_STORE___);
        r_op_AMO      <= (r_ir[ 6: 0]==`OPCODE_AMO_____);
        r_op_SYS      <= (r_ir[ 6: 0]==`OPCODE_SYSTEM__);
        r_op_ECALL    <= (w_op_priv && r_ir[31:20]==`FUNCT12_ECALL_);
        r_op_SRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_SRET__);
        r_op_MRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_MRET__);
        r_op_CSR_MSTA <= (w_op_csr  && r_ir[31:20]==`CSR_MSTATUS);
        r_op_CSR_SSTA <= (w_op_csr  && r_ir[31:20]==`CSR_SSTATUS);
    end
    

    wire signed [31:0] w_sin1 = r_rrs1;
    wire signed [31:0] w_sin2 = r_rrs2;

    wire [63:0] w_mul_SS = {{32{w_sin1[31]}},w_sin1} * {{32{w_sin2[31]}},w_sin2};
    wire [63:0] w_mul_SU = {{32{w_sin1[31]}},w_sin1} * {32'b0, r_rrs2};
    wire [63:0] w_mul_UU = {32'b0, r_rrs1} * {32'b0, r_rrs2};

    wire [31:0] w_mem_addr = (r_op_LOAD || r_op_STORE) ? r_rrs1+r_imm : (r_op_AMO) ? r_rrs1 : 0;
    
    reg [63:0]  r_mul_SS =0;
    reg [63:0]  r_mul_SU =0;
    reg [63:0]  r_mul_UU =0;
    always @(posedge CLK) if(state == `S_OF) begin
        r_mem_addr <= w_mem_addr;
        r_mul_SS   <= w_mul_SS;
        r_mul_SU   <= w_mul_SU;
        r_mul_UU   <= w_mul_UU;
        r_rcsr     <= r_rcsr_t;
        r_alu_in2  <= (r_opcode==`OPCODE_OP_IMM__) ? r_imm : w_rrs2;
        r_alu_f7   <= (r_opcode==`OPCODE_OP_IMM__) ?
                      ((r_funct3==`FUNCT3_ADD___) ? 0 : r_funct7 & 7'h20) : r_funct7;;
    end
    

    wire [31:0] w_alu_im_rslt;
    wire        w_alu_b_rslt;
    wire [31:0] w_alu_c_rslt;
    wire        w_ex1 = (state == `S_EX1);
    wire        w_ex1_busy;

    m_alu_im ALU_IM(CLK, RST_X, w_ex1, r_rrs1, r_alu_in2, r_funct3, r_alu_f7, w_alu_im_rslt,
                    w_ex1_busy, r_mul_SS, r_mul_SU, r_mul_UU);
    m_alu_b  ALU_B(r_rrs1, r_alu_in2, r_funct3, w_alu_b_rslt);
    m_alu_c  ALU_C(r_rcsr, r_rrs1, r_imm, r_funct3, w_alu_c_rslt);

    always @(posedge CLK) begin
        if(w_pagefault != ~0) begin
            pending_exception <= w_pagefault;
        end
        else if(state == `S_INI) begin
            pending_exception <= ~0;
            r_tkn             <= 0;
        end
        else if(state == `S_FIN && !w_busy) begin
            if(w_interrupt_mask != 0) begin
                pending_exception <= `CAUSE_INTERRUPT | irq_num;
            end
        end
        else if(state == `S_EX1) begin
            case(r_opcode)
                `OPCODE_LUI_____ : begin r_wb_data  <= r_imm;          end
                `OPCODE_AUIPC___ : begin r_wb_data  <= pc + r_imm;     end
                `OPCODE_OP______ : begin r_wb_data  <= w_alu_im_rslt;  end
                `OPCODE_OP_IMM__ : begin r_wb_data  <= w_alu_im_rslt;  end
                `OPCODE_LOAD____ : begin end
                `OPCODE_STORE___ : begin end
                `OPCODE_JAL_____ : begin
                    r_tkn       <= 1;
                    r_wb_data   <= (r_cinsn) ? pc+2 : pc+4;
                    r_jmp_pc    <= pc + r_imm;
                end
                `OPCODE_JALR____ : begin
                    r_tkn       <= 1;
                    r_wb_data   <= (r_cinsn) ? pc+2 : pc+4;
                    r_jmp_pc    <= r_rrs1 + r_imm;
                end
                `OPCODE_AMO_____ : begin
                    if(r_op_AMO_SC) begin
                        r_wb_data <= !((r_rrs1==load_res) && reserved);
                    end
                end
                `OPCODE_BRANCH__ : begin
                    r_tkn       <= w_alu_b_rslt;
                    r_jmp_pc    <= pc + r_imm;
                end
                `OPCODE_MISC_MEM : begin end
                `OPCODE_SYSTEM__ : begin
                    if(r_funct3 == `FUNCT3_PRIV__) begin
                        case (r_funct12)
                            `FUNCT12_ECALL_ : begin
                                r_wb_data_csr       <= `CAUSE_USER_ECALL + priv;
                                pending_exception   <= `CAUSE_USER_ECALL + priv;
                            end
                            `FUNCT12_EBREAK : begin end
                            `FUNCT12_URET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_SRET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_MRET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_WFI___ : begin end
                            default: begin
                                if(r_funct7==`FUNCT7_SFENCE_VMA) r_tkn <= 0;
                            end
                        endcase
                    end else begin
                        r_wb_data_csr <= w_alu_c_rslt;
                    end
                end



           endcase
        end
    end


    reg [2:0] r_data_ctrl=0;
    always @(posedge CLK) r_data_ctrl <= (r_op_AMO) ? 3'h2 : r_funct3;
    
    assign w_data_ctrl = r_data_ctrl;
    assign w_data_addr = r_mem_addr;
    
    wire [31:0] w_mem_rdata = w_data_data;
    always@(posedge CLK) begin

        if(state == `S_COM && (r_op_AMO && r_op_AMO_LR) && !w_busy) begin
            load_res <= r_mem_addr;
            reserved <= 1;
        end
        if(state == `S_WB && r_op_AMO && r_op_AMO_SC && !r_wb_data[0] && !w_busy) begin
            reserved <= 0;
        end
    end


    wire [31:0] w_alu_a_rslt;
    m_alu_a ALU_A (r_rrs2, w_mem_rdata, r_funct5, w_alu_a_rslt);

    always @(posedge CLK) if(state == `S_EX2) begin
        r_mem_rdata  <= w_mem_rdata;
        r_atom_wdata <= w_alu_a_rslt;
    end


    reg [31:0] r_data_wdata=0;
    always@(posedge CLK) begin
        if     (state==`S_LD ) r_data_wdata <= r_rrs2;
        else if(state==`S_EX2) r_data_wdata <= w_alu_a_rslt;
    end
    
    assign w_data_wdata = r_data_wdata;


    assign w_wb_r_data =    (r_op_LOAD)                ? w_mem_rdata :
                            (r_op_AMO && !r_op_AMO_SC) ? r_mem_rdata :
                            (r_op_SYS && r_funct3!=`FUNCT3_PRIV__) ? r_rcsr : r_wb_data;

    assign w_wb_r_enable =  (r_op_LOAD)                    ? 1 :
                            (r_opcode == `OPCODE_LUI_____) ? 1 :
                            (r_opcode == `OPCODE_AUIPC___) ? 1 :
                            (r_opcode == `OPCODE_JAL_____) ? 1 :
                            (r_opcode == `OPCODE_JALR____) ? 1 :
                            (r_opcode == `OPCODE_OP______) ? 1 :
                            (r_opcode == `OPCODE_OP_IMM__) ? 1 :
                            (r_op_AMO)                     ? 1 :
                            (r_op_SYS && r_funct3!=`FUNCT3_PRIV__) ? 1 : 0;

    reg [31:0] r_mstatus_t = 0;
    reg  [1:0] r_priv_t    = `PRIV_M;

    always@(posedge CLK) begin
        if(state==`S_INI) r_mstatus_t <= mstatus;
        else if(state == `S_WB) begin
            if(r_op_SYS && r_funct3 == `FUNCT3_PRIV__) begin
                case (r_funct12)
                    `FUNCT12_SRET__ : begin
                        r_mstatus_t <= (((mstatus & ~(1<<mstatus[8])) | (mstatus[5] << mstatus[8])) | 32'h20) & ~32'h100;
                        r_priv_t    <= mstatus[8];
                    end
                    `FUNCT12_MRET__ : begin
                        r_mstatus_t <= (((mstatus & ~(1 << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                         | (mstatus[`MSTATUS_MPIE_SHIFT] << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                        | `MSTATUS_MPIE) & ~`MSTATUS_MPP;
                        r_priv_t    <= mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT];
                    end
                    default: begin
                        r_mstatus_t <= mstatus;
                        r_priv_t    <= priv;
                    end
                endcase
            end
            else begin
                r_mstatus_t <= mstatus;
                r_priv_t    <= priv;
            end
        end
    end


    wire [31:0] w_mstatus_nxt;

    wire [31:0] pending_interrupts = mip & mie;
    wire [31:0] enable_interrupts  = (pending_interrupts) ? (r_priv_t == `PRIV_M) ? ((w_mstatus_nxt & `MSTATUS_MIE) ? ~mideleg : 0) :
                                                            (r_priv_t == `PRIV_S) ? ((w_mstatus_nxt & `MSTATUS_SIE) ? (~mideleg | mideleg) : ~mideleg) :
                                                            (r_priv_t == `PRIV_U) ? ~0 : 0 : 0;
    assign w_interrupt_mask = pending_interrupts & enable_interrupts;
    assign w_irq_t          = w_interrupt_mask & (~w_interrupt_mask+1);

    always@(posedge CLK) begin
        if(state == `S_COM) begin
            case (w_irq_t)
                32'h00000001: irq_num <= 0;
                32'h00000002: irq_num <= 1;
                32'h00000004: irq_num <= 2;
                32'h00000008: irq_num <= 3;
                32'h00000010: irq_num <= 4;
                32'h00000020: irq_num <= 5;
                32'h00000040: irq_num <= 6;
                32'h00000080: irq_num <= 7;
                32'h00000100: irq_num <= 8;
                32'h00000200: irq_num <= 9;
                32'h00000400: irq_num <= 10;
                32'h00000800: irq_num <= 11;
                32'h00001000: irq_num <= 12;
                32'h00002000: irq_num <= 13;
                32'h00004000: irq_num <= 14;
                32'h00008000: irq_num <= 15;
                32'h00010000: irq_num <= 16;
                32'h00020000: irq_num <= 17;
                32'h00040000: irq_num <= 18;
                32'h00080000: irq_num <= 19;
                32'h00100000: irq_num <= 20;
                32'h00200000: irq_num <= 21;
                32'h00400000: irq_num <= 22;
                32'h00800000: irq_num <= 23;
                32'h01000000: irq_num <= 24;
                32'h02000000: irq_num <= 25;
                32'h04000000: irq_num <= 26;
                32'h08000000: irq_num <= 27;
                32'h10000000: irq_num <= 28;
                32'h20000000: irq_num <= 29;
                32'h40000000: irq_num <= 30;
                32'h80000000: irq_num <= 31;
                default:      irq_num <= 32;
            endcase
        end
    end

    wire [31:0] cause = (pending_exception != ~0) ? pending_exception : (`CAUSE_INTERRUPT | irq_num);
    wire [31:0] w_deleg = (r_priv_t <= `PRIV_S) ? ((cause & `CAUSE_INTERRUPT) ? (mideleg >> (cause & 32'h1f))  & 1 :
                                                                                (medeleg >> (cause & 32'h1f))) & 1 : 0;

    always @(posedge CLK) begin
        if(!RST_X || r_halt) begin pc <= `D_START_PC; end
        else if(w_pagefault != ~32'h0) begin  pending_tval <= (state==`S_IF) ? pc : (state!=`S_LD && state!=`S_SD) ? 0 : r_mem_addr; end
        else if(state==`S_FIN && !w_busy) begin
            if(pending_exception != ~0)   begin pc <= (w_deleg) ? stvec : mtvec; end
            else begin
                if(w_interrupt_mask != 0) begin pc <= (w_deleg) ? stvec : mtvec; end
                else                      begin pc <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4; end
            end
            r_ir16_v    <= !((pending_exception != ~0) || (w_interrupt_mask != 0) || (r_tkn) || (!r_cinsn));
        end
        else if(state==`S_INI) begin
            pending_tval <= 0;
        end
    end
    

    always@(posedge CLK) begin
`ifdef REAL_MTIME
        if(RST_X) mtime <= mtime + 1;
`endif
        if(state == `S_FIN && !w_busy) begin 
`ifndef REAL_MTIME
            mtime <= mtime + 1;
`endif
            if((pending_exception == ~0) ||
               (pending_exception != ~0 && (pending_exception & `CAUSE_INTERRUPT)) ||
               (pending_exception != ~0 && r_op_ECALL)) begin
                e_icount <= e_icount + 1;
            end
        end
    end


    wire [11:0] w_csr_addr = (r_funct3  != `FUNCT3_PRIV__ )  ? r_funct12 :
                             (r_funct12 == `FUNCT12_ECALL_)  ? `CSR_MTVEC:
                             (r_funct12 == `FUNCT12_URET__)  ? `CSR_UEPC :
                             (r_funct12 == `FUNCT12_SRET__)  ? `CSR_SEPC :
                             (r_funct12 == `FUNCT12_MRET__)  ? `CSR_MEPC : 0;
    
    wire [31:0] w_sstatus_t = (mstatus | 32'h6000) & 32'h000de133;
    wire [31:0] w_mstatus_t = (mstatus | 32'h6000);

    always@(*) begin
        case(w_csr_addr)
            12'h3A0         : r_rcsr_t = 0;
            12'h3B0         : r_rcsr_t = 0;
            `CSR_FFLAGS     : r_rcsr_t = 0;
            `CSR_FRM        : r_rcsr_t = 0;
            `CSR_FCSR       : r_rcsr_t = 0;
            `CSR_SIE        : r_rcsr_t = mie & mideleg;
            `CSR_STVEC      : r_rcsr_t = stvec;
            `CSR_SCOUNTEREN : r_rcsr_t = scounteren;
            `CSR_SSCRATCH   : r_rcsr_t = sscratch;
            `CSR_SEPC       : r_rcsr_t = sepc;
            `CSR_SCAUSE     : r_rcsr_t = scause;
            `CSR_STVAL      : r_rcsr_t = stval;
            `CSR_SIP        : r_rcsr_t = mip & mideleg;
            `CSR_SATP       : r_rcsr_t = satp;

            `CSR_MEDELEG    : r_rcsr_t = medeleg;
            `CSR_MIDELEG    : r_rcsr_t = mideleg;
            `CSR_MIE        : r_rcsr_t = mie;
            `CSR_MTVEC      : r_rcsr_t = mtvec;
            `CSR_MCOUNTEREN : r_rcsr_t = mcounteren;
            `CSR_MSCRATCH   : r_rcsr_t = mscratch;
            `CSR_MEPC       : r_rcsr_t = mepc;
            `CSR_MCAUSE     : r_rcsr_t = mcause;
            `CSR_MTVAL      : r_rcsr_t = mtval;
            `CSR_MIP        : r_rcsr_t = mip;
            `CSR_MISA       : r_rcsr_t = misa | 32'h40000000;

            `CSR_MCYCLE     : r_rcsr_t = mtime[31:0];
            `CSR_MINSTRET   : r_rcsr_t = mtime[31:0];
            `CSR_CYCLE      : r_rcsr_t = mtime[31:0];
            `CSR_INSTRET    : r_rcsr_t = mtime[31:0];
            `CSR_TIME       : r_rcsr_t = mtime[31:0];

            `CSR_MCYCLEH    : r_rcsr_t = mtime[63:32];
            `CSR_MINSTRETH  : r_rcsr_t = mtime[63:32];
            `CSR_CYCLEH     : r_rcsr_t = mtime[63:32];
            `CSR_INSTRETH   : r_rcsr_t = mtime[63:32];
            `CSR_TIMEH      : r_rcsr_t = mtime[63:32];

            `CSR_SSTATUS    : r_rcsr_t = (w_sstatus_t[31:13]==3 | w_sstatus_t[31:15]==3) ? (w_sstatus_t | 32'h80000000) : w_sstatus_t;
            `CSR_MSTATUS    : r_rcsr_t = (w_mstatus_t[31:13]==3 | w_mstatus_t[31:15]==3) ? (w_mstatus_t | 32'h80000000) : w_mstatus_t;
            `CSR_MHARTID    : r_rcsr_t = mhartid;
            default         : r_rcsr_t = 0;
        endcase
    end


    wire        w_csr_we    = (r_op_SYS) && (r_funct3 != `FUNCT3_PRIV__);
    wire [31:0] w_sstatus   = (mstatus & ~`SSTATUS_MASK) | (r_wb_data_csr & `SSTATUS_MASK);

    wire [31:0] w_sstatus_t1 = (w_mstatus_nxt & ~`MSTATUS_SPIE) | (((w_mstatus_nxt >> r_priv_t) & 1) << `MSTATUS_SPIE_SHIFT);
    wire [31:0] w_sstatus_t2 = (w_sstatus_t1  & ~`MSTATUS_SPP) | (r_priv_t << `MSTATUS_SPP_SHIFT);
    wire [31:0] w_sstatus_t3 = (w_sstatus_t2  & ~`MSTATUS_SIE);
    wire [31:0] w_mstatus_t1 = (w_mstatus_nxt & ~`MSTATUS_MPIE) | (((w_mstatus_nxt >> r_priv_t) & 1) << `MSTATUS_MPIE_SHIFT);
    wire [31:0] w_mstatus_t2 = (w_mstatus_t1  & ~`MSTATUS_MPP) | (r_priv_t << `MSTATUS_MPP_SHIFT);
    wire [31:0] w_mstatus_t3 = (w_mstatus_t2  & ~`MSTATUS_MIE);

    always@(posedge CLK) begin
        if(state == `S_IF) begin
            if(mtime > `ENABLE_TIMER) begin
                if(w_plic_we) begin
                    mip <= w_wmip;
                end
                else if(mtimecmp < mtime) begin
                    mip <= mip | `MIP_MTIP;
                end
            end
        end

        if(state == `S_EX2 || state == `S_WB) begin
            if(w_plic_we) begin
                mip <= w_wmip;
            end
        end
        if(state == `S_SD && !w_busy) begin
            if(w_clint_we) begin
                mtimecmp    <= w_wmtimecmp;
                mip         <= mip & ~`MIP_MTIP;
            end
        end

        if(state == `S_FIN && !w_busy) begin
            if(pending_exception != ~0) begin
                if(w_deleg) begin
                    scause  <= cause;
                    sepc    <= pc;
                    stval   <= pending_tval;
                    mstatus <= w_sstatus_t3;
                    priv    <= `PRIV_S;
                end else begin
                    mcause  <= cause;
                    mepc    <= pc;
                    mtval   <= pending_tval;
                    mstatus <= w_mstatus_t3;
                    priv    <= `PRIV_M;
                end
            end
            else if(w_interrupt_mask != 0) begin
                if(w_deleg) begin
                    scause  <= cause;
                    sepc    <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4;
                    stval   <= pending_tval;
                    mstatus <= w_sstatus_t3;
                    priv    <= `PRIV_S;
                end else begin
                    mcause  <= cause;
                    mepc    <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4;
                    mtval   <= pending_tval;
                    mstatus <= w_mstatus_t3;
                    priv    <= `PRIV_M;
                end
            end
        end

        else if(state == `S_COM && !w_busy) begin
            if(r_opcode == `OPCODE_SYSTEM__ && r_funct3 == `FUNCT3_PRIV__) begin
                case (r_funct12)
                    `FUNCT12_URET__ : begin
                    end
                    `FUNCT12_SRET__ : begin
                        mstatus <= (((mstatus & ~(1<<mstatus[8])) | (mstatus[5] << mstatus[8])) | 32'h20) & ~32'h100;
                        priv    <= mstatus[8];
                    end
                    `FUNCT12_MRET__ : begin
                        mstatus <= (((mstatus & ~(1 << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT]))
                                     | (mstatus[`MSTATUS_MPIE_SHIFT] << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                    | `MSTATUS_MPIE) & ~`MSTATUS_MPP;
                        priv    <= mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT];
                    end
                endcase
            end
            else if(w_csr_we) begin
                case(r_funct12)
                    `CSR_STVEC      : stvec      <= r_wb_data_csr & ~3;
                    `CSR_SCOUNTEREN : scounteren <= r_wb_data_csr & 5;
                    `CSR_SSCRATCH   : sscratch   <= r_wb_data_csr;
                    `CSR_SEPC       : sepc       <= r_wb_data_csr & ~1;
                    `CSR_SCAUSE     : scause     <= r_wb_data_csr;
                    `CSR_STVAL      : stval      <= r_wb_data_csr;

                    `CSR_MTVEC      : mtvec      <= r_wb_data_csr & ~3;
                    `CSR_MCOUNTEREN : mcounteren <= r_wb_data_csr & 5;
                    `CSR_MSCRATCH   : mscratch   <= r_wb_data_csr;
                    `CSR_MEPC       : mepc       <= r_wb_data_csr & ~1;
                    `CSR_MCAUSE     : mcause     <= r_wb_data_csr;
                    `CSR_MTVAL      : mtval      <= r_wb_data_csr;

                    `CSR_SIE        : mie        <= (mie & ~mideleg) | (r_wb_data_csr & mideleg);
                    `CSR_SIP        : mip        <= (mip & ~mideleg) | (r_wb_data_csr & mideleg);

                    `CSR_MEDELEG    : medeleg    <= (medeleg & ~`WCSR_MASK1) | (r_wb_data_csr & `WCSR_MASK1);
                    `CSR_MIDELEG    : mideleg    <= (mideleg & ~`WCSR_MASK2) | (r_wb_data_csr & `WCSR_MASK2);
                    `CSR_MIE        : mie        <= (mie & ~`WCSR_MASK3) | (r_wb_data_csr & `WCSR_MASK3);
                    `CSR_MIP        : mip        <= (mip & ~`WCSR_MASK4) | (r_wb_data_csr & `WCSR_MASK4);

                    `CSR_SATP       : satp       <= r_wb_data_csr;

                    `CSR_MSTATUS    : mstatus    <= (mstatus & ~`MASK_STATUS) | (r_wb_data_csr & `MASK_STATUS);
                    `CSR_SSTATUS    : mstatus    <= (mstatus & ~`MASK_STATUS) | (w_sstatus & `MASK_STATUS);
                endcase
            end
        end
    end

    assign w_mstatus_nxt =  (pending_exception != ~0)             ? r_mstatus_t :
                        (w_csr_we && r_funct12 == `CSR_MSTATUS) ? (mstatus & ~`MASK_STATUS) | (r_wb_data_csr & `MASK_STATUS) :
                        (w_csr_we && r_funct12 == `CSR_SSTATUS) ? (mstatus & ~`MASK_STATUS) | (w_sstatus & `MASK_STATUS) : r_mstatus_t;


    reg  r_tlb_flush;
    wire [31:0] w_data_t = (r_funct12==`CSR_MSTATUS) ? r_wb_data_csr : w_sstatus;
    wire [31:0] w_mod    = w_data_t ^ mstatus;
    
    assign w_tlb_flush   = r_tlb_flush;


    always@(*) begin


        if(state==`S_COM && !w_busy) begin
            if(pending_exception != ~0 || w_interrupt_mask != 0) r_tlb_flush <= 1;
            else if(r_op_SRET || r_op_MRET) r_tlb_flush <= 1;
            else if(r_op_CSR_MSTA) begin
                if((w_mod & (`MSTATUS_MPRV | `MSTATUS_SUM | `MSTATUS_MXR)) != 0 ||
                   ((mstatus & `MSTATUS_MPRV) && (w_mod & `MSTATUS_MPP) != 0)) begin
                    r_tlb_flush <= 1;
                end
            end
            else if(r_op_CSR_SSTA) begin
                if((w_mod & (`MSTATUS_MPRV | `MSTATUS_SUM | `MSTATUS_MXR)) != 0 ||
                   ((mstatus & `MSTATUS_MPRV) && (w_mod & `MSTATUS_MPP) != 0)) begin
                    r_tlb_flush <= 1;
                end
            end
            else r_tlb_flush <= 0;
        end
        else r_tlb_flush <= 0;
    end


    wire w_com = ((pending_exception!=~0 || w_pagefault!=~0 || (state==`S_EX1 && r_op_ECALL)) 
                  && state!=`S_COM && state!=`S_FIN && state!=`S_INI);

    assign w_state = (!RST_X | r_halt)                                         ? 0      :
                     (w_com)                                                   ? `S_COM :
                     (w_busy || w_ex1_busy)                                    ? state  :
                     (state==`S_FIN)                                           ? `S_INI :
                     (state==`S_IF  && w_nalign4 && r_if_state!=3)             ? `S_IF  :
                     (state==`S_EX1 && !r_op_AMO && !r_op_LOAD && !r_op_STORE) ? `S_WB  :
                     (state==`S_LD  && r_op_STORE)                             ? `S_SD  :
                     (state==`S_LD  && r_op_LOAD)                              ? `S_WB  : state+1;
         
    always @(posedge CLK) state <= w_state;

    reg [2:0] r_com;
    always @(posedge CLK) r_com <= (state!=`S_COM && state!=`S_FIN && state!=`S_INI) ? {pending_exception!=~0, w_pagefault!=~0, (state==`S_EX1 && r_op_ECALL)} : 0;


    wire w_d_we_t = (w_state==`S_SD && (r_op_STORE || 
                                        (r_op_AMO &&  r_op_AMO_SC && !r_wb_data[0]) || 
                                        (r_op_AMO && !r_op_AMO_LR && !r_op_AMO_SC)));
    wire w_d_en_t = (w_state==`S_LD && (r_op_LOAD || (r_op_AMO && (!r_op_AMO_SC))));

         
    reg       r_data_we=0;
    reg       r_data_en=0;
    reg [2:0] r_tlb_req=0;
    always @(posedge CLK) begin
        r_data_we <= w_d_we_t;
        r_data_en <= w_d_en_t;
        r_tlb_req <= (w_state==`S_IF && w_if_state!=1) ? `ACCESS_CODE  :
                     (w_d_en_t)                        ? `ACCESS_READ  :
                     (w_d_we_t)                        ? `ACCESS_WRITE : 2'h3;
    end

    assign w_tlb_req  = r_tlb_req;
    assign w_data_we  = r_data_we;
    assign w_priv     = priv;
    assign w_satp     = satp;
    assign w_mstatus  = mstatus;
    assign w_mtime    = mtime;
    assign w_mtimecmp = mtimecmp;
    assign w_mip      = mip;


    initial r_halt = 0;
    always @(posedge CLK) if(r_opcode==`OPCODE_HALT____) r_halt <= 1;

    assign w_core_pc = pc;
    assign w_core_ir = r_ir;
    assign w_core_odata = 0;
endmodule
module m_RVCoreM(CLK, RST_X, w_stall, r_halt, w_insn_addr, w_data_addr, w_insn_data, w_data_data,
                w_data_wdata, w_data_we, w_data_ctrl, w_priv, w_satp, w_mstatus, w_mtime,
                w_mtimecmp, w_wmtimecmp, w_clint_we, w_mip, w_wmip, w_plic_we, w_busy, w_pagefault,
                w_tlb_req, w_tlb_flush, w_core_pc, w_core_ir, w_core_odata, w_init_stage);

    input  wire         CLK, RST_X, w_stall;
    input  wire [31:0]  w_insn_data, w_data_data;
    input  wire [63:0]  w_wmtimecmp;
    input  wire         w_clint_we;
    input  wire [31:0]  w_wmip;
    input  wire         w_plic_we;
    input  wire         w_busy;
    input  wire [31:0]  w_pagefault;

    output reg          r_halt;
    output wire [31:0]  w_core_odata;
    output wire [31:0]  w_data_wdata;
    output wire [31:0]  w_insn_addr;
    output wire [2:0]   w_data_ctrl;
    output wire [31:0]  w_data_addr;
    output wire [63:0]  w_mtime;
    output wire [63:0]  w_mtimecmp;
    output wire [31:0]  w_priv;
    output wire [31:0]  w_satp;
    output wire [31:0]  w_mstatus;
    output wire [31:0]  w_mip;
    output wire [31:0]  w_core_pc;
    output wire [31:0]  w_core_ir;
    output wire         w_init_stage;
    output wire  [1:0]  w_tlb_req;
    output wire         w_data_we;
    output wire         w_tlb_flush;


    reg   [3:0] state          = 0;
    reg  [31:0] pc             = `D_START_PC;

    reg  [31:0] mstatus        = 0;
    reg  [31:0] mtvec          = 0;
    reg  [31:0] mscratch       = 0;
    reg  [31:0] mepc           = 0;
    reg  [31:0] mcause         = 0;
    reg  [31:0] mtval          = 0;
    reg  [31:0] mhartid        = 0;
    reg  [31:0] misa           = 32'h00141105;
    reg  [31:0] mie            = 0;
    reg  [31:0] mip            = 0;
    reg  [31:0] medeleg        = 0;
    reg  [31:0] mideleg        = 0;
    reg  [31:0] mcounteren     = 0;
    reg  [31:0] stvec          = 0;
    reg  [31:0] sscratch       = 0;
    reg  [31:0] sepc           = 0;
    reg  [31:0] scause         = 0;
    reg  [31:0] stval          = 0;
    reg  [31:0] satp           = 0;
    reg  [31:0] scounteren     = 0;
    
    reg  [31:0] load_res       = 0;
    reg         reserved       = 0;
    reg   [1:0] priv           = `PRIV_M;
    reg  [63:0] mtime          = 1;
    reg  [63:0] mtimecmp       = 1;
    reg  [31:0] pending_tval   = 0;
    reg  [31:0] pending_exception = ~0;


    reg  [31:0] r_cpc          = 0;
    reg  [31:0] r_ir_org       = 0;

    reg         r_cinsn        = 0;
    reg  [31:0] r_ir           = 0;
    reg  [15:0] r_ir16         = 0;
    reg         r_ir16_v       = 0;

    reg   [6:0] r_opcode       = 0;
    reg   [4:0] r_rd           = 0;
    reg   [4:0] r_rs1          = 0;
    reg   [4:0] r_rs2          = 0;
    reg   [2:0] r_funct3       = 0;
    reg   [4:0] r_funct5       = 0;
    reg   [6:0] r_funct7       = 0;
    reg  [11:0] r_funct12      = 0;
    reg  [31:0] r_imm          = 0;
    reg         r_op_AMO_SC    = 0;
    reg         r_op_AMO_LR    = 0;
    reg         r_op_LOAD      = 0;
    reg         r_op_STORE     = 0;
    reg         r_op_AMO       = 0;
    reg         r_op_SYS       = 0;
    reg         r_op_ECALL     = 0;
    reg         r_op_SRET      = 0;
    reg         r_op_MRET      = 0;
    reg         r_op_CSR_MSTA  = 0;
    reg         r_op_CSR_SSTA  = 0; 

    reg  [31:0] r_rrs1         = 0;
    reg  [31:0] r_rrs2         = 0;
    reg  [31:0] r_rcsr         = 0;
    reg  [31:0] r_alu_in2      = 0;
    reg   [6:0] r_alu_f7       = 0;

    reg         r_tkn          = 0;
    reg  [31:0] r_jmp_pc       = 0;
    reg  [31:0] r_mem_addr     = 0;
    reg  [31:0] r_wb_data      = 0;
    reg  [31:0] r_wb_data_csr  = 0;

    reg  [31:0] r_mem_rdata    = 0;
    reg  [31:0] r_atom_wdata   = 0;


    reg  [63:0] e_icount    = 1;
    reg         r_if_done   = 0;
    reg  [15:0] r_if_irl    = 0;
    reg  [31:0] r_rcsr_t    = 0;
    reg  [31:0] irq_num     = 0;
    reg   [1:0] r_if_state  = 0;


    wire [31:0] w_wb_r_data;
    wire        w_wb_r_enable;
    wire [31:0] w_interrupt_mask;
    wire [31:0] w_irq_t;
    wire [3:0]  w_state;
    

    reg r_init_stage=0;
    always@(posedge CLK) r_init_stage <= (w_state==`S_INI);
                                        
    assign w_init_stage = r_init_stage;


    wire [31:0] w_vadr1 = {pc[31:2], 2'b0};
    wire [31:0] w_vadr2 = pc + 2;
    wire        w_nalign4 = (pc[3:1]==3'b111);
    wire        w_usestate = (w_nalign4 && !r_ir16_v);

    always@(posedge CLK) begin
        if(state==`S_IF && r_if_state==1 && !w_busy) r_if_irl <= w_insn_data[31:16];
        if(state==`S_IF && w_pagefault==~0) begin r_cpc <= pc; end
    end

    wire [1:0] w_if_state = ((!(state==`S_IF || state==`S_CVT)) || w_pagefault!=~0) ? 0 :
                            (r_if_state==0 && w_nalign4 && !w_busy)                 ? (r_ir16_v) ? 3 : 1 :
                            (r_if_state==1 &&              !w_busy)                 ? 2 :
                            (r_if_state==2 &&              !w_busy)                 ? 3 : r_if_state;
    
    always@(posedge CLK) r_if_state <= w_if_state;

    reg [31:0] r_insn_addr=0;
    always@(posedge CLK) begin
        r_insn_addr <=  (w_nalign4 && r_ir16_v) ? w_vadr2 :
                        (w_if_state==2 || w_if_state==3) ? w_vadr2 :
                        (w_usestate) ? w_vadr1 : pc;
    end
    assign w_insn_addr = r_insn_addr;
      
    wire [31:0] w_ir_org = (r_if_state == 3) ? (r_ir16_v) ? {w_insn_data[15:0], r_ir16} :
                                                            {w_insn_data[15:0], r_if_irl} :
                                                w_insn_data;


    wire w_cinsn = (w_ir_org[1:0] != 2'b11);
    
    wire [31:0] w_ir_t;
    m_decomp decomp0(w_ir_org, w_ir_t);
    
    wire w_nop = (w_ir_t[6:0]==`OPCODE_OP_FP___ ||  
                  w_ir_t[6:0]==`OPCODE_LOAD_FP_ ||  w_ir_t[6:0]==`OPCODE_STORE_FP);

    wire [31:0] w_ir = (w_nop) ? `RV32_NOP : (w_cinsn) ? w_ir_t : w_ir_org;
    always@(posedge CLK) if(state == `S_CVT) begin 
        r_ir    <= w_ir;
        r_cinsn <= w_cinsn;
        if(!w_busy) r_ir16  <= w_ir_org[31:16];
    end


    wire [31:0] w_imm;
    m_imm_gen imm_gen0(r_ir, w_imm);

    wire [4:0] w_rs1 = r_ir[19:15];
    wire [4:0] w_rs2 = r_ir[24:20];
                      
    wire [31:0] w_rrs1, w_rrs2;
    wire w_regfile_we = (w_wb_r_enable && state==`S_WB);
    m_regfile regs(CLK, w_rs1, w_rs2, w_rrs1, w_rrs2, w_regfile_we, r_rd, w_wb_r_data);

    always @(posedge CLK) if(state == `S_ID) begin
        r_rrs1    <= w_rrs1;
        r_rrs2    <= w_rrs2;
        r_opcode  <= r_ir[ 6: 0];
        r_rd      <= r_ir[11: 7];
        r_rs1     <= r_ir[19:15];
        r_rs2     <= r_ir[24:20];
        r_funct3  <= r_ir[14:12];
        r_funct5  <= r_ir[31:27];
        r_funct7  <= r_ir[31:25];
        r_funct12 <= r_ir[31:20];
        r_imm     <= w_imm;
    end

    wire w_op_priv = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]==`FUNCT3_PRIV__);
    wire w_op_csr  = (r_ir[ 6: 0]==`OPCODE_SYSTEM__ && r_ir[14:12]!=`FUNCT3_PRIV__);
    always @(posedge CLK) if(state == `S_ID) begin
        r_op_AMO_SC   <= (r_ir[31:27]==`FUNCT5_AMO_SC__);
        r_op_AMO_LR   <= (r_ir[31:27]==`FUNCT5_AMO_LR__);
        r_op_LOAD     <= (r_ir[ 6: 0]==`OPCODE_LOAD____);
        r_op_STORE    <= (r_ir[ 6: 0]==`OPCODE_STORE___);
        r_op_AMO      <= (r_ir[ 6: 0]==`OPCODE_AMO_____);
        r_op_SYS      <= (r_ir[ 6: 0]==`OPCODE_SYSTEM__);
        r_op_ECALL    <= (w_op_priv && r_ir[31:20]==`FUNCT12_ECALL_);
        r_op_SRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_SRET__);
        r_op_MRET     <= (w_op_priv && r_ir[31:20]==`FUNCT12_MRET__);
        r_op_CSR_MSTA <= (w_op_csr  && r_ir[31:20]==`CSR_MSTATUS);
        r_op_CSR_SSTA <= (w_op_csr  && r_ir[31:20]==`CSR_SSTATUS);
    end
    

    wire signed [31:0] w_sin1 = r_rrs1;
    wire signed [31:0] w_sin2 = r_rrs2;

    wire [63:0] w_mul_SS = {{32{w_sin1[31]}},w_sin1} * {{32{w_sin2[31]}},w_sin2};
    wire [63:0] w_mul_SU = {{32{w_sin1[31]}},w_sin1} * {32'b0, r_rrs2};
    wire [63:0] w_mul_UU = {32'b0, r_rrs1} * {32'b0, r_rrs2};

    wire [31:0] w_mem_addr = (r_op_LOAD || r_op_STORE) ? r_rrs1+r_imm : (r_op_AMO) ? r_rrs1 : 0;
    
    reg [63:0]  r_mul_SS =0;
    reg [63:0]  r_mul_SU =0;
    reg [63:0]  r_mul_UU =0;
    always @(posedge CLK) if(state == `S_OF) begin
        r_mem_addr <= w_mem_addr;
        r_mul_SS   <= w_mul_SS;
        r_mul_SU   <= w_mul_SU;
        r_mul_UU   <= w_mul_UU;
        r_rcsr     <= r_rcsr_t;
        r_alu_in2  <= (r_opcode==`OPCODE_OP_IMM__) ? r_imm : w_rrs2;
        r_alu_f7   <= (r_opcode==`OPCODE_OP_IMM__) ?
                      ((r_funct3==`FUNCT3_ADD___) ? 0 : r_funct7 & 7'h20) : r_funct7;;
    end
    

    wire [31:0] w_alu_im_rslt;
    wire        w_alu_b_rslt;
    wire [31:0] w_alu_c_rslt;
    wire        w_ex1 = (state == `S_EX1);
    wire        w_ex1_busy;

    m_alu_im ALU_IM(CLK, RST_X, w_ex1, r_rrs1, r_alu_in2, r_funct3, r_alu_f7, w_alu_im_rslt,
                    w_ex1_busy, r_mul_SS, r_mul_SU, r_mul_UU);
    m_alu_b  ALU_B(r_rrs1, r_alu_in2, r_funct3, w_alu_b_rslt);
    m_alu_c  ALU_C(r_rcsr, r_rrs1, r_imm, r_funct3, w_alu_c_rslt);

    always @(posedge CLK) begin
        if(w_pagefault != ~0) begin
            pending_exception <= w_pagefault;
        end
        else if(state == `S_INI) begin
            pending_exception <= ~0;
            r_tkn             <= 0;
        end
        else if(state == `S_FIN && !w_busy) begin
            if(w_interrupt_mask != 0) begin
                pending_exception <= `CAUSE_INTERRUPT | irq_num;
            end
        end
        else if(state == `S_EX1) begin
            case(r_opcode)
                `OPCODE_LUI_____ : begin r_wb_data  <= r_imm;          end
                `OPCODE_AUIPC___ : begin r_wb_data  <= pc + r_imm;     end
                `OPCODE_OP______ : begin r_wb_data  <= w_alu_im_rslt;  end
                `OPCODE_OP_IMM__ : begin r_wb_data  <= w_alu_im_rslt;  end
                `OPCODE_LOAD____ : begin end
                `OPCODE_STORE___ : begin end
                `OPCODE_JAL_____ : begin
                    r_tkn       <= 1;
                    r_wb_data   <= (r_cinsn) ? pc+2 : pc+4;
                    r_jmp_pc    <= pc + r_imm;
                end
                `OPCODE_JALR____ : begin
                    r_tkn       <= 1;
                    r_wb_data   <= (r_cinsn) ? pc+2 : pc+4;
                    r_jmp_pc    <= r_rrs1 + r_imm;
                end
                `OPCODE_AMO_____ : begin
                    if(r_op_AMO_SC) begin
                        r_wb_data <= !((r_rrs1==load_res) && reserved);
                    end
                end
                `OPCODE_BRANCH__ : begin
                    r_tkn       <= w_alu_b_rslt;
                    r_jmp_pc    <= pc + r_imm;
                end
                `OPCODE_MISC_MEM : begin end
                `OPCODE_SYSTEM__ : begin
                    if(r_funct3 == `FUNCT3_PRIV__) begin
                        case (r_funct12)
                            `FUNCT12_ECALL_ : begin
                                r_wb_data_csr       <= `CAUSE_USER_ECALL + priv;
                                pending_exception   <= `CAUSE_USER_ECALL + priv;
                            end
                            `FUNCT12_EBREAK : begin end
                            `FUNCT12_URET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_SRET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_MRET__ : begin
                                r_tkn       <= 1;
                                r_jmp_pc    <= r_rcsr;
                            end
                            `FUNCT12_WFI___ : begin end
                            default: begin
                                if(r_funct7==`FUNCT7_SFENCE_VMA) r_tkn <= 0;
                            end
                        endcase
                    end else begin
                        r_wb_data_csr <= w_alu_c_rslt;
                    end
                end



           endcase
        end
    end


    reg [2:0] r_data_ctrl=0;
    always @(posedge CLK) r_data_ctrl <= (r_op_AMO) ? 3'h2 : r_funct3;
    
    assign w_data_ctrl = r_data_ctrl;
    assign w_data_addr = r_mem_addr;
    
    wire [31:0] w_mem_rdata = w_data_data;
    always@(posedge CLK) begin

        if(state == `S_COM && (r_op_AMO && r_op_AMO_LR) && !w_busy) begin
            load_res <= r_mem_addr;
            reserved <= 1;
        end
        if(state == `S_WB && r_op_AMO && r_op_AMO_SC && !r_wb_data[0] && !w_busy) begin
            reserved <= 0;
        end
    end


    wire [31:0] w_alu_a_rslt;
    m_alu_a ALU_A (r_rrs2, w_mem_rdata, r_funct5, w_alu_a_rslt);

    always @(posedge CLK) if(state == `S_EX2) begin
        r_mem_rdata  <= w_mem_rdata;
        r_atom_wdata <= w_alu_a_rslt;
    end


    reg [31:0] r_data_wdata=0;
    always@(posedge CLK) begin
        if     (state==`S_LD ) r_data_wdata <= r_rrs2;
        else if(state==`S_EX2) r_data_wdata <= w_alu_a_rslt;
    end
    
    assign w_data_wdata = r_data_wdata;


    assign w_wb_r_data =    (r_op_LOAD)                ? w_mem_rdata :
                            (r_op_AMO && !r_op_AMO_SC) ? r_mem_rdata :
                            (r_op_SYS && r_funct3!=`FUNCT3_PRIV__) ? r_rcsr : r_wb_data;

    assign w_wb_r_enable =  (r_op_LOAD)                    ? 1 :
                            (r_opcode == `OPCODE_LUI_____) ? 1 :
                            (r_opcode == `OPCODE_AUIPC___) ? 1 :
                            (r_opcode == `OPCODE_JAL_____) ? 1 :
                            (r_opcode == `OPCODE_JALR____) ? 1 :
                            (r_opcode == `OPCODE_OP______) ? 1 :
                            (r_opcode == `OPCODE_OP_IMM__) ? 1 :
                            (r_op_AMO)                     ? 1 :
                            (r_op_SYS && r_funct3!=`FUNCT3_PRIV__) ? 1 : 0;

    reg [31:0] r_mstatus_t = 0;
    reg  [1:0] r_priv_t    = `PRIV_M;

    always@(posedge CLK) begin
        if(state==`S_INI) r_mstatus_t <= mstatus;
        else if(state == `S_WB) begin
            if(r_op_SYS && r_funct3 == `FUNCT3_PRIV__) begin
                case (r_funct12)
                    `FUNCT12_SRET__ : begin
                        r_mstatus_t <= (((mstatus & ~(1<<mstatus[8])) | (mstatus[5] << mstatus[8])) | 32'h20) & ~32'h100;
                        r_priv_t    <= mstatus[8];
                    end
                    `FUNCT12_MRET__ : begin
                        r_mstatus_t <= (((mstatus & ~(1 << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                         | (mstatus[`MSTATUS_MPIE_SHIFT] << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                        | `MSTATUS_MPIE) & ~`MSTATUS_MPP;
                        r_priv_t    <= mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT];
                    end
                    default: begin
                        r_mstatus_t <= mstatus;
                        r_priv_t    <= priv;
                    end
                endcase
            end
            else begin
                r_mstatus_t <= mstatus;
                r_priv_t    <= priv;
            end
        end
    end


    wire [31:0] w_mstatus_nxt;

    wire [31:0] pending_interrupts = mip & mie;
    wire [31:0] enable_interrupts  = (pending_interrupts) ? (r_priv_t == `PRIV_M) ? ((w_mstatus_nxt & `MSTATUS_MIE) ? ~mideleg : 0) :
                                                            (r_priv_t == `PRIV_S) ? ((w_mstatus_nxt & `MSTATUS_SIE) ? (~mideleg | mideleg) : ~mideleg) :
                                                            (r_priv_t == `PRIV_U) ? ~0 : 0 : 0;
    assign w_interrupt_mask = pending_interrupts & enable_interrupts;
    assign w_irq_t          = w_interrupt_mask & (~w_interrupt_mask+1);

    always@(posedge CLK) begin
        if(state == `S_COM) begin
            case (w_irq_t)
                32'h00000001: irq_num <= 0;
                32'h00000002: irq_num <= 1;
                32'h00000004: irq_num <= 2;
                32'h00000008: irq_num <= 3;
                32'h00000010: irq_num <= 4;
                32'h00000020: irq_num <= 5;
                32'h00000040: irq_num <= 6;
                32'h00000080: irq_num <= 7;
                32'h00000100: irq_num <= 8;
                32'h00000200: irq_num <= 9;
                32'h00000400: irq_num <= 10;
                32'h00000800: irq_num <= 11;
                32'h00001000: irq_num <= 12;
                32'h00002000: irq_num <= 13;
                32'h00004000: irq_num <= 14;
                32'h00008000: irq_num <= 15;
                32'h00010000: irq_num <= 16;
                32'h00020000: irq_num <= 17;
                32'h00040000: irq_num <= 18;
                32'h00080000: irq_num <= 19;
                32'h00100000: irq_num <= 20;
                32'h00200000: irq_num <= 21;
                32'h00400000: irq_num <= 22;
                32'h00800000: irq_num <= 23;
                32'h01000000: irq_num <= 24;
                32'h02000000: irq_num <= 25;
                32'h04000000: irq_num <= 26;
                32'h08000000: irq_num <= 27;
                32'h10000000: irq_num <= 28;
                32'h20000000: irq_num <= 29;
                32'h40000000: irq_num <= 30;
                32'h80000000: irq_num <= 31;
                default:      irq_num <= 32;
            endcase
        end
    end

    wire [31:0] cause = (pending_exception != ~0) ? pending_exception : (`CAUSE_INTERRUPT | irq_num);
    wire [31:0] w_deleg = (r_priv_t <= `PRIV_S) ? ((cause & `CAUSE_INTERRUPT) ? (mideleg >> (cause & 32'h1f))  & 1 :
                                                                                (medeleg >> (cause & 32'h1f))) & 1 : 0;

    always @(posedge CLK) begin
        if(!RST_X || r_halt) begin pc <= `D_START_PC; end
        else if(w_pagefault != ~32'h0) begin  pending_tval <= (state==`S_IF) ? pc : (state!=`S_LD && state!=`S_SD) ? 0 : r_mem_addr; end
        else if(state==`S_FIN && !w_busy) begin
            if(pending_exception != ~0)   begin pc <= (w_deleg) ? stvec : mtvec; end
            else begin
                if(w_interrupt_mask != 0) begin pc <= (w_deleg) ? stvec : mtvec; end
                else                      begin pc <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4; end
            end
            r_ir16_v    <= !((pending_exception != ~0) || (w_interrupt_mask != 0) || (r_tkn) || (!r_cinsn));
        end
        else if(state==`S_INI) begin
            pending_tval <= 0;
        end
    end
    

    always@(posedge CLK) begin
`ifdef REAL_MTIME
        if(RST_X) mtime <= mtime + 1;
`endif
        if(state == `S_FIN && !w_busy) begin 
`ifndef REAL_MTIME
            mtime <= mtime + 1;
`endif
            if((pending_exception == ~0) ||
               (pending_exception != ~0 && (pending_exception & `CAUSE_INTERRUPT)) ||
               (pending_exception != ~0 && r_op_ECALL)) begin
                e_icount <= e_icount + 1;
            end
        end
    end


    wire [11:0] w_csr_addr = (r_funct3  != `FUNCT3_PRIV__ )  ? r_funct12 :
                             (r_funct12 == `FUNCT12_ECALL_)  ? `CSR_MTVEC:
                             (r_funct12 == `FUNCT12_URET__)  ? `CSR_UEPC :
                             (r_funct12 == `FUNCT12_SRET__)  ? `CSR_SEPC :
                             (r_funct12 == `FUNCT12_MRET__)  ? `CSR_MEPC : 0;
    
    wire [31:0] w_sstatus_t = (mstatus | 32'h6000) & 32'h000de133;
    wire [31:0] w_mstatus_t = (mstatus | 32'h6000);

    always@(*) begin
        case(w_csr_addr)
            12'h3A0         : r_rcsr_t = 0;
            12'h3B0         : r_rcsr_t = 0;
            `CSR_FFLAGS     : r_rcsr_t = 0;
            `CSR_FRM        : r_rcsr_t = 0;
            `CSR_FCSR       : r_rcsr_t = 0;
            `CSR_SIE        : r_rcsr_t = mie & mideleg;
            `CSR_STVEC      : r_rcsr_t = stvec;
            `CSR_SCOUNTEREN : r_rcsr_t = scounteren;
            `CSR_SSCRATCH   : r_rcsr_t = sscratch;
            `CSR_SEPC       : r_rcsr_t = sepc;
            `CSR_SCAUSE     : r_rcsr_t = scause;
            `CSR_STVAL      : r_rcsr_t = stval;
            `CSR_SIP        : r_rcsr_t = mip & mideleg;
            `CSR_SATP       : r_rcsr_t = satp;

            `CSR_MEDELEG    : r_rcsr_t = medeleg;
            `CSR_MIDELEG    : r_rcsr_t = mideleg;
            `CSR_MIE        : r_rcsr_t = mie;
            `CSR_MTVEC      : r_rcsr_t = mtvec;
            `CSR_MCOUNTEREN : r_rcsr_t = mcounteren;
            `CSR_MSCRATCH   : r_rcsr_t = mscratch;
            `CSR_MEPC       : r_rcsr_t = mepc;
            `CSR_MCAUSE     : r_rcsr_t = mcause;
            `CSR_MTVAL      : r_rcsr_t = mtval;
            `CSR_MIP        : r_rcsr_t = mip;
            `CSR_MISA       : r_rcsr_t = misa | 32'h40000000;

            `CSR_MCYCLE     : r_rcsr_t = mtime[31:0];
            `CSR_MINSTRET   : r_rcsr_t = mtime[31:0];
            `CSR_CYCLE      : r_rcsr_t = mtime[31:0];
            `CSR_INSTRET    : r_rcsr_t = mtime[31:0];
            `CSR_TIME       : r_rcsr_t = mtime[31:0];

            `CSR_MCYCLEH    : r_rcsr_t = mtime[63:32];
            `CSR_MINSTRETH  : r_rcsr_t = mtime[63:32];
            `CSR_CYCLEH     : r_rcsr_t = mtime[63:32];
            `CSR_INSTRETH   : r_rcsr_t = mtime[63:32];
            `CSR_TIMEH      : r_rcsr_t = mtime[63:32];

            `CSR_SSTATUS    : r_rcsr_t = (w_sstatus_t[31:13]==3 | w_sstatus_t[31:15]==3) ? (w_sstatus_t | 32'h80000000) : w_sstatus_t;
            `CSR_MSTATUS    : r_rcsr_t = (w_mstatus_t[31:13]==3 | w_mstatus_t[31:15]==3) ? (w_mstatus_t | 32'h80000000) : w_mstatus_t;
            `CSR_MHARTID    : r_rcsr_t = mhartid;
            default         : r_rcsr_t = 0;
        endcase
    end


    wire        w_csr_we    = (r_op_SYS) && (r_funct3 != `FUNCT3_PRIV__);
    wire [31:0] w_sstatus   = (mstatus & ~`SSTATUS_MASK) | (r_wb_data_csr & `SSTATUS_MASK);

    wire [31:0] w_sstatus_t1 = (w_mstatus_nxt & ~`MSTATUS_SPIE) | (((w_mstatus_nxt >> r_priv_t) & 1) << `MSTATUS_SPIE_SHIFT);
    wire [31:0] w_sstatus_t2 = (w_sstatus_t1  & ~`MSTATUS_SPP) | (r_priv_t << `MSTATUS_SPP_SHIFT);
    wire [31:0] w_sstatus_t3 = (w_sstatus_t2  & ~`MSTATUS_SIE);
    wire [31:0] w_mstatus_t1 = (w_mstatus_nxt & ~`MSTATUS_MPIE) | (((w_mstatus_nxt >> r_priv_t) & 1) << `MSTATUS_MPIE_SHIFT);
    wire [31:0] w_mstatus_t2 = (w_mstatus_t1  & ~`MSTATUS_MPP) | (r_priv_t << `MSTATUS_MPP_SHIFT);
    wire [31:0] w_mstatus_t3 = (w_mstatus_t2  & ~`MSTATUS_MIE);

    always@(posedge CLK) begin
        if(state == `S_IF) begin
            if(mtime > `ENABLE_TIMER) begin
                if(w_plic_we) begin
                    mip <= w_wmip;
                end
                else if(mtimecmp < mtime) begin
                    mip <= mip | `MIP_MTIP;
                end
            end
        end

        if(state == `S_EX2 || state == `S_WB) begin
            if(w_plic_we) begin
                mip <= w_wmip;
            end
        end
        if(state == `S_SD && !w_busy) begin
            if(w_clint_we) begin
                mtimecmp    <= w_wmtimecmp;
                mip         <= mip & ~`MIP_MTIP;
            end
        end

        if(state == `S_FIN && !w_busy) begin
            if(pending_exception != ~0) begin
                if(w_deleg) begin
                    scause  <= cause;
                    sepc    <= pc;
                    stval   <= pending_tval;
                    mstatus <= w_sstatus_t3;
                    priv    <= `PRIV_S;
                end else begin
                    mcause  <= cause;
                    mepc    <= pc;
                    mtval   <= pending_tval;
                    mstatus <= w_mstatus_t3;
                    priv    <= `PRIV_M;
                end
            end
            else if(w_interrupt_mask != 0) begin
                if(w_deleg) begin
                    scause  <= cause;
                    sepc    <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4;
                    stval   <= pending_tval;
                    mstatus <= w_sstatus_t3;
                    priv    <= `PRIV_S;
                end else begin
                    mcause  <= cause;
                    mepc    <= (r_tkn) ? r_jmp_pc : (r_cinsn) ? pc + 2 : pc + 4;
                    mtval   <= pending_tval;
                    mstatus <= w_mstatus_t3;
                    priv    <= `PRIV_M;
                end
            end
        end

        else if(state == `S_COM && !w_busy) begin
            if(r_opcode == `OPCODE_SYSTEM__ && r_funct3 == `FUNCT3_PRIV__) begin
                case (r_funct12)
                    `FUNCT12_URET__ : begin
                    end
                    `FUNCT12_SRET__ : begin
                        mstatus <= (((mstatus & ~(1<<mstatus[8])) | (mstatus[5] << mstatus[8])) | 32'h20) & ~32'h100;
                        priv    <= mstatus[8];
                    end
                    `FUNCT12_MRET__ : begin
                        mstatus <= (((mstatus & ~(1 << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT]))
                                     | (mstatus[`MSTATUS_MPIE_SHIFT] << mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT])) 
                                    | `MSTATUS_MPIE) & ~`MSTATUS_MPP;
                        priv    <= mstatus[`MSTATUS_MPP_SHIFT+1:`MSTATUS_MPP_SHIFT];
                    end
                endcase
            end
            else if(w_csr_we) begin
                case(r_funct12)
                    `CSR_STVEC      : stvec      <= r_wb_data_csr & ~3;
                    `CSR_SCOUNTEREN : scounteren <= r_wb_data_csr & 5;
                    `CSR_SSCRATCH   : sscratch   <= r_wb_data_csr;
                    `CSR_SEPC       : sepc       <= r_wb_data_csr & ~1;
                    `CSR_SCAUSE     : scause     <= r_wb_data_csr;
                    `CSR_STVAL      : stval      <= r_wb_data_csr;

                    `CSR_MTVEC      : mtvec      <= r_wb_data_csr & ~3;
                    `CSR_MCOUNTEREN : mcounteren <= r_wb_data_csr & 5;
                    `CSR_MSCRATCH   : mscratch   <= r_wb_data_csr;
                    `CSR_MEPC       : mepc       <= r_wb_data_csr & ~1;
                    `CSR_MCAUSE     : mcause     <= r_wb_data_csr;
                    `CSR_MTVAL      : mtval      <= r_wb_data_csr;

                    `CSR_SIE        : mie        <= (mie & ~mideleg) | (r_wb_data_csr & mideleg);
                    `CSR_SIP        : mip        <= (mip & ~mideleg) | (r_wb_data_csr & mideleg);

                    `CSR_MEDELEG    : medeleg    <= (medeleg & ~`WCSR_MASK1) | (r_wb_data_csr & `WCSR_MASK1);
                    `CSR_MIDELEG    : mideleg    <= (mideleg & ~`WCSR_MASK2) | (r_wb_data_csr & `WCSR_MASK2);
                    `CSR_MIE        : mie        <= (mie & ~`WCSR_MASK3) | (r_wb_data_csr & `WCSR_MASK3);
                    `CSR_MIP        : mip        <= (mip & ~`WCSR_MASK4) | (r_wb_data_csr & `WCSR_MASK4);

                    `CSR_SATP       : satp       <= r_wb_data_csr;

                    `CSR_MSTATUS    : mstatus    <= (mstatus & ~`MASK_STATUS) | (r_wb_data_csr & `MASK_STATUS);
                    `CSR_SSTATUS    : mstatus    <= (mstatus & ~`MASK_STATUS) | (w_sstatus & `MASK_STATUS);
                endcase
            end
        end
    end

    assign w_mstatus_nxt =  (pending_exception != ~0)             ? r_mstatus_t :
                        (w_csr_we && r_funct12 == `CSR_MSTATUS) ? (mstatus & ~`MASK_STATUS) | (r_wb_data_csr & `MASK_STATUS) :
                        (w_csr_we && r_funct12 == `CSR_SSTATUS) ? (mstatus & ~`MASK_STATUS) | (w_sstatus & `MASK_STATUS) : r_mstatus_t;


    reg  r_tlb_flush;
    wire [31:0] w_data_t = (r_funct12==`CSR_MSTATUS) ? r_wb_data_csr : w_sstatus;
    wire [31:0] w_mod    = w_data_t ^ mstatus;
    
    assign w_tlb_flush   = r_tlb_flush;


    always@(*) begin


        if(state==`S_COM && !w_busy) begin
            if(pending_exception != ~0 || w_interrupt_mask != 0) r_tlb_flush <= 1;
            else if(r_op_SRET || r_op_MRET) r_tlb_flush <= 1;
            else if(r_op_CSR_MSTA) begin
                if((w_mod & (`MSTATUS_MPRV | `MSTATUS_SUM | `MSTATUS_MXR)) != 0 ||
                   ((mstatus & `MSTATUS_MPRV) && (w_mod & `MSTATUS_MPP) != 0)) begin
                    r_tlb_flush <= 1;
                end
            end
            else if(r_op_CSR_SSTA) begin
                if((w_mod & (`MSTATUS_MPRV | `MSTATUS_SUM | `MSTATUS_MXR)) != 0 ||
                   ((mstatus & `MSTATUS_MPRV) && (w_mod & `MSTATUS_MPP) != 0)) begin
                    r_tlb_flush <= 1;
                end
            end
            else r_tlb_flush <= 0;
        end
        else r_tlb_flush <= 0;
    end


    wire w_com = ((pending_exception!=~0 || w_pagefault!=~0 || (state==`S_EX1 && r_op_ECALL)) 
                  && state!=`S_COM && state!=`S_FIN && state!=`S_INI);

    assign w_state = (!RST_X | r_halt)                                         ? 0      :
                     (w_com)                                                   ? `S_COM :
                     (w_busy || w_ex1_busy)                                    ? state  :
                     (state==`S_FIN)                                           ? `S_INI :
                     (state==`S_IF  && w_nalign4 && r_if_state!=3)             ? `S_IF  :
                     (state==`S_EX1 && !r_op_AMO && !r_op_LOAD && !r_op_STORE) ? `S_WB  :
                     (state==`S_LD  && r_op_STORE)                             ? `S_SD  :
                     (state==`S_LD  && r_op_LOAD)                              ? `S_WB  : state+1;
         
    always @(posedge CLK) state <= w_state;

    reg [2:0] r_com;
    always @(posedge CLK) r_com <= (state!=`S_COM && state!=`S_FIN && state!=`S_INI) ? {pending_exception!=~0, w_pagefault!=~0, (state==`S_EX1 && r_op_ECALL)} : 0;


    wire w_d_we_t = (w_state==`S_SD && (r_op_STORE || 
                                        (r_op_AMO &&  r_op_AMO_SC && !r_wb_data[0]) || 
                                        (r_op_AMO && !r_op_AMO_LR && !r_op_AMO_SC)));
    wire w_d_en_t = (w_state==`S_LD && (r_op_LOAD || (r_op_AMO && (!r_op_AMO_SC))));

         
    reg       r_data_we=0;
    reg       r_data_en=0;
    reg [2:0] r_tlb_req=0;
    always @(posedge CLK) begin
        r_data_we <= w_d_we_t;
        r_data_en <= w_d_en_t;
        r_tlb_req <= (w_state==`S_IF && w_if_state!=1) ? `ACCESS_CODE  :
                     (w_d_en_t)                        ? `ACCESS_READ  :
                     (w_d_we_t)                        ? `ACCESS_WRITE : 2'h3;
    end

    assign w_tlb_req  = r_tlb_req;
    assign w_data_we  = r_data_we;
    assign w_priv     = priv;
    assign w_satp     = satp;
    assign w_mstatus  = mstatus;
    assign w_mtime    = mtime;
    assign w_mtimecmp = mtimecmp;
    assign w_mip      = mip;


    initial r_halt = 0;
    always @(posedge CLK) if(r_opcode==`OPCODE_HALT____) r_halt <= 1;

    assign w_core_pc = pc;
    assign w_core_ir = r_ir;
    assign w_core_odata = 0;
endmodule