-
Notifications
You must be signed in to change notification settings - Fork 0
/
WB_stage.v
228 lines (206 loc) · 6.27 KB
/
WB_stage.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
`include "mycpu.h"
module wb_stage(
input clk ,
input reset ,
// allowin
output ws_allowin ,
// from ms
input ms_to_ws_valid,
input [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus ,
// to rf: for write back and forward bus (to ds)
output [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus ,
output ws_mt_entryhi ,
// trace debug interface
output [31:0] debug_wb_pc ,
output [ 3:0] debug_wb_rf_wen ,
output [ 4:0] debug_wb_rf_wnum ,
output [31:0] debug_wb_rf_wdata,
output [31:0] cp0_epc,
output ws_eret,
output ws_ex ,
output has_int,
output ws_tlb_refill,
// TLB
output [19:0] entryhi_vpn,
input [ 5:0] tlbp_bus,
// search port asid
output [ 7:0] s0_asid,
output [ 7:0] s1_asid,
// write port
output we ,
output [ 3:0] w_index,
output [18:0] w_vpn2 ,
output [ 7:0] w_asid ,
output w_g ,
output [19:0] w_pfn0 ,
output [ 2:0] w_c0 ,
output w_d0 ,
output w_v0 ,
output [19:0] w_pfn1 ,
output [ 2:0] w_c1 ,
output w_d1 ,
output w_v1 ,
// read port
output [ 3:0] r_index,
input [18:0] r_vpn2 ,
input [ 7:0] r_asid ,
input r_g ,
input [19:0] r_pfn0 ,
input [ 2:0] r_c0 ,
input r_d0 ,
input r_v0 ,
input [19:0] r_pfn1 ,
input [ 2:0] r_c1 ,
input r_d1 ,
input r_v1 ,
output start_refetch
);
reg ws_valid;
wire ws_ready_go;
reg [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus_r;
// wire ws_gr_we;
wire [ 4:0] ws_dest;
wire [31:0] ws_final_result;
wire [31:0] ws_pc;
wire [3 :0] ws_rf_we;
wire [3 :0] rf_we;
// exception
wire [10:0] c0_bus;
// wire ws_eret; declare in output
wire ws_mtc0;
wire ws_mfc0;
wire [ 7:0] c0_raddr;
wire ws_bd;
wire ms_ex;
wire [ 4:0] ms_excode;
wire [31:0] ms_badvaddr;
wire [31:0] wb_badvaddr;
wire tlb_refill;
wire ws_tlbwi;
wire ws_tlbr;
assign {
tlb_refill , // 125:125
ws_tlbwi , // 124:124
ws_tlbr , // 123:123
ms_badvaddr , // 122:91
c0_bus , // 90:80
ws_bd , // 79:79
ms_ex , // 78:78
ms_excode , // 77:73
ws_rf_we , // 72:69
ws_dest , // 68:64
ws_final_result, // 63:32
ws_pc // 31:0
} = ms_to_ws_bus_r;
assign wb_badvaddr = ms_badvaddr;
assign {ws_eret, // 10:10
ws_mtc0, // 9:9
ws_mfc0, // 8:8
c0_raddr // 7:0
} = c0_bus & {11{ws_valid}};
wire [31:0] cp0_rdata;
wire eret_flush;
assign eret_flush = ws_valid && ws_eret;
assign ws_mt_entryhi = ws_mtc0 && (c0_raddr[7:3] == `CR_ENTRYHI) && ws_valid;
assign start_refetch = (ws_tlbwi || ws_tlbr) && ws_valid;
wire [4 :0] rf_waddr;
wire [31:0] rf_wdata;
assign ws_to_rf_bus = {rf_we , //40:37
rf_waddr, //36:32
rf_wdata //31:0
};
// exception
// wire ws_ex; declare in output
wire [ 4:0] ws_excode;
assign ws_ex = ws_valid && ms_ex;
assign ws_excode = {5{ws_ex}} & ms_excode;
assign ws_tlb_refill = ws_valid && tlb_refill;
assign ws_ready_go = 1'b1;
assign ws_allowin = !ws_valid || ws_ready_go;
always @(posedge clk) begin
if (reset) begin
ws_valid <= 1'b0;
end
else if (ws_ex || eret_flush) begin
ws_valid <= 1'b0;
end
else if (ws_allowin) begin
ws_valid <= ms_to_ws_valid;
end
if (ms_to_ws_valid && ws_allowin) begin
ms_to_ws_bus_r <= ms_to_ws_bus;
end
end
assign rf_we = {4{ws_valid & ~ws_ex}} & ws_rf_we;
assign rf_waddr = ws_dest;
assign rf_wdata = ws_mfc0 ? cp0_rdata : ws_final_result;
// debug info generate
assign debug_wb_pc = ws_pc;
assign debug_wb_rf_wen = rf_we;
assign debug_wb_rf_wnum = ws_dest;
assign debug_wb_rf_wdata = rf_wdata;
wire [31:0] c0_entryhi ;
wire [31:0] c0_entrylo0;
wire [31:0] c0_entrylo1;
wire [31:0] c0_index ;
wire es_tlbp ;
wire tlbp_found;
wire [ 3:0] tlbp_index;
assign entryhi_vpn = c0_entryhi[31:12];
assign {es_tlbp ,
tlbp_found,
tlbp_index
} = tlbp_bus;
assign s0_asid = c0_entryhi[7:0];
assign s1_asid = c0_entryhi[7:0];
assign we = ws_tlbwi && ws_valid;
assign w_index = c0_index[3:0];
assign w_vpn2 = c0_entryhi[31:13];
assign w_asid = c0_entryhi[7:0];
assign w_g = c0_entrylo0[0] && c0_entrylo1[0];
assign w_pfn0 = c0_entrylo0[25:6];
assign {w_c0, w_d0, w_v0} = c0_entrylo0[5:1];
assign w_pfn1 = c0_entrylo1[25:6];
assign {w_c1, w_d1, w_v1} = c0_entrylo1[5:1];
assign r_index = c0_index[3:0];
// int signals
wire [5:0] ext_int_in;
assign ext_int_in = 6'b0;
// cp0_regfile
cp0_regfile u_cp0_regfile(
.clk (clk ),
.reset (reset ),
.mtc0_we (ws_mtc0 && !ws_ex),
.c0_raddr (c0_raddr ),
.c0_wdata (ws_final_result ),
.wb_bd (ws_bd ),
.wb_ex (ws_ex ),
.wb_excode (ws_excode ),
.eret_flush (eret_flush ),
.wb_badvaddr(wb_badvaddr ),
.wb_pc (ws_pc ),
.rdata (cp0_rdata ),
.c0_epc (cp0_epc ),
.ext_int_in (ext_int_in ),
.has_int (has_int ),
.c0_entryhi (c0_entryhi ),
.c0_entrylo0(c0_entrylo0 ),
.c0_entrylo1(c0_entrylo1 ),
.c0_index (c0_index ),
.tlbp (es_tlbp ),
.tlbp_found (tlbp_found ),
.tlbp_index (tlbp_index ),
.tlbr (ws_tlbr ),
.r_vpn2 (r_vpn2 ),
.r_asid (r_asid ),
.r_g (r_g ),
.r_pfn0 (r_pfn0 ),
.r_c0 (r_c0 ),
.r_d0 (r_d0 ),
.r_v0 (r_v0 ),
.r_pfn1 (r_pfn1 ),
.r_c1 (r_c1 ),
.r_d1 (r_d1 ),
.r_v1 (r_v1 )
);
endmodule