aboutsummaryrefslogtreecommitdiff
path: root/core/rtl/exe.sv
blob: 46156388f91b1e0e6f754c4265b7175c3bcf29b6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
module exe (
    input logic clk,
    input logic rst,

    //-----------------
    // Decode Interface
    //-----------------
    input logic               idu_exe_rs1Vld_EXE,
    input logic [REG_IDX-1:0] idu_exe_rs1Idx_EXE,

    input logic               idu_exe_rs2Vld_EXE,
    input logic [REG_IDX-1:0] idu_exe_rs2Idx_EXE,

    input alu_op_t idu_exe_aluOp_EXE,

    //-----------------
    // Memory Interface
    //-----------------
    output logic [WORD_WID-1:0] exe_mem_aluOpOut_EXE,

    //-----------------------
    // Fetch Branch Interface
    //-----------------------
    output logic                exe_ifu_brRes_EXE,
    output logic                exe_ifu_brTaken_EXE,
    output logic [WORD_WID-1:0] exe_ifu_brPC_EXE,

    //--------------------
    // Writeback Interface
    //--------------------
    input logic                wb_exe_rdVld_WB,
    input logic [ REG_IDX-1:0] wb_exe_rdIdx_WB,
    input logic [WORD_WID-1:0] wb_exe_rdData_WB

);

  // Alu
  logic [WORD_WID-1:0] aluSumDiff_EXE;
  logic [WORD_WID-1:0] aluSumDiffIn1_EXE;
  logic [WORD_WID-1:0] aluSumDiffIn2_EXE;

  logic [WORD_WID-1:0] aluLeftShft_EXE;
  logic [WORD_WID-1:0] aluRightShft_EXE;
  logic [WORD_WID-1:0] aluRightShftUsign_EXE;
  logic [WORD_WID-1:0] aluRightShftSext_EXE;

  logic [WORD_WID-1:0] aluCmp_EXE;
  logic [WORD_WID-1:0] aluCmpSign_EXE;
  logic [WORD_WID-1:0] aluCmpUsign_EXE;
  logic                aluCmpMsbDiff_EXE;
  logic                aluCmpLowUsign_EXE;

  // Branch Resolution
  logic [         5:0] brResChoice_EXE;

  //--------------------
  // Decode Output Flops
  //--------------------
  assign stallVld_ID = ~exe_idu_exeRdy_EXE;

  // Flop Decode information
  AFF #( .DTYPE(alu_op_t) ) AFF_EXE_aluOp    ( .q(idu_exe_aluOp_EXE),    .d(idu_exe_aluOp_ID),    .en(stallVld_ID), .clk(clk) );
  AFF #( .WIDTH(WORD_WID) ) AFF_EXE_pc       ( .q(idu_exe_pc_EXE),       .d(idu_exe_pc_ID),       .en(stallVld_ID), .clk(clk) );
  AFF #( .WIDTH(1)        ) AFF_EXE_instrJmp ( .q(idu_exe_instrJmp_EXE), .d(idu_exe_instrJmp_ID), .en(stallVld_ID), .clk(clk) );
  AFF #( .WIDTH(1)        ) AFF_EXE_brRes    ( .q(idu_exe_brRes_EXE),    .d(brResNxt_EXEM1),      .en(stallVld_ID), .clk(clk) );

  //--------------
  // Register File
  //--------------
  // FIXME: Add support for the zero register
  always_ff @(posedge clk) begin

    // RS1 Read Port with Forwarding
    if (instrRs1Vld_ID) begin
      idu_exe_rs1Data_EXE <= (wb_exe_rdVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB)) ? wb_exe_rdData_WB : regData_XXX[idu_exe_rs1Idx_ID];
    end

    // RS2 Read Port with Forwarding
    if (instrRdVld_ID) begin
      idu_exe_rs2Data_EXE <= (wb_exe_rdVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB)) ? wb_exe_rdData_WB : regData_XXX[idu_exe_rs2Idx_ID];
    end

    // RD Write Port
    if (wb_exe_rdData_WB) begin
      regData_XXX[wb_exe_rdIdx_WB] <= wb_exe_rdData_WB;
    end

  end

  //----
  // ALU
  //----

  // Operand Selection
  assign aluIn1_EXE = (aluOp_EXE.rs1Sel == PC) ? pc_EXE :  // PC for AUIPC, JAL
      (aluOp_EXE.rs1Sel == ZERO) ? WORD_WID'(0) :  // 0 for LUI
      rs1Data_EXE;  // RS1 for other operations

  assign aluIn2_EXE = (aluOp_EXE.rs2Sel == RS2) ? rs2Data_EXE :  // RS2 for R type operations
      aluOp_EXE.immediate;  // Immediate for all other operations

  // Two's complement negation of aluIn2 if func7 is set (subtract)
  assign aluSumDiffIn1_EXE = aluIn1_EXE;
  assign aluSumDiffIn2_EXE = ({WORD_WID{aluOp_EXE.func7}} ^ aluIn2_EXE) + aluOp_EXE.func7;
  assign aluSumDiff_EXE = aluSumDiffIn1_EXE + aluSumDiffIn2_EXE;

  // Shifter, TODO: Explicit signed barrel shifter
  assign aluRightShftUsign_EXE = aluIn1_EXE >> aluIn2_EXE[4:0];
  assign aluRightShftSext_EXE = ~({WORD_WID{1'b1}} >> aluIn2_EXE[4:0]);
  assign aluRightShft_EXE      = aluRightShftUsgn_EXE | (aluRightShftSext_EXE & {WORD_WID{aluOp_EXE.func7}});

  FLIP #(
      .WIDTH(WORD_WID)
  ) EXE_aluLeftShft (
      .in (aluRightShftUsign_EXE),
      .out(aluLeftShft_EXE)
  );

  // Set Less Than
  assign aluCmpMsbDiff_EXE = aluIn2_EXE ^ aluIn1_EXE;
  assign aluCmpLowUsign_EXE = aluIn1_EXE[WORD_WID-2:0] < aluIn2_EXE[WORD_WID-2:0];
  assign aluCmpSign_EXE        = aluCmpMsbDiff_EXE ? aluIn1_EXE[WORD_WID-1] : aluCmpLowUsign_EXE; // If diff signs (MSB) and in1 negative, then in1 < 0 < in2, else compare low bits
  assign aluCmpUSign_EXE       = aluCmpMsbDiff_EXE ? aluIn2_EXE[WORD_WID-1] : aluCmpLowUsign_EXE; // If diff MSB and MSB in2[31] == 1,     then in1 < in2,     else compare low bits

  // Bitwise Operations
  assign aluXor_EXE = aluIn1_EXE ^ aluIn2_EXE;
  assign aluOr_EXE = aluIn1_EXE | aluIn2_EXE;
  assign aluAnd_EXE = aluIn1_EXE & aluIn2_EXE;

  // ALU Operation Select
  assign aluOpRes_EXE[0] = aluSumDiff_EXE;
  assign aluOpRes_EXE[1] = aluLeftShft_EXE;
  assign aluOpRes_EXE[2] = {(WORD_WID - 1)'(0), aluCmpSign_EXE};
  assign aluOpRes_EXE[3] = {(WORD_WID - 1)'(0), aluCmpUSign_EXE};
  assign aluOpRes_EXE[4] = aluXor_EXE;
  assign aluOpRes_EXE[5] = aluRightShft_EXE;
  assign aluOpRes_EXE[6] = aluOr_EXE;
  assign aluOpRes_EXE[7] = aluAnd_EXE;

  EMUX #(
      .WIDTH (WORD_WID),
      .INPUTS(8)
  ) EMUX_exe_aluOpSel (
      .in (aluOpResults_EXE),
      .out(aluOpOut_EXE),
      .sel(aluOp_EXE.func3)
  );

  // rd is either PC from jump instr or alu output
  assign exe_mem_rdData_EXE = instrJmp_EXE ? pc_EXE : aluOpOut_EXE;

  //------------------
  // Branch Resolution
  //------------------
  assign exe_ifu_brPC_EXE = aluOpOut_EXE;
  assign exe_ifu_brRes_EXE    = brRes_EXE;    // FIXME: Only send this once after a branch is processed until stall is lifted

  assign brResChoice_EXE[0] = ~|aluXor_EXE;
  assign brResChoice_EXE[1] = |aluXor_EXE;
  assign brResChoice_EXE[2] = aluCmpSign_EXE;
  assign brResChoice_EXE[3] = ~aluCmpSign_EXE;
  assign brResChoice_EXE[4] = aluCmpUSign_EXE;
  assign brResChoice_EXE[5] = ~aluCmpUSign_EXE;

  EMUX #(
      .WIDTH (1),
      .INPUTS(6)
  ) EMUX_exe_aluOpSel (
      .in (brResChoice_EXE),
      .out(exe_ifu_brTaken_EXE),
      .sel(idu_exe_brOp_ID)
  );

  //---------------------
  // Pipeline passthrough
  //---------------------


endmodule