/* -----------------------------------------------------------------------------
* Project Name   : Architectures of Processor Systems (APS) lab work
* Organization   : National Research University of Electronic Technology (MIET)
* Department     : Institute of Microdevices and Control Systems
* Author(s)      : Alexey Kozin
* Email(s)       : akozin@edu.miet.ru

See https://github.com/MPSU/APS/blob/master/LICENSE file for licensing details.
* ------------------------------------------------------------------------------
*/
function logic ldF0poVEX4 (input logic F8w8Agr, SQ5L2T, Hfvec, weM, ziZG3f3w85eBr);
    case ({F8w8Agr, SQ5L2T, Hfvec, weM, ziZG3f3w85eBr})
        'b00000: ldF0poVEX4 = 'b0;
        'b00001: ldF0poVEX4 = 'b1;
        'b00010: ldF0poVEX4 = 'b1;
        'b00011: ldF0poVEX4 = 'b1;
        'b00100: ldF0poVEX4 = 'b0;
        'b00101: ldF0poVEX4 = 'b1;
        'b00110: ldF0poVEX4 = 'b1;
        'b00111: ldF0poVEX4 = 'b1;
        'b01000: ldF0poVEX4 = 'b0;
        'b01001: ldF0poVEX4 = 'b1;
        'b01010: ldF0poVEX4 = 'b1;
        'b01011: ldF0poVEX4 = 'b1;
        'b01100: ldF0poVEX4 = 'b0;
        'b01101: ldF0poVEX4 = 'b1;
        'b01110: ldF0poVEX4 = 'b1;
        'b01111: ldF0poVEX4 = 'b1;
        'b10000: ldF0poVEX4 = 'b0;
        'b10001: ldF0poVEX4 = 'b1;
        'b10010: ldF0poVEX4 = 'b1;
        'b10011: ldF0poVEX4 = 'b1;
        'b10100: ldF0poVEX4 = 'b0;
        'b10101: ldF0poVEX4 = 'b1;
        'b10110: ldF0poVEX4 = 'b1;
        'b10111: ldF0poVEX4 = 'b1;
        'b11000: ldF0poVEX4 = 'b0;
        'b11001: ldF0poVEX4 = 'b1;
        'b11010: ldF0poVEX4 = 'b1;
        'b11011: ldF0poVEX4 = 'b1;
        'b11100: ldF0poVEX4 = 'b0;
        'b11101: ldF0poVEX4 = 'b1;
        'b11110: ldF0poVEX4 = 'b1;
        'b11111: ldF0poVEX4 = 'b1;
    endcase
endfunction

function logic VL5PghYXdkG6kEn (input logic F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr);
    case ({F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr})
        'b00000: VL5PghYXdkG6kEn = 'b0;
        'b00001: VL5PghYXdkG6kEn = 'b0;
        'b00010: VL5PghYXdkG6kEn = 'b0;
        'b00011: VL5PghYXdkG6kEn = 'b0;
        'b00100: VL5PghYXdkG6kEn = 'b0;
        'b00101: VL5PghYXdkG6kEn = 'b0;
        'b00110: VL5PghYXdkG6kEn = 'b0;
        'b00111: VL5PghYXdkG6kEn = 'b0;
        'b01000: VL5PghYXdkG6kEn = 'b0;
        'b01001: VL5PghYXdkG6kEn = 'b0;
        'b01010: VL5PghYXdkG6kEn = 'b0;
        'b01011: VL5PghYXdkG6kEn = 'b0;
        'b01100: VL5PghYXdkG6kEn = 'b0;
        'b01101: VL5PghYXdkG6kEn = 'b0;
        'b01110: VL5PghYXdkG6kEn = 'b0;
        'b01111: VL5PghYXdkG6kEn = 'b0;
        'b10000: VL5PghYXdkG6kEn = 'b1;
        'b10001: VL5PghYXdkG6kEn = 'b1;
        'b10010: VL5PghYXdkG6kEn = 'b1;
        'b10011: VL5PghYXdkG6kEn = 'b1;
        'b10100: VL5PghYXdkG6kEn = 'b0;
        'b10101: VL5PghYXdkG6kEn = 'b0;
        'b10110: VL5PghYXdkG6kEn = 'b0;
        'b10111: VL5PghYXdkG6kEn = 'b0;
        'b11000: VL5PghYXdkG6kEn = 'b1;
        'b11001: VL5PghYXdkG6kEn = 'b1;
        'b11010: VL5PghYXdkG6kEn = 'b1;
        'b11011: VL5PghYXdkG6kEn = 'b1;
        'b11100: VL5PghYXdkG6kEn = 'b0;
        'b11101: VL5PghYXdkG6kEn = 'b0;
        'b11110: VL5PghYXdkG6kEn = 'b0;
        'b11111: VL5PghYXdkG6kEn = 'b0;
    endcase
endfunction

function logic Kgs4sx4nQ5ZCQK (input logic F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr);
    case ({F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr})
        'b00000: Kgs4sx4nQ5ZCQK = 'b0;
        'b00001: Kgs4sx4nQ5ZCQK = 'b0;
        'b00010: Kgs4sx4nQ5ZCQK = 'b0;
        'b00011: Kgs4sx4nQ5ZCQK = 'b0;
        'b00100: Kgs4sx4nQ5ZCQK = 'b0;
        'b00101: Kgs4sx4nQ5ZCQK = 'b0;
        'b00110: Kgs4sx4nQ5ZCQK = 'b0;
        'b00111: Kgs4sx4nQ5ZCQK = 'b0;
        'b01000: Kgs4sx4nQ5ZCQK = 'b1;
        'b01001: Kgs4sx4nQ5ZCQK = 'b1;
        'b01010: Kgs4sx4nQ5ZCQK = 'b1;
        'b01011: Kgs4sx4nQ5ZCQK = 'b1;
        'b01100: Kgs4sx4nQ5ZCQK = 'b0;
        'b01101: Kgs4sx4nQ5ZCQK = 'b0;
        'b01110: Kgs4sx4nQ5ZCQK = 'b0;
        'b01111: Kgs4sx4nQ5ZCQK = 'b0;
        'b10000: Kgs4sx4nQ5ZCQK = 'b0;
        'b10001: Kgs4sx4nQ5ZCQK = 'b0;
        'b10010: Kgs4sx4nQ5ZCQK = 'b0;
        'b10011: Kgs4sx4nQ5ZCQK = 'b0;
        'b10100: Kgs4sx4nQ5ZCQK = 'b0;
        'b10101: Kgs4sx4nQ5ZCQK = 'b0;
        'b10110: Kgs4sx4nQ5ZCQK = 'b0;
        'b10111: Kgs4sx4nQ5ZCQK = 'b0;
        'b11000: Kgs4sx4nQ5ZCQK = 'b1;
        'b11001: Kgs4sx4nQ5ZCQK = 'b1;
        'b11010: Kgs4sx4nQ5ZCQK = 'b1;
        'b11011: Kgs4sx4nQ5ZCQK = 'b1;
        'b11100: Kgs4sx4nQ5ZCQK = 'b0;
        'b11101: Kgs4sx4nQ5ZCQK = 'b0;
        'b11110: Kgs4sx4nQ5ZCQK = 'b0;
        'b11111: Kgs4sx4nQ5ZCQK = 'b0;
    endcase
endfunction

function logic WmQYuPf7wm0 (input logic F8w8Agr, SQ5L2T, Tc1U, Hfvec, ziZG3f3w85eBr);
    case ({F8w8Agr, SQ5L2T, Tc1U, Hfvec, ziZG3f3w85eBr})
        'b00000: WmQYuPf7wm0 = 'b1;
        'b00001: WmQYuPf7wm0 = 'b1;
        'b00010: WmQYuPf7wm0 = 'b0;
        'b00011: WmQYuPf7wm0 = 'b0;
        'b00100: WmQYuPf7wm0 = 'b1;
        'b00101: WmQYuPf7wm0 = 'b1;
        'b00110: WmQYuPf7wm0 = 'b1;
        'b00111: WmQYuPf7wm0 = 'b1;
        'b01000: WmQYuPf7wm0 = 'b1;
        'b01001: WmQYuPf7wm0 = 'b1;
        'b01010: WmQYuPf7wm0 = 'b0;
        'b01011: WmQYuPf7wm0 = 'b0;
        'b01100: WmQYuPf7wm0 = 'b1;
        'b01101: WmQYuPf7wm0 = 'b1;
        'b01110: WmQYuPf7wm0 = 'b1;
        'b01111: WmQYuPf7wm0 = 'b1;
        'b10000: WmQYuPf7wm0 = 'b1;
        'b10001: WmQYuPf7wm0 = 'b1;
        'b10010: WmQYuPf7wm0 = 'b0;
        'b10011: WmQYuPf7wm0 = 'b0;
        'b10100: WmQYuPf7wm0 = 'b1;
        'b10101: WmQYuPf7wm0 = 'b1;
        'b10110: WmQYuPf7wm0 = 'b1;
        'b10111: WmQYuPf7wm0 = 'b1;
        'b11000: WmQYuPf7wm0 = 'b1;
        'b11001: WmQYuPf7wm0 = 'b1;
        'b11010: WmQYuPf7wm0 = 'b0;
        'b11011: WmQYuPf7wm0 = 'b0;
        'b11100: WmQYuPf7wm0 = 'b1;
        'b11101: WmQYuPf7wm0 = 'b1;
        'b11110: WmQYuPf7wm0 = 'b1;
        'b11111: WmQYuPf7wm0 = 'b1;
    endcase
endfunction

module processor_core (
  input  logic        clk_i,
  input  logic        rst_i,

  input  logic        stall_i,
  input  logic [31:0] instr_i,
  input  logic [31:0] mem_rd_i,

  output logic [31:0] instr_addr_o,
  output logic [31:0] mem_addr_o,
  output logic [ 2:0] mem_size_o,
  output logic        mem_req_o,
  output logic        mem_we_o,
  output logic [31:0] mem_wd_o,

  input  logic        irq_req_i,
  output logic        irq_ret_o
);

    logic [31:0] KD;
    logic [31:0] RPgcnv34Ab8;
    logic [1:0]  C56l2;
    logic [2:0]  i2H9F;
    logic [4:0]  eliEEt;
    logic [2:0]  O1caGF;
    logic        yTOhJF;
    logic        F8w8Agr;
    logic        SQ5L2T;
    logic [2:0]  rUH9bYT1;
    logic        vchjfm;
    logic [1:0]  uBH1Gp;
    logic        ziZG3f3w85eBr;
    logic        UcLmtF;
    logic        kSk;
    logic        a6ln;
    logic        TIO8;
    logic [31:0] dmdxZ;
    logic [31:0] dIl7b;
    logic [31:0] YZm7Q;
    logic [31:0] EwU9w;
    logic [31:0] FBCHA;
    logic [31:0] txJRD;
    logic [31:0] DWlTlqRLiKeFQ;
    logic [31:0] gYB5AZf7Kq1I6;
    logic [31:0] bysc1V2cT;
    logic [31:0] tsAQZ5bKX;
    logic [31:0] Eew7nvb5T;
    logic [31:0] HdVOT0c25;
    logic [31:0] Y54pg83z5;
    logic [31:0] VvGqYiZH0Q;
    logic        WkwDlaJY;
    logic [31:0] aswkfYVCHk;
    logic [31:0] FA2lvEpcG4;
    logic [31:0] JYPAbNp3k;
    logic [31:0] lLYh8Ufl2;
    logic [31:0] oKihdL;
    logic [31:0] Ws9A5HuaS;
    logic        weM;
    logic        gHecFb;
    logic [31:0] zuVaW6J9Fuz1f;
    logic [31:0] c3y;
    logic [31:0] hAkC;
    logic [31:0] fCRWx;
    logic        Tc1U;
    logic [31:0] gF7sX6e;
    logic        iMdRf;
    logic        Hfvec;
    logic [31:0] fwSfv;
    logic [ 2:0] vdegv;
    logic [ 3:0] brsdv;
    logic [ 2:0] frddd;
    logic [ 4:0] ghtdb;
    logic [ 1:0] gbefv;
    logic [ 3:0] ntbtm;
    logic [ 3:0] fveev;
    logic        bffto;
    logic [ 4:0] wdudy;
    logic        dobvu;

    decoder cWDIi3Yip2wSVkI (
        .fetched_instr_i (fwSfv),
        .a_sel_o         (C56l2),
        .b_sel_o         (i2H9F),
        .alu_op_o        (eliEEt),
        .csr_op_o        (O1caGF),
        .csr_we_o        (yTOhJF),
        .mem_req_o       (F8w8Agr),
        .mem_we_o        (SQ5L2T),
        .mem_size_o      (rUH9bYT1),
        .gpr_we_o        (vchjfm),
        .wb_sel_o        (uBH1Gp),
        .illegal_instr_o (ziZG3f3w85eBr),
        .branch_o        (UcLmtF),
        .jal_o           (kSk),
        .jalr_o          (a6ln),
        .mret_o          (TIO8)
    );

    register_file v9QOWb9Pd9 (
        .clk_i          (clk_i),
        .write_enable_i (gHecFb),
        .write_addr_i   ({ntbtm[0],fveev}),
        .read_addr1_i   ({ghtdb[2:0],gbefv}),
        .read_addr2_i   ({frddd,ghtdb[4:3]}),
        .write_data_i   (oKihdL),
        .read_data1_o   (aswkfYVCHk),
        .read_data2_o   (FA2lvEpcG4)
    );

    alu VyeRFt4138f (
        .alu_op_i (eliEEt),
        .a_i      (JYPAbNp3k),
        .b_i      (lLYh8Ufl2),
        .result_o (VvGqYiZH0Q),
        .flag_o   (WkwDlaJY)
    );

    interrupt_controller otEsIBhkTruDLt9g5p0nxg (
        .clk_i       (clk_i),
        .rst_i       (rst_i),
        .exception_i (ziZG3f3w85eBr),
        .irq_req_i   (irq_req_i),
        .mie_i       (c3y[16]),
        .mret_i      (TIO8),
        .irq_ret_o   (irq_ret_o),
        .irq_cause_o (Ws9A5HuaS),
        .irq_o       (weM)
    );

    csr_controller e11Sx5yGo97INX2M (
        .clk_i          (clk_i),
        .rst_i          (rst_i),
        .trap_i         (Tc1U),
        .opcode_i       (O1caGF),
        .addr_i         ({vdegv,brsdv,frddd,ghtdb[4:3]}),
        .pc_i           (KD),
        .mcause_i       (gF7sX6e),
        .rs1_data_i     (aswkfYVCHk),
        .imm_data_i     (txJRD),
        .write_enable_i (yTOhJF),
        .read_data_o    (zuVaW6J9Fuz1f),
        .mie_o          (c3y),
        .mepc_o         (hAkC),
        .mtvec_o        (fCRWx)
    );

    assign Hfvec = stall_i;

    assign fwSfv = instr_i;

    assign instr_addr_o = KD;

    assign DWlTlqRLiKeFQ = '0;
    assign gYB5AZf7Kq1I6 = '1;

    assign dmdxZ = fwSfv[31] ? {gYB5AZf7Kq1I6,fwSfv[31:20]} :
                                 {DWlTlqRLiKeFQ,fwSfv[31:20]};
    assign dIl7b = {fwSfv[31:12],12'b0};
    assign EwU9w = fwSfv[31] ? {gYB5AZf7Kq1I6,fwSfv[31],fwSfv[7],fwSfv[30:25],fwSfv[11:8],1'b0} :
                                 {DWlTlqRLiKeFQ,fwSfv[31],fwSfv[7],fwSfv[30:25],fwSfv[11:8],1'b0};

    assign RPgcnv34Ab8 = aswkfYVCHk + dmdxZ;

    assign gHecFb = DWlTlqRLiKeFQ | vchjfm & ~(Hfvec | Tc1U);

    assign bysc1V2cT = UcLmtF ? EwU9w :
                                FBCHA;
    assign tsAQZ5bKX = WkwDlaJY & UcLmtF | kSk ? bysc1V2cT :
                                                 'd4;
    assign Eew7nvb5T = a6ln ? {RPgcnv34Ab8[31:1],1'b0} :
                              KD + tsAQZ5bKX;
    assign YZm7Q = fwSfv[31] ? {gYB5AZf7Kq1I6,fwSfv[31:25],fwSfv[11:7]} :
                                 {DWlTlqRLiKeFQ,fwSfv[31:25],fwSfv[11:7]};

    assign HdVOT0c25 = Tc1U ? fCRWx : Eew7nvb5T;
    assign txJRD = fwSfv[19] ? {gYB5AZf7Kq1I6,fwSfv[19:15]} :
                                 {DWlTlqRLiKeFQ,fwSfv[19:15]};
    assign Y54pg83z5 = TIO8 ? hAkC : HdVOT0c25;

    assign JYPAbNp3k = C56l2 == 'd0 ? aswkfYVCHk :
                       C56l2 == 'd1 ? KD :
                                      'd0;
    assign mem_wd_o = FA2lvEpcG4;
    assign FBCHA = fwSfv[31] ? {gYB5AZf7Kq1I6,fwSfv[31],fwSfv[19:12],fwSfv[20],fwSfv[30:21],1'b0} :
                                 {DWlTlqRLiKeFQ,fwSfv[31],fwSfv[19:12],fwSfv[20],fwSfv[30:21],1'b0};

    assign vdegv = fwSfv[31:29];

    assign brsdv = fwSfv[28:25];

    assign frddd = fwSfv[24:22];

    assign ghtdb = fwSfv[21:17];

    assign gbefv = fwSfv[16:15];

    assign ntbtm = fwSfv[14:11];

    assign fveev = fwSfv[10:7];

    assign bffto = fwSfv[6];

    assign wdudy = fwSfv[5:1];

    assign dobvu = fwSfv[0];

    assign lLYh8Ufl2 = i2H9F == 'd0 ? FA2lvEpcG4 :
                       i2H9F == 'd1 ? dmdxZ :
                       i2H9F == 'd2 ? dIl7b :
                       i2H9F == 'd3 ? YZm7Q :
                                      'd4;
    assign mem_addr_o = VvGqYiZH0Q;

    assign oKihdL = uBH1Gp == 'd1 ? mem_rd_i :
                    uBH1Gp == 'd2 ? zuVaW6J9Fuz1f :
                                    VvGqYiZH0Q;

    assign mem_size_o = rUH9bYT1;

    assign gF7sX6e = ziZG3f3w85eBr ? 32'h2 : Ws9A5HuaS;

    assign lpgJ988DA = ldF0poVEX4 (F8w8Agr, SQ5L2T, Hfvec, weM, ziZG3f3w85eBr);
    assign Pv09590YSbZIv4 = VL5PghYXdkG6kEn (F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr);
    assign vNHUYwUZvaeU4 = Kgs4sx4nQ5ZCQK (F8w8Agr, SQ5L2T, Tc1U, weM, ziZG3f3w85eBr);
    assign pSbkt4Sk4Y = WmQYuPf7wm0 (F8w8Agr, SQ5L2T, Tc1U, Hfvec, ziZG3f3w85eBr);

    always_comb begin
        case (lpgJ988DA)
            'b0:
            Tc1U = 'b0;
            'b1:
            Tc1U = 'b1;
            default:
            Tc1U = 1'b0;
        endcase
        case (Pv09590YSbZIv4)
            'b0:
            mem_req_o = 'b0;
            'b1:
            mem_req_o = 'b1;
            default:
            mem_req_o = 1'b0;
        endcase
        case (vNHUYwUZvaeU4)
            'b0:
            mem_we_o = 'b0;
            'b1:
            mem_we_o = 'b1;
            default:
            mem_we_o = 1'b0;
        endcase
        case (pSbkt4Sk4Y)
            'b0:
            iMdRf = 'b0;
            'b1:
            iMdRf = 'b1;
            default:
            iMdRf = 1'b0;
        endcase
    end

    always_ff @(posedge clk_i or posedge rst_i) begin
        if      (rst_i) KD <= 'b0;
        else if (iMdRf) KD <= Y54pg83z5;
    end

endmodule
