data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v
1: b'%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:11: Cannot find include file: sm_cpu.vh\n`include "sm_cpu.vh" \n         ^~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb,data/full_repos/permissive/102870077/sm_cpu.vh\n             data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb,data/full_repos/permissive/102870077/sm_cpu.vh.v\n             data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb,data/full_repos/permissive/102870077/sm_cpu.vh.sv\n             sm_cpu.vh\n             sm_cpu.vh.v\n             sm_cpu.vh.sv\n             obj_dir/sm_cpu.vh\n             obj_dir/sm_cpu.vh.v\n             obj_dir/sm_cpu.vh.sv\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:12: Cannot find include file: sm_settings.vh\n`include "sm_settings.vh" \n         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:178: Define or directive not defined: \'`PC_EXC\'\n    assign pc_new = pcExc == `PC_EXC  ?  cp0_ExcHandler :\n                             ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:178: syntax error, unexpected \'?\', expecting TYPE-IDENTIFIER\n    assign pc_new = pcExc == `PC_EXC  ?  cp0_ExcHandler :\n                                      ^\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:179: Define or directive not defined: \'`PC_ERET\'\n                    pcExc == `PC_ERET ?  cp0_EPC        :\n                             ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:235: Define or directive not defined: \'`PC_EXC\'\n    assign pcExc = exception      ? `PC_EXC  :\n                                    ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:235: syntax error, unexpected \':\', expecting TYPE-IDENTIFIER\n    assign pcExc = exception      ? `PC_EXC  :\n                                             ^\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:236: Define or directive not defined: \'`PC_ERET\'\n                   cw_cpzExcEret  ? `PC_ERET : `PC_FLOW;\n                                    ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:236: Define or directive not defined: \'`PC_FLOW\'\n                   cw_cpzExcEret  ? `PC_ERET : `PC_FLOW;\n                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:244: Define or directive not defined: \'`ALU_ADD\'\n        aluControl  = `ALU_ADD;\n                      ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:244: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n        aluControl  = `ALU_ADD;\n                              ^\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n                     ^\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: Define or directive not defined: \'`F_ADDU\'\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n                        ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: Define or directive not defined: \'`ALU_ADD\'\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:256: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n            { `C_SPEC,  `F_ADDU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_ADD;  end\n                                                                                                       ^\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:257: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_OR,   `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_OR;   end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:257: Define or directive not defined: \'`F_OR\'\n            { `C_SPEC,  `F_OR,   `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_OR;   end\n                        ^~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:257: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_OR,   `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_OR;   end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:257: Define or directive not defined: \'`ALU_OR\'\n            { `C_SPEC,  `F_OR,   `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_OR;   end\n                                                                                               ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:258: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_SRL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SRL;  end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:258: Define or directive not defined: \'`F_SRL\'\n            { `C_SPEC,  `F_SRL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SRL;  end\n                        ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:258: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_SRL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SRL;  end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:258: Define or directive not defined: \'`ALU_SRL\'\n            { `C_SPEC,  `F_SRL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SRL;  end\n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:259: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_SLL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLL;  end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:259: Define or directive not defined: \'`F_SLL\'\n            { `C_SPEC,  `F_SLL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLL;  end\n                        ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:259: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_SLL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLL;  end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:259: Define or directive not defined: \'`ALU_SLL\'\n            { `C_SPEC,  `F_SLL,  `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLL;  end\n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:260: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_SLTU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLTU; end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:260: Define or directive not defined: \'`F_SLTU\'\n            { `C_SPEC,  `F_SLTU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLTU; end\n                        ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:260: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_SLTU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLTU; end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:260: Define or directive not defined: \'`ALU_SLTU\'\n            { `C_SPEC,  `F_SLTU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SLTU; end\n                                                                                               ^~~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:261: Define or directive not defined: \'`C_SPEC\'\n            { `C_SPEC,  `F_SUBU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SUBU; end\n              ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:261: Define or directive not defined: \'`F_SUBU\'\n            { `C_SPEC,  `F_SUBU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SUBU; end\n                        ^~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:261: Define or directive not defined: \'`S_ANY\'\n            { `C_SPEC,  `F_SUBU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SUBU; end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:261: Define or directive not defined: \'`ALU_SUBU\'\n            { `C_SPEC,  `F_SUBU, `S_ANY } : begin regDst = 1\'b1; regWrite = 1\'b1; aluControl = `ALU_SUBU; end\n                                                                                               ^~~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:263: Define or directive not defined: \'`C_ADDIU\'\n            { `C_ADDIU, `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD;  end\n              ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:263: Define or directive not defined: \'`F_ANY\'\n            { `C_ADDIU, `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD;  end\n                        ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:263: Define or directive not defined: \'`S_ANY\'\n            { `C_ADDIU, `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD;  end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:263: Define or directive not defined: \'`ALU_ADD\'\n            { `C_ADDIU, `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD;  end\n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:264: Define or directive not defined: \'`C_LUI\'\n            { `C_LUI,   `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_LUI;  end\n              ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:264: Define or directive not defined: \'`F_ANY\'\n            { `C_LUI,   `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_LUI;  end\n                        ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:264: Define or directive not defined: \'`S_ANY\'\n            { `C_LUI,   `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_LUI;  end\n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:264: Define or directive not defined: \'`ALU_LUI\'\n            { `C_LUI,   `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_LUI;  end\n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:265: Define or directive not defined: \'`C_LW\'\n            { `C_LW,    `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD; \n              ^~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:265: Define or directive not defined: \'`F_ANY\'\n            { `C_LW,    `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD; \n                        ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:265: Define or directive not defined: \'`S_ANY\'\n            { `C_LW,    `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD; \n                                 ^~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:265: Define or directive not defined: \'`ALU_ADD\'\n            { `C_LW,    `F_ANY,  `S_ANY } : begin regWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD; \n                                                                                               ^~~~~~~~\n%Error: data/full_repos/permissive/102870077/engine/static/school_mips/pipeline_ahb/sm_cpu.v:267: Define or directive not defined: \'`C_SW\'\n            { `C_SW,    `F_ANY,  `S_ANY } : begin memWrite = 1\'b1; aluSrc = 1\'b1; aluControl = `ALU_ADD; \n              ^~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module sm_cpu
(
    input           clk,
    input           rst_n,
    input   [ 4:0]  regAddr,
    output  [31:0]  regData,
    output  [31:0]  imAddr,
    input   [31:0]  imData,
    output  [31:0]  dmAddr,
    output          dmWe,
    output  [31:0]  dmWData,
    output          dmValid,
    input           dmReady,
    input   [31:0]  dmRData
);

    wire        pcSrc;
    wire [ 1:0] pcExc;
    wire        regDst;
    wire        regWrite;
    wire        aluSrc;
    wire        aluZero;
    wire [ 2:0] aluControl;
    wire        memToReg;
    wire        memWrite;
    wire        memAccess;
    wire        hz_stall;
    wire        hz_mem_en;


    wire [31:0] pc;
    wire [31:0] pcBranch;
    wire [31:0] pcNext  = pc + 4;
    wire [31:0] pc_new;
    wire [31:0] pc_flow = ~pcSrc ? pcNext : pcBranch;
    sm_register_we #(32) r_pc(clk ,rst_n, ~hz_stall, pc_new, pc);


    assign imAddr = pc >> 2;
    wire [31:0] instr = imData;


    wire [31:0] rd0;
    assign regData = (regAddr != 0) ? rd0 : pc;


    wire [ 4:0] a3  = regDst ? instr[15:11] : instr[20:16];
    wire [31:0] rd1;
    wire [31:0] rd2;
    wire [31:0] wd3;

    sm_register_file rf
    (
        .clk        ( clk          ),
        .a0         ( regAddr      ),
        .a1         ( instr[25:21] ),
        .a2         ( instr[20:16] ),
        .a3         ( a3           ),
        .rd0        ( rd0          ),
        .rd1        ( rd1          ),
        .rd2        ( rd2          ),
        .wd3        ( wd3          ),
        .we3        ( regWrite     )
    );


    wire [31:0] signImm = { {16 { instr[15] }}, instr[15:0] };
    assign pcBranch = pcNext + (signImm << 2);


    wire [31:0] aluResult;
    wire [31:0] srcB = aluSrc ? signImm : rd2;

    sm_alu alu
    (
        .srcA       ( rd1          ),
        .srcB       ( srcB         ),
        .oper       ( aluControl   ),
        .shift      ( instr[10:6 ] ),
        .zero       ( aluZero      ),
        .result     ( aluResult    )
    );


    assign dmWe = memWrite;
    assign dmAddr = aluResult;
    assign dmWData = rd2;
    assign dmValid = hz_mem_en;


    wire        cw_cpzToReg;
    wire        cw_cpzRegWrite;
    wire        cp0_ExcAsync;
    wire        cp0_ExcSync;
    wire        cw_cpzExcEret;
    wire        excRiFound;
    wire        cw_epcSrc;
    wire        cw_branch;

    sm_control sm_control
    (
        .cmdOper    ( instr[31:26] ),
        .cmdRegS    ( instr[25:21] ),
        .cmdFunk    ( instr[ 5:0 ] ),
        .aluZero    ( aluZero      ),
        .pcSrc      ( pcSrc        ),
        .pcExc      ( pcExc        ),
        .regDst     ( regDst       ),
        .regWrite   ( regWrite     ),
        .aluSrc     ( aluSrc       ),
        .aluControl ( aluControl   ),
        .memWrite   ( memWrite     ),
        .memToReg   ( memToReg     ),
        .memAccess  ( memAccess    ),
        .branch     ( cw_branch    ),
        .cw_cpzToReg    ( cw_cpzToReg    ),
        .cw_cpzRegWrite ( cw_cpzRegWrite ),
        .cw_cpzExcEret  ( cw_cpzExcEret  ),
        .excAsync       ( cp0_ExcAsync   ),
        .excSync        ( cp0_ExcSync    ),
        .cw_epcSrc      ( cw_epcSrc      ),
        .excRiFound     ( excRiFound     )
    );

    wire [31:0] cp0_EPC;
    wire [31:0] cp0_ExcHandler;
    wire [ 4:0] cp0_regNum = instr[15:11];
    wire [ 2:0] cp0_regSel = instr[ 2:0 ];
    wire [31:0] cp0_regRD;
    wire [31:0] cp0_regWD   = rd2;
    wire        cp0_TI;
    wire [ 5:0] cp0_ExcIP = { cp0_TI, 5'b0 };
    wire        cp0_ExcRI   = excRiFound;
    wire        cp0_ExcOv   = 1'b0;
    wire        cp0_ExcAsyncRq;
    
    wire [31:0] cp0_PC = cw_epcSrc ? pc : pc_flow;

    sm_cpz sm_cpz
    (
        .clk            ( clk            ),
        .rst_n          ( rst_n          ),
        .cp0_PC         ( cp0_PC         ),
        .cp0_EPC        ( cp0_EPC        ),
        .cp0_ExcHandler ( cp0_ExcHandler ),
        .cp0_ExcAsyncReq( cp0_ExcAsyncRq ),
        .cp0_ExcAsyncAck( cp0_ExcAsyncRq ),
        .cp0_ExcAsync   ( cp0_ExcAsync   ),
        .cp0_ExcSync    ( cp0_ExcSync    ),
        .cp0_ExcEret    ( cw_cpzExcEret  ),
        .cp0_regNum     ( cp0_regNum     ),
        .cp0_regSel     ( cp0_regSel     ),
        .cp0_regRD      ( cp0_regRD      ),
        .cp0_regWD      ( cp0_regWD      ),
        .cp0_regWE      ( cw_cpzRegWrite ),
        .cp0_ExcIP      ( cp0_ExcIP      ),
        .cp0_ExcRI      ( cp0_ExcRI      ),
        .cp0_ExcOv      ( cp0_ExcOv      ),
        .cp0_TI         ( cp0_TI         )
    );

    assign wd3 = memToReg    ? dmRData   :
                ( cw_cpzToReg ? cp0_regRD : aluResult );

    assign pc_new = pcExc == `PC_EXC  ?  cp0_ExcHandler :
                    pcExc == `PC_ERET ?  cp0_EPC        :
pc_flow;


    wire memWait;
    wire memAccessStart    = ~memWait &  memAccess;
    wire memAccessDone     =  memWait &  dmReady;
    wire memAccessProgress =  memWait & ~dmReady;

    wire memWait_new = memAccessStart ? 1 :
                       memAccessDone  ? 0 :
                       memWait;
    sm_register_c r_memWait(clk ,rst_n, memWait_new, memWait);




    assign hz_stall  = memAccessStart | memAccessProgress;



    assign hz_mem_en = memAccessStart;

endmodule
module sm_cpu
(
    input           clk,
    input           rst_n,
    input   [ 4:0]  regAddr,
    output  [31:0]  regData,
    output  [31:0]  imAddr,
    input   [31:0]  imData,
    output  [31:0]  dmAddr,
    output          dmWe,
    output  [31:0]  dmWData,
    output          dmValid,
    input           dmReady,
    input   [31:0]  dmRData
);


    wire        pcSrc;
    wire [ 1:0] pcExc;
    wire        regDst;
    wire        regWrite;
    wire        aluSrc;
    wire        aluZero;
    wire [ 2:0] aluControl;
    wire        memToReg;
    wire        memWrite;
    wire        memAccess;
    wire        hz_stall;
    wire        hz_mem_en;


    wire [31:0] pc;
    wire [31:0] pcBranch;
    wire [31:0] pcNext  = pc + 4;
    wire [31:0] pc_new;
    wire [31:0] pc_flow = ~pcSrc ? pcNext : pcBranch;
    sm_register_we #(32) r_pc(clk ,rst_n, ~hz_stall, pc_new, pc);


    assign imAddr = pc >> 2;
    wire [31:0] instr = imData;


    wire [31:0] rd0;
    assign regData = (regAddr != 0) ? rd0 : pc;


    wire [ 4:0] a3  = regDst ? instr[15:11] : instr[20:16];
    wire [31:0] rd1;
    wire [31:0] rd2;
    wire [31:0] wd3;

    sm_register_file rf
    (
        .clk        ( clk          ),
        .a0         ( regAddr      ),
        .a1         ( instr[25:21] ),
        .a2         ( instr[20:16] ),
        .a3         ( a3           ),
        .rd0        ( rd0          ),
        .rd1        ( rd1          ),
        .rd2        ( rd2          ),
        .wd3        ( wd3          ),
        .we3        ( regWrite     )
    );


    wire [31:0] signImm = { {16 { instr[15] }}, instr[15:0] };
    assign pcBranch = pcNext + (signImm << 2);


    wire [31:0] aluResult;
    wire [31:0] srcB = aluSrc ? signImm : rd2;

    sm_alu alu
    (
        .srcA       ( rd1          ),
        .srcB       ( srcB         ),
        .oper       ( aluControl   ),
        .shift      ( instr[10:6 ] ),
        .zero       ( aluZero      ),
        .result     ( aluResult    )
    );


    assign dmWe = memWrite;
    assign dmAddr = aluResult;
    assign dmWData = rd2;
    assign dmValid = hz_mem_en;


    wire        cw_cpzToReg;
    wire        cw_cpzRegWrite;
    wire        cp0_ExcAsync;
    wire        cp0_ExcSync;
    wire        cw_cpzExcEret;
    wire        excRiFound;
    wire        cw_epcSrc;
    wire        cw_branch;

    sm_control sm_control
    (
        .cmdOper    ( instr[31:26] ),
        .cmdRegS    ( instr[25:21] ),
        .cmdFunk    ( instr[ 5:0 ] ),
        .aluZero    ( aluZero      ),
        .pcSrc      ( pcSrc        ),
        .pcExc      ( pcExc        ),
        .regDst     ( regDst       ),
        .regWrite   ( regWrite     ),
        .aluSrc     ( aluSrc       ),
        .aluControl ( aluControl   ),
        .memWrite   ( memWrite     ),
        .memToReg   ( memToReg     ),
        .memAccess  ( memAccess    ),
        .branch     ( cw_branch    ),
        .cw_cpzToReg    ( cw_cpzToReg    ),
        .cw_cpzRegWrite ( cw_cpzRegWrite ),
        .cw_cpzExcEret  ( cw_cpzExcEret  ),
        .excAsync       ( cp0_ExcAsync   ),
        .excSync        ( cp0_ExcSync    ),
        .cw_epcSrc      ( cw_epcSrc      ),
        .excRiFound     ( excRiFound     )
    );

    wire [31:0] cp0_EPC;
    wire [31:0] cp0_ExcHandler;
    wire [ 4:0] cp0_regNum = instr[15:11];
    wire [ 2:0] cp0_regSel = instr[ 2:0 ];
    wire [31:0] cp0_regRD;
    wire [31:0] cp0_regWD   = rd2;
    wire        cp0_TI;
    wire [ 5:0] cp0_ExcIP = { cp0_TI, 5'b0 };
    wire        cp0_ExcRI   = excRiFound;
    wire        cp0_ExcOv   = 1'b0;
    wire        cp0_ExcAsyncRq;
    
    wire [31:0] cp0_PC = cw_epcSrc ? pc : pc_flow;

    sm_cpz sm_cpz
    (
        .clk            ( clk            ),
        .rst_n          ( rst_n          ),
        .cp0_PC         ( cp0_PC         ),
        .cp0_EPC        ( cp0_EPC        ),
        .cp0_ExcHandler ( cp0_ExcHandler ),
        .cp0_ExcAsyncReq( cp0_ExcAsyncRq ),
        .cp0_ExcAsyncAck( cp0_ExcAsyncRq ),
        .cp0_ExcAsync   ( cp0_ExcAsync   ),
        .cp0_ExcSync    ( cp0_ExcSync    ),
        .cp0_ExcEret    ( cw_cpzExcEret  ),
        .cp0_regNum     ( cp0_regNum     ),
        .cp0_regSel     ( cp0_regSel     ),
        .cp0_regRD      ( cp0_regRD      ),
        .cp0_regWD      ( cp0_regWD      ),
        .cp0_regWE      ( cw_cpzRegWrite ),
        .cp0_ExcIP      ( cp0_ExcIP      ),
        .cp0_ExcRI      ( cp0_ExcRI      ),
        .cp0_ExcOv      ( cp0_ExcOv      ),
        .cp0_TI         ( cp0_TI         )
    );

    assign wd3 = memToReg    ? dmRData   :
                ( cw_cpzToReg ? cp0_regRD : aluResult );

    assign pc_new = pcExc == `PC_EXC  ?  cp0_ExcHandler :
                    pcExc == `PC_ERET ?  cp0_EPC        :
pc_flow;


    wire memWait;
    wire memAccessStart    = ~memWait &  memAccess;
    wire memAccessDone     =  memWait &  dmReady;
    wire memAccessProgress =  memWait & ~dmReady;

    wire memWait_new = memAccessStart ? 1 :
                       memAccessDone  ? 0 :
                       memWait;
    sm_register_c r_memWait(clk ,rst_n, memWait_new, memWait);




    assign hz_stall  = memAccessStart | memAccessProgress;



    assign hz_mem_en = memAccessStart;

endmodule