-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcpu.v
518 lines (451 loc) · 11.5 KB
/
cpu.v
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
/*
Authored 2018-2019, Ryan Voo.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the following
disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/*
* cpu top-level
*/
module cpu(
clk,
inst_mem_in,
inst_mem_out,
data_mem_out,
data_mem_addr,
data_mem_WrData,
data_mem_memwrite,
data_mem_memread,
data_mem_sign_mask
);
/*
* Input Clock
*/
input clk;
/*
* instruction memory input
*/
output [31:0] inst_mem_in;
input [31:0] inst_mem_out;
/*
* Data Memory
*/
input [31:0] data_mem_out;
output [31:0] data_mem_addr;
output [31:0] data_mem_WrData;
output data_mem_memwrite;
output data_mem_memread;
output [3:0] data_mem_sign_mask;
/*
* Program Counter
*/
wire [31:0] pc_mux0;
wire [31:0] pc_in;
wire [31:0] pc_out;
wire pcsrc;
wire [31:0] inst_mux_out;
wire [31:0] fence_mux_out;
/*
* Pipeline Registers
*/
wire [63:0] if_id_out;
wire [177:0] id_ex_out;
wire [154:0] ex_mem_out;
wire [116:0] mem_wb_out;
/*
* Control signals
*/
wire MemtoReg1;
wire RegWrite1;
wire MemWrite1;
wire MemRead1;
wire Branch1;
wire Jump1;
wire Jalr1;
wire ALUSrc1;
wire Lui1;
wire Auipc1;
wire Fence_signal;
wire CSRR_signal;
wire CSRRI_signal;
/*
* Decode stage
*/
wire [31:0] cont_mux_out; //control signal mux
wire [31:0] regA_out;
wire [31:0] regB_out;
wire [31:0] imm_out;
wire [31:0] RegA_mux_out;
wire [31:0] RegB_mux_out;
wire [31:0] RegA_AddrFwdFlush_mux_out;
wire [31:0] RegB_AddrFwdFlush_mux_out;
wire [31:0] rdValOut_CSR;
wire [3:0] dataMem_sign_mask;
/*
* Execute stage
*/
wire [31:0] ex_cont_mux_out;
wire [31:0] addr_adder_mux_out;
wire [31:0] alu_mux_out;
wire [31:0] addr_adder_sum;
wire [6:0] alu_ctl;
wire alu_branch_enable;
wire [31:0] alu_result;
wire [31:0] lui_result;
/*
* Memory access stage
*/
wire [31:0] auipc_mux_out;
wire [31:0] mem_csrr_mux_out;
/*
* Writeback to registers stage
*/
wire [31:0] wb_mux_out;
wire [31:0] reg_dat_mux_out;
/*
* Forwarding multiplexer wires
*/
wire [31:0] dataMemOut_fwd_mux_out;
wire [31:0] mem_fwd1_mux_out;
wire [31:0] mem_fwd2_mux_out;
wire [31:0] wb_fwd1_mux_out;
wire [31:0] wb_fwd2_mux_out;
wire mfwd1;
wire mfwd2;
wire wfwd1;
wire wfwd2;
/*
* Branch Predictor
*/
wire [31:0] pc_adder_out;
wire [31:0] branch_predictor_addr;
wire predict;
wire [31:0] branch_predictor_mux_out;
wire actual_branch_decision;
wire mistake_trigger;
wire decode_ctrl_mux_sel;
wire inst_mux_sel;
/*
* Instruction Fetch Stage
*/
mux2to1 pc_mux(
.input0(pc_mux0),
.input1(ex_mem_out[72:41]),
.select(pcsrc),
.out(pc_in)
);
adder pc_adder(
.input1(32'b100),
.input2(pc_out),
.out(pc_adder_out)
);
program_counter PC(
.inAddr(pc_in),
.outAddr(pc_out),
.clk(clk)
);
mux2to1 inst_mux(
.input0(inst_mem_out),
.input1(32'b0),
.select(inst_mux_sel),
.out(inst_mux_out)
);
mux2to1 fence_mux(
.input0(pc_adder_out),
.input1(pc_out),
.select(Fence_signal),
.out(fence_mux_out)
);
/*
* IF/ID Pipeline Register
*/
if_id if_id_reg(
.clk(clk),
.data_in({inst_mux_out, pc_out}),
.data_out(if_id_out)
);
/*
* Decode Stage
*/
control control_unit(
.opcode({if_id_out[38:32]}),
.MemtoReg(MemtoReg1),
.RegWrite(RegWrite1),
.MemWrite(MemWrite1),
.MemRead(MemRead1),
.Branch(Branch1),
.ALUSrc(ALUSrc1),
.Jump(Jump1),
.Jalr(Jalr1),
.Lui(Lui1),
.Auipc(Auipc1),
.Fence(Fence_signal),
.CSRR(CSRR_signal)
);
mux2to1 cont_mux(
.input0({21'b0, Jalr1, ALUSrc1, Lui1, Auipc1, Branch1, MemRead1, MemWrite1, CSRR_signal, RegWrite1, MemtoReg1, Jump1}),
.input1(32'b0),
.select(decode_ctrl_mux_sel),
.out(cont_mux_out)
);
regfile register_files(
.clk(clk),
.write(ex_mem_out[2]),
.wrAddr(ex_mem_out[142:138]),
.wrData(reg_dat_mux_out),
.rdAddrA(inst_mux_out[19:15]),
.rdDataA(regA_out),
.rdAddrB(inst_mux_out[24:20]),
.rdDataB(regB_out)
);
imm_gen immediate_generator(
.inst(if_id_out[63:32]),
.imm(imm_out)
);
ALUControl alu_control(
.Opcode(if_id_out[38:32]),
.FuncCode({if_id_out[62], if_id_out[46:44]}),
.ALUCtl(alu_ctl)
);
sign_mask_gen sign_mask_gen_inst(
.func3(if_id_out[46:44]),
.sign_mask(dataMem_sign_mask)
);
csr_file ControlAndStatus_registers(
.clk(clk),
.write(mem_wb_out[3]), //TODO
.wrAddr_CSR(mem_wb_out[116:105]),
.wrVal_CSR(mem_wb_out[35:4]),
.rdAddr_CSR(inst_mux_out[31:20]),
.rdVal_CSR(rdValOut_CSR)
);
mux2to1 RegA_mux(
.input0(regA_out),
.input1({27'b0, if_id_out[51:47]}),
.select(CSRRI_signal),
.out(RegA_mux_out)
);
mux2to1 RegB_mux(
.input0(regB_out),
.input1(rdValOut_CSR),
.select(CSRR_signal),
.out(RegB_mux_out)
);
mux2to1 RegA_AddrFwdFlush_mux( //TODO cleanup
.input0({27'b0, if_id_out[51:47]}),
.input1(32'b0),
.select(CSRRI_signal),
.out(RegA_AddrFwdFlush_mux_out)
);
mux2to1 RegB_AddrFwdFlush_mux( //TODO cleanup
.input0({27'b0, if_id_out[56:52]}),
.input1(32'b0),
.select(CSRR_signal),
.out(RegB_AddrFwdFlush_mux_out)
);
assign CSRRI_signal = CSRR_signal & (if_id_out[46]);
//ID/EX Pipeline Register
id_ex id_ex_reg(
.clk(clk),
.data_in({if_id_out[63:52], RegB_AddrFwdFlush_mux_out[4:0], RegA_AddrFwdFlush_mux_out[4:0], if_id_out[43:39], dataMem_sign_mask, alu_ctl, imm_out, RegB_mux_out, RegA_mux_out, if_id_out[31:0], cont_mux_out[10:7], predict, cont_mux_out[6:0]}),
.data_out(id_ex_out)
);
//Execute stage
mux2to1 ex_cont_mux(
.input0({23'b0, id_ex_out[8:0]}),
.input1(32'b0),
.select(pcsrc),
.out(ex_cont_mux_out)
);
mux2to1 addr_adder_mux(
.input0(id_ex_out[43:12]),
.input1(wb_fwd1_mux_out),
.select(id_ex_out[11]),
.out(addr_adder_mux_out)
);
adder addr_adder(
.input1(addr_adder_mux_out),
.input2(id_ex_out[139:108]),
.out(addr_adder_sum)
);
mux2to1 alu_mux(
.input0(wb_fwd2_mux_out),
.input1(id_ex_out[139:108]),
.select(id_ex_out[10]),
.out(alu_mux_out)
);
alu alu_main(
.ALUctl(id_ex_out[146:140]),
.A(wb_fwd1_mux_out),
.B(alu_mux_out),
.ALUOut(alu_result),
.Branch_Enable(alu_branch_enable)
);
mux2to1 lui_mux(
.input0(alu_result),
.input1(id_ex_out[139:108]),
.select(id_ex_out[9]),
.out(lui_result)
);
//EX/MEM Pipeline Register
ex_mem ex_mem_reg(
.clk(clk),
.data_in({id_ex_out[177:166], id_ex_out[155:151], wb_fwd2_mux_out, lui_result, alu_branch_enable, addr_adder_sum, id_ex_out[43:12], ex_cont_mux_out[8:0]}),
.data_out(ex_mem_out)
);
//Memory Access Stage
branch_decision branch_decide(
.Branch(ex_mem_out[6]),
.Predicted(ex_mem_out[7]),
.Branch_Enable(ex_mem_out[73]),
.Jump(ex_mem_out[0]),
.Mispredict(mistake_trigger),
.Decision(actual_branch_decision),
.Branch_Jump_Trigger(pcsrc)
);
mux2to1 auipc_mux(
.input0(ex_mem_out[105:74]),
.input1(ex_mem_out[72:41]),
.select(ex_mem_out[8]),
.out(auipc_mux_out)
);
mux2to1 mem_csrr_mux(
.input0(auipc_mux_out),
.input1(ex_mem_out[137:106]),
.select(ex_mem_out[3]),
.out(mem_csrr_mux_out)
);
//MEM/WB Pipeline Register
mem_wb mem_wb_reg(
.clk(clk),
.data_in({ex_mem_out[154:143], ex_mem_out[142:138], data_mem_out, mem_csrr_mux_out, ex_mem_out[105:74], ex_mem_out[3:0]}),
.data_out(mem_wb_out)
);
//Writeback to Register Stage
mux2to1 wb_mux(
.input0(mem_wb_out[67:36]),
.input1(mem_wb_out[99:68]),
.select(mem_wb_out[1]),
.out(wb_mux_out)
);
mux2to1 reg_dat_mux( //TODO cleanup
.input0(mem_regwb_mux_out),
.input1(id_ex_out[43:12]),
.select(ex_mem_out[0]),
.out(reg_dat_mux_out)
);
//Forwarding Unit
ForwardingUnit forwarding_unit(
.rs1(id_ex_out[160:156]),
.rs2(id_ex_out[165:161]),
.MEM_RegWriteAddr(ex_mem_out[142:138]),
.WB_RegWriteAddr(mem_wb_out[104:100]),
.MEM_RegWrite(ex_mem_out[2]),
.WB_RegWrite(mem_wb_out[2]),
.EX_CSRR_Addr(id_ex_out[177:166]),
.MEM_CSRR_Addr(ex_mem_out[154:143]),
.WB_CSRR_Addr(mem_wb_out[116:105]),
.MEM_CSRR(ex_mem_out[3]),
.WB_CSRR(mem_wb_out[3]),
.MEM_fwd1(mfwd1),
.MEM_fwd2(mfwd2),
.WB_fwd1(wfwd1),
.WB_fwd2(wfwd2)
);
mux2to1 mem_fwd1_mux(
.input0(id_ex_out[75:44]),
.input1(dataMemOut_fwd_mux_out),
.select(mfwd1),
.out(mem_fwd1_mux_out)
);
mux2to1 mem_fwd2_mux(
.input0(id_ex_out[107:76]),
.input1(dataMemOut_fwd_mux_out),
.select(mfwd2),
.out(mem_fwd2_mux_out)
);
mux2to1 wb_fwd1_mux(
.input0(mem_fwd1_mux_out),
.input1(wb_mux_out),
.select(wfwd1),
.out(wb_fwd1_mux_out)
);
mux2to1 wb_fwd2_mux(
.input0(mem_fwd2_mux_out),
.input1(wb_mux_out),
.select(wfwd2),
.out(wb_fwd2_mux_out)
);
mux2to1 dataMemOut_fwd_mux(
.input0(ex_mem_out[105:74]),
.input1(data_mem_out),
.select(ex_mem_out[1]),
.out(dataMemOut_fwd_mux_out)
);
//Branch Predictor
branch_predictor branch_predictor_FSM(
.clk(clk),
.actual_branch_decision(actual_branch_decision),
.branch_decode_sig(cont_mux_out[6]),
.branch_mem_sig(ex_mem_out[6]),
.in_addr(if_id_out[31:0]),
.offset(imm_out),
.branch_addr(branch_predictor_addr),
.prediction(predict)
);
mux2to1 branch_predictor_mux(
.input0(fence_mux_out),
.input1(branch_predictor_addr),
.select(predict),
.out(branch_predictor_mux_out)
);
mux2to1 mistaken_branch_mux(
.input0(branch_predictor_mux_out),
.input1(id_ex_out[43:12]),
.select(mistake_trigger),
.out(pc_mux0)
);
wire[31:0] mem_regwb_mux_out; //TODO copy of wb_mux but in mem stage, move back and cleanup
//A copy of the writeback mux, but in MEM stage //TODO move back and cleanup
mux2to1 mem_regwb_mux(
.input0(mem_csrr_mux_out),
.input1(data_mem_out),
.select(ex_mem_out[1]),
.out(mem_regwb_mux_out)
);
//OR gate assignments, used for flushing
assign decode_ctrl_mux_sel = pcsrc | mistake_trigger;
assign inst_mux_sel = pcsrc | predict | mistake_trigger | Fence_signal;
//Instruction Memory Connections
assign inst_mem_in = pc_out;
//Data Memory Connections
assign data_mem_addr = lui_result;
assign data_mem_WrData = wb_fwd2_mux_out;
assign data_mem_memwrite = ex_cont_mux_out[4];
assign data_mem_memread = ex_cont_mux_out[5];
assign data_mem_sign_mask = id_ex_out[150:147];
endmodule