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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
module exe (
input logic clk,
input logic rst,
//-----------------
// Decode Interface
//-----------------
input logic idu_exe_instrVld_ID,
// Register Access
input logic idu_exe_rs1Vld_ID,
input logic [REG_IDX-1:0] idu_exe_rs1Idx_ID,
input logic idu_exe_rs2Vld_ID,
input logic [REG_IDX-1:0] idu_exe_rs2Idx_ID,
// Branch Type
input logic idu_exe_instrJmp_ID,
input logic idu_exe_instrBr_ID,
// ALU information
input alu_op_t idu_exe_aluOp_ID,
// Passthrough Information
input mem_op_t idu_exe_instrMemOp_ID,
input mem_size_t idu_exe_instrMemSize_ID,
input rd_data_sel_t idu_exe_instrRdDataSel_ID,
//-----------------
// Memory Interface
//-----------------
// ALU Result information
output logic [WORD_WID-1:0] exe_mem_aluOpOut_EXE,
// Stall
input logic mem_exe_stallVld_EXE,
// Memory Information
output mem_op_t exe_mem_instrMemOp_EXE,
output mem_size_t exe_mem_instrMemSize_EXE,
// Passthrough information
output rd_data_sel_t exe_mem_instrRdDataSel_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
);
logic instrVld_EXE;
// 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;
// Reg File
logic [NUM_REG-1:1] [WORD_WID-1:0] regData_XXX;
// Stall Signal
assign stallVld_ID = exe_mem_instrVld_EXE & ~mem_exe_stallVld_EXE;
//--------------------
// Decode Output Flops
//--------------------
// Flop Decode information
AFFR #(.WIDTH(1)) AFFR_EXE_instrVld (.q(exe_mem_instrVld_EXE), .d(idu_exe_instrVld_ID), .en(stallVld_ID), .clk(clk), rst(rst));
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
//--------------
assign rs1WrFwd_ID = wb_exe_rdWrVld_WB & (idu_exe_rs1Idx_ID == wb_exe_rdIdx_WB);
assign rs2WrFwd_ID = wb_exe_rdWrVld_WB & (idu_exe_rs2Idx_ID == wb_exe_rdIdx_WB);
always_ff @(posedge clk) begin
// RS1 Read Port with Forwarding
if (instrRs1Vld_ID) begin
if (idx_exe_rs1Idx == REG_IDX'0) // X0 Register
idu_exe_rs1Data_EXE <= WORD_SIZE'0;
else if (rs1WrFwd_ID) begin // Write Foward
idu_exe_rs1Data_EXE <= wb_exe_rdData_WB;
else // Normal Read
idu_exe_rs1Data_EXE <= regData_XXX[idu_exe_rs1Idx_ID];
end
// RS2 Read Port with Forwarding
if (instrRs2Vld_ID) begin
if (idx_exe_rs2Idx == REG_IDX'0) // X0 Register
idu_exe_rs2Data_EXE <= WORD_WID'0;
else if (rs2WrFwd_ID) begin // Write Foward
idu_exe_rs2Data_EXE <= wb_exe_rdData_WB;
else // Normal Read
idu_exe_rs2Data_EXE <= regData_XXX[idu_exe_rs1Idx_ID];
end
// RD Write Port
if (wb_exe_rdWrVld_WB & (~|wb_exe_rdIdx_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 with sign bit
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;
assign exe_ifu_brTaken_EXE = (brTaken_EXE & idu_exe_instrBr_ID) | idu_exe_instrJmp_ID;
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(brTaken_EXE),
.sel(idu_exe_brOp_ID)
);
//---------------------
// Pipeline passthrough
//---------------------
// Memory
AFF #(.DTYPE(mem_op_t)) AFF_EXE_instRdDataSel (
.q(exe_mem_instrMemOp_EXE),
.d(idu_exe_instrMemOp_ID),
.en(stallVld_ID),
.clk(clk)
);
AFF #(.DTYPE(mem_op_size_t)) AFF_EXE_instMemSize (
.q(exe_mem_instrMemSize_EXE),
.d(idu_exe_instrMemSize_ID),
.en(stallVld_ID),
.clk(clk)
);
// Write Back
AFF #(.DTYPE(rd_data_sel_t)) AFF_EXE_instRdDataSel (
.q(exe_mem_instrRdDataSel_EXE),
.d(idu_exe_instrRdDataSel_ID),
.en(stallVld_ID),
.clk(clk)
);
endmodule
|