-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmycpu_top.v
330 lines (291 loc) · 10.3 KB
/
mycpu_top.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
module mycpu_top (
input wire clk,
input wire resetn,
// inst sram interface
output wire inst_sram_en, //添加指令RAM片选信号
output wire [ 3:0] inst_sram_we, //改为4位的字节写使能信号
output wire [31:0] inst_sram_addr,
output wire [31:0] inst_sram_wdata,
input wire [31:0] inst_sram_rdata,
// data sram interface
output wire data_sram_en, //添加数据RAM片选信号
output wire [ 3:0] data_sram_we,
output wire [31:0] data_sram_addr,
output wire [31:0] data_sram_wdata,
input wire [31:0] data_sram_rdata,
// trace debug interface
output wire [31:0] debug_wb_pc,
output wire [ 3:0] debug_wb_rf_we,
output wire [ 4:0] debug_wb_rf_wnum,
output wire [31:0] debug_wb_rf_wdata
);
wire reset;
assign reset = ~resetn;
wire [31:0] seq_pc;
wire [31:0] nextpc;
wire br_taken;
wire [31:0] br_target;
wire [31:0] inst;
reg [31:0] pc;
wire [11:0] alu_op;
wire load_op;
wire src1_is_pc;
wire src2_is_imm;
wire res_from_mem;
wire dst_is_r1;
wire gr_we;
wire mem_we;
wire src_reg_is_rd;
wire [ 4:0] dest;
wire [31:0] rj_value;
wire [31:0] rkd_value;
wire [31:0] imm;
wire [31:0] br_offs;
wire [31:0] jirl_offs;
wire [ 5:0] op_31_26;
wire [ 3:0] op_25_22;
wire [ 1:0] op_21_20;
wire [ 4:0] op_19_15;
wire [ 4:0] rd;
wire [ 4:0] rj;
wire [ 4:0] rk;
wire [11:0] i12;
wire [19:0] i20;
wire [15:0] i16;
wire [25:0] i26;
wire [63:0] op_31_26_d;
wire [15:0] op_25_22_d;
wire [ 3:0] op_21_20_d;
wire [31:0] op_19_15_d;
wire inst_add_w;
wire inst_sub_w;
wire inst_slt;
wire inst_sltu;
wire inst_nor;
wire inst_and;
wire inst_or;
wire inst_xor;
wire inst_slli_w;
wire inst_srli_w;
wire inst_srai_w;
wire inst_addi_w;
wire inst_ld_w;
wire inst_st_w;
wire inst_jirl;
wire inst_b;
wire inst_bl;
wire inst_beq;
wire inst_bne;
wire inst_lu12i_w;
wire need_ui5;
wire need_si12;
wire need_si16;
wire need_si20;
wire need_si26;
wire src2_is_4;
wire [ 4:0] rf_raddr1;
wire [31:0] rf_rdata1;
wire [ 4:0] rf_raddr2;
wire [31:0] rf_rdata2;
wire rf_we;
wire [ 4:0] rf_waddr;
wire [31:0] rf_wdata;
wire [31:0] alu_src1;
wire [31:0] alu_src2;
wire [31:0] alu_result;
wire [31:0] mem_result;
wire [31:0] ms_final_result;
// 修改
wire valid; // 缓存有效信号
wire IF; // 指令取指
wire ID; // 指令译码
wire EXE; // 指令执行
wire MEM; // 存储访问
wire WB; // 写回
wire pre_fetch;
assign pre_fetch = WB;
// 预取,使用的是同步指令RAM,因此在发起读命令后,需要等待一个周期才能读到数据
// 在IF前一个周期发起读命令
// 更改取指逻辑,使用nextpc作为取指地址,而不是pc
assign valid = 1'b1;
wire [31:0] final_result;
reg [ 2:0] cycle_cnt = 3'b0;
reg [31:0] IDreg; //级间缓存
reg [31:0] EXEreg;
reg [31:0] MEMreg;
reg [31:0] WBreg;
reg [31:0] IFreg;
assign IF = (cycle_cnt == 3'b0);
assign ID = (cycle_cnt == 3'b1);
assign EXE = (cycle_cnt == 3'd2);
assign MEM = (cycle_cnt == 3'd3);
assign WB = (cycle_cnt == 3'd4);
assign seq_pc = pc + 3'h4;
assign nextpc = br_taken ? br_target : seq_pc;
assign inst_sram_en = pre_fetch;
assign inst_sram_we = 4'b0;
assign inst_sram_addr = nextpc;
assign inst_sram_wdata = 32'b0;
assign inst = IDreg;
assign op_31_26 = inst[31:26];
assign op_25_22 = inst[25:22];
assign op_21_20 = inst[21:20];
assign op_19_15 = inst[19:15];
assign rd = inst[4:0];
assign rj = inst[9:5];
assign rk = inst[14:10];
assign i12 = inst[21:10];
assign i20 = inst[24:5];
assign i16 = inst[25:10];
assign i26 = {inst[9:0], inst[25:10]};
decoder_6_64 u_dec0 (
.in (op_31_26),
.out(op_31_26_d)
);
decoder_4_16 u_dec1 (
.in (op_25_22),
.out(op_25_22_d)
);
decoder_2_4 u_dec2 (
.in (op_21_20),
.out(op_21_20_d)
);
decoder_5_32 u_dec3 (
.in (op_19_15),
.out(op_19_15_d)
);
assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00];
assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02];
assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04];
assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05];
assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08];
assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09];
assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a];
assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b];
assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01];
assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09];
assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11];
assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha];
assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2];
assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6];
assign inst_jirl = op_31_26_d[6'h13];
assign inst_b = op_31_26_d[6'h14];
assign inst_bl = op_31_26_d[6'h15];
assign inst_beq = op_31_26_d[6'h16];
assign inst_bne = op_31_26_d[6'h17];
assign inst_lu12i_w = op_31_26_d[6'h05] & ~inst[25];
assign alu_op[0] = inst_add_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | inst_bl;
assign alu_op[1] = inst_sub_w;
assign alu_op[2] = inst_slt;
assign alu_op[3] = inst_sltu;
assign alu_op[4] = inst_and;
assign alu_op[5] = inst_nor;
assign alu_op[6] = inst_or;
assign alu_op[7] = inst_xor;
assign alu_op[8] = inst_slli_w;
assign alu_op[9] = inst_srli_w;
assign alu_op[10] = inst_srai_w;
assign alu_op[11] = inst_lu12i_w;
assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w;
assign need_si12 = inst_addi_w | inst_ld_w | inst_st_w;
assign need_si16 = inst_jirl | inst_beq | inst_bne;
assign need_si20 = inst_lu12i_w;
assign need_si26 = inst_b | inst_bl;
assign src2_is_4 = inst_jirl | inst_bl;
always @(posedge clk) begin
if (reset) begin
// pc <= 32'h1c000000;
pc <= 32'h1bfffffc; // 由于使用nextpc作为取指地址,因此pc应该是nextpc的前一个地址
cycle_cnt <= 3'd4;
IDreg <= 32'h0;
EXEreg <= 32'h0;
MEMreg <= 32'h0;
WBreg <= 32'h0;
end else begin
if (cycle_cnt == 3'b100) begin
cycle_cnt <= 3'b0;
end else begin
cycle_cnt <= cycle_cnt + 3'b1;
end
if (IF) IDreg <= inst_sram_rdata;
if (ID) MEMreg <= alu_result;
// if (EXE) begin //EXE阶段需要给RAM发送读写命令和地址,因此要在EXE阶段前准备好地址,不能在EXE阶段后再准备地址,否则地址会冲突(在EXE阶段末地址才改变,恰好是RAM的读写时钟上升沿)
// MEMreg <= EXEreg;
// end
if (MEM) begin
if (res_from_mem) WBreg <= data_sram_rdata;
else WBreg <= alu_result;
end
if (WB) begin
pc <= nextpc;
end
end
end
assign imm = src2_is_4 ? 32'h4 :
need_si20 ? {i20[19:0], 12'b0}:
need_ui5 ? rk[4:0] :
/*need_si12*/{{20{i12[11]}}, i12[11:0]} ;
assign br_offs = need_si26 ? {{4{i26[25]}}, i26[25:0], 2'b0} : {{14{i16[15]}}, i16[15:0], 2'b0};
assign jirl_offs = {{14{i16[15]}}, i16[15:0], 2'b0};
assign src_reg_is_rd = inst_beq | inst_bne | inst_st_w;
assign src1_is_pc = inst_jirl | inst_bl;
assign src2_is_imm = inst_slli_w |
inst_srli_w |
inst_srai_w |
inst_addi_w |
inst_ld_w |
inst_st_w |
inst_lu12i_w|
inst_jirl |
inst_bl ;
assign res_from_mem = inst_ld_w;
assign dst_is_r1 = inst_bl;
assign gr_we = (~inst_st_w & ~inst_beq & ~inst_bne & ~inst_b) & WB;
assign mem_we = (inst_st_w) & EXE; //在EXE阶段发写使能,MEM阶段写数据
assign dest = dst_is_r1 ? 5'd1 : rd;
assign rf_raddr1 = rj;
assign rf_raddr2 = src_reg_is_rd ? rd : rk;
regfile u_regfile (
.clk (clk),
.raddr1(rf_raddr1),
.rdata1(rf_rdata1),
.raddr2(rf_raddr2),
.rdata2(rf_rdata2),
.we (rf_we),
.waddr (rf_waddr),
.wdata (rf_wdata)
);
assign rj_value = rf_rdata1;
assign rkd_value = rf_rdata2;
assign rj_eq_rd = (rj_value == rkd_value);
assign br_taken = ( inst_beq && rj_eq_rd
|| inst_bne && !rj_eq_rd
|| inst_jirl
|| inst_bl
|| inst_b
) && valid;
assign br_target = (inst_beq || inst_bne || inst_bl || inst_b) ? (pc + br_offs) :
/*inst_jirl*/ (rj_value + jirl_offs);
assign alu_src1 = src1_is_pc ? pc[31:0] : rj_value;
assign alu_src2 = src2_is_imm ? imm : rkd_value;
alu u_alu (
.alu_op (alu_op),
.alu_src1 (alu_src1),
.alu_src2 (alu_src2),
.alu_result(alu_result)
);
assign data_sram_en = (res_from_mem || mem_we) && EXE;
assign data_sram_we = {4{mem_we}};
assign data_sram_addr = MEMreg;
assign data_sram_wdata = rkd_value;
assign mem_result = WBreg;
assign final_result = res_from_mem ? mem_result : alu_result;
assign rf_we = gr_we;
assign rf_waddr = dest;
assign rf_wdata = final_result;
// debug info generate
assign debug_wb_pc = pc;
assign debug_wb_rf_we = {4{rf_we}};
assign debug_wb_rf_wnum = dest;
assign debug_wb_rf_wdata = final_result;
endmodule