OpenCores
URL https://opencores.org/ocsvn/aor3000/aor3000/trunk

Subversion Repositories aor3000

[/] [aor3000/] [trunk/] [rtl/] [block/] [block_cp0.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * This file is subject to the terms and conditions of the BSD License. See
3
 * the file "LICENSE" in the main directory of this archive for more details.
4
 *
5
 * Copyright (C) 2014 Aleksander Osman
6
 */
7
 
8
`include "defines.v"
9
 
10
module block_cp0(
11
    input               clk,
12
    input               rst_n,
13
 
14
    //
15
    output reg          config_switch_caches,
16
    output reg          config_isolate_cache,
17
    output              config_coproc0_usable,
18
    output              config_coproc1_usable,
19
    output              config_kernel_mode,
20
 
21
    //
22
    input               exe_cmd_mtc0,
23
    input       [31:0]  exe_instr,
24
    input       [31:0]  exe_b,
25
 
26
    input               exe_cmd_rfe,
27
    input               exe_cmd_tlbr,
28
    input               exe_cmd_tlbwi,
29
    input               exe_cmd_tlbwr,
30
 
31
    //
32
    output      [31:0]  coproc0_output,
33
 
34
    //
35
    output      [5:0]   tlbw_index,
36
    output      [49:0]  tlbw_value,
37
 
38
    //
39
    output reg  [5:0]   tlbr_index,
40
 
41
    input               tlb_ram_read_result_ready,
42
    input       [49:0]  tlb_ram_read_result,
43
 
44
    //
45
    input               tlbp_update,
46
    input               tlbp_hit,
47
    input       [5:0]   tlbp_index,
48
 
49
    //
50
    output              micro_flush_do,
51
    output reg  [5:0]   entryhi_asid,
52
 
53
    //
54
    input               sr_cm_set,
55
    input               sr_cm_clear,
56
 
57
    //
58
    input       [5:0]   interrupt_vector,
59
 
60
    //
61
    output              exception_start,
62
    output      [31:0]  exception_start_pc,
63
 
64
    //
65
    input               mem_stalled,
66
    input       [6:0]   mem_cmd,
67
    input       [31:0]  mem_instr,
68
    input       [31:0]  mem_pc_plus4,
69
    input       [1:0]   mem_branched,
70
    input       [31:0]  mem_branch_address,
71
    input       [31:0]  mem_badvpn
72
); /* verilator public_module */
73
 
74
//------------------------------------------------------------------------------
75
 
76
reg [5:0]  sr_ku_ie;            //kernel/user and interrupt enable
77
reg        sr_bev;              //boot exception vector
78
reg        sr_cm;               //last d-cache load hit; used in d-cache isolated
79
reg [7:0]  sr_im;               //interrupt mask
80
reg [3:0]  sr_coproc_usable;    //coprocessor usable
81
reg        sr_reverse_endian;
82
reg        sr_tlb_shutdown;
83
reg        sr_parity_error;
84
reg        sr_parity_zero;
85
 
86
always @(posedge clk or negedge rst_n) begin
87
    if(rst_n == 1'b0)                                   sr_ku_ie <= 6'b0;
88
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12)  sr_ku_ie <= exe_b[5:0];
89
    else if(exe_cmd_rfe)                                sr_ku_ie <= { sr_ku_ie[5:4], sr_ku_ie[5:2] };
90
    else if(exception_start)                            sr_ku_ie <= { sr_ku_ie[3:0], 2'b00 };
91
end
92
 
93
always @(posedge clk or negedge rst_n) begin
94
    if(rst_n == 1'b0)                                   sr_cm <= `FALSE;
95
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12)  sr_cm <= exe_b[19];
96
    else if(sr_cm_clear)                                sr_cm <= `FALSE; //first sr_cm_clear important
97
    else if(sr_cm_set)                                  sr_cm <= `TRUE;
98
end
99
 
100
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_coproc_usable      <= 4'b0;   else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_coproc_usable     <= exe_b[31:28]; end
101
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_reverse_endian     <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_reverse_endian    <= exe_b[25];    end
102
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_bev                <= `TRUE;  else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_bev               <= exe_b[22];    end
103
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_tlb_shutdown       <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_tlb_shutdown      <= exe_b[21];    end
104
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_parity_error       <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_parity_error      <= exe_b[20];    end
105
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_parity_zero        <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_parity_zero       <= exe_b[18];    end
106
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) config_switch_caches  <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) config_switch_caches <= exe_b[17];    end
107
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) config_isolate_cache  <= `FALSE; else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) config_isolate_cache <= exe_b[16];    end
108
always @(posedge clk or negedge rst_n) begin if(rst_n == 1'b0) sr_im                 <= 8'h00;  else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd12) sr_im                <= exe_b[15:8];  end
109
 
110
assign config_kernel_mode    = ~(sr_ku_ie[1]);
111
assign config_coproc0_usable = sr_coproc_usable[0];
112
assign config_coproc1_usable = sr_coproc_usable[1];
113
 
114
//------------------------------------------------------------------------------
115
 
116
reg        cause_bd;            //branch delay
117
reg [1:0]  cause_ce;            //coproc error
118
reg [1:0]  cause_ip_writable;   //interrupt pending ([1:0] writable)
119
reg [4:0]  cause_exccode;       //exccode
120
reg [31:0] epc;
121
reg [31:0] badvaddr;
122
 
123
reg [5:0] interrupt_vector_reg;
124
always @(posedge clk or negedge rst_n) begin
125
    if(rst_n == 1'b0)   interrupt_vector_reg <= 6'd0;
126
    else                interrupt_vector_reg <= interrupt_vector;
127
end
128
 
129
wire [7:0] cause_ip = { interrupt_vector_reg, cause_ip_writable };
130
 
131
always @(posedge clk or negedge rst_n) begin
132
    if(rst_n == 1'b0)                                   cause_bd <= `FALSE;
133
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13)  cause_bd <= exe_b[31];
134
    else if(exception_start)                            cause_bd <= (exception_not_interrupt && mem_branched == 2'd2) || (exception_interrupt && mem_branched == 2'd1);
135
end
136
 
137
always @(posedge clk or negedge rst_n) begin
138
    if(rst_n == 1'b0)                                   cause_ce <= 2'd0;
139
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13)  cause_ce <= exe_b[29:28];
140
    else if(exception_coprocessor_error)                cause_ce <= mem_instr[27:26];
141
    else if(exception_start)                            cause_ce <= 2'd0;
142
end
143
 
144
always @(posedge clk or negedge rst_n) begin
145
    if(rst_n == 1'b0)                                   cause_ip_writable <= 2'd0;
146
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13)  cause_ip_writable <= exe_b[9:8];
147
    else if(exception_start)                            cause_ip_writable <= 2'd0;
148
end
149
 
150
always @(posedge clk or negedge rst_n) begin
151
    if(rst_n == 1'b0)                                   cause_exccode <= 5'd31;
152
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd13)  cause_exccode <= exe_b[6:2];
153
    else if(exception_start)                            cause_exccode <= exception_cause;
154
end
155
 
156
always @(posedge clk or negedge rst_n) begin
157
    if(rst_n == 1'b0)                                   epc <= 32'd0;
158
    else if(exception_start)                            epc <= exception_epc;
159
end
160
 
161
always @(posedge clk or negedge rst_n) begin
162
    if(rst_n == 1'b0)                                   badvaddr <= 32'd0;
163
    else if(exception_badvaddr_update)                  badvaddr <= mem_badvpn;
164
end
165
 
166
//------------------------------------------------------------------------------
167
 
168
reg        tlb_probe;
169
reg [5:0]  tlb_random;
170
reg [10:0] tlb_ptebase;
171
reg [18:0] tlb_badvpn;
172
 
173
reg [19:0]  entryhi_vpn;
174
reg [19:0]  entrylo_pfn;
175
reg         entrylo_n;
176
reg         entrylo_d;
177
reg         entrylo_v;
178
reg         entrylo_g;
179
 
180
always @(posedge clk or negedge rst_n) begin
181
    if(rst_n == 1'b0)                                   entryhi_vpn <= 20'd0;
182
    else if(exception_badvaddr_update)                  entryhi_vpn <= mem_badvpn[31:12];
183
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd10)  entryhi_vpn <= exe_b[31:12];
184
    else if(tlb_ram_read_result_ready)                  entryhi_vpn <= tlb_ram_read_result[19:0];
185
end
186
always @(posedge clk or negedge rst_n) begin
187
    if(rst_n == 1'b0)                                   entryhi_asid <= 6'd0;
188
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd10)  entryhi_asid <= exe_b[11:6];
189
    else if(tlb_ram_read_result_ready)                  entryhi_asid <= tlb_ram_read_result[45:40];
190
end
191
always @(posedge clk or negedge rst_n) begin
192
    if(rst_n == 1'b0)                                   entrylo_pfn <= 20'd0;
193
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2)   entrylo_pfn <= exe_b[31:12];
194
    else if(tlb_ram_read_result_ready)                  entrylo_pfn <= tlb_ram_read_result[39:20];
195
end
196
always @(posedge clk or negedge rst_n) begin
197
    if(rst_n == 1'b0)                                   entrylo_n <= `FALSE;
198
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2)   entrylo_n <= exe_b[11];
199
    else if(tlb_ram_read_result_ready)                  entrylo_n <= tlb_ram_read_result[46];
200
end
201
always @(posedge clk or negedge rst_n) begin
202
    if(rst_n == 1'b0)                                   entrylo_d <= `FALSE;
203
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2)   entrylo_d <= exe_b[10];
204
    else if(tlb_ram_read_result_ready)                  entrylo_d <= tlb_ram_read_result[47];
205
end
206
always @(posedge clk or negedge rst_n) begin
207
    if(rst_n == 1'b0)                                   entrylo_v <= `FALSE;
208
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2)   entrylo_v <= exe_b[9];
209
    else if(tlb_ram_read_result_ready)                  entrylo_v <= tlb_ram_read_result[48];
210
end
211
always @(posedge clk or negedge rst_n) begin
212
    if(rst_n == 1'b0)                                   entrylo_g <= `FALSE;
213
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd2)   entrylo_g <= exe_b[8];
214
    else if(tlb_ram_read_result_ready)                  entrylo_g <= tlb_ram_read_result[49];
215
end
216
 
217
always @(posedge clk or negedge rst_n) begin
218
    if(rst_n == 1'b0)                                   tlb_ptebase <= 11'd0;
219
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd4)   tlb_ptebase <= exe_b[31:21];
220
end
221
 
222
always @(posedge clk or negedge rst_n) begin
223
    if(rst_n == 1'b0)                                   tlb_badvpn <= 19'd0;
224
    else if(exception_badvaddr_update)                  tlb_badvpn <= mem_badvpn[30:12];
225
end
226
 
227
always @(posedge clk or negedge rst_n) begin
228
    if(rst_n == 1'b0)                                   tlbr_index <= 6'd0;
229
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd0)   tlbr_index <= exe_b[13:8];
230
    else if(tlbp_update)                                tlbr_index <= (tlbp_hit)? tlbp_index : 6'd0;
231
end
232
always @(posedge clk or negedge rst_n) begin
233
    if(rst_n == 1'b0)                                   tlb_probe <= `FALSE;
234
    else if(exe_cmd_mtc0 && exe_instr[15:11] == 5'd0)   tlb_probe <= exe_b[31];
235
    else if(tlbp_update)                                tlb_probe <= ~(tlbp_hit);
236
end
237
 
238
always @(posedge clk or negedge rst_n) begin
239
    if(rst_n == 1'b0)                                   tlb_random <= 6'd63;
240
    else if(exe_cmd_tlbwr)                              tlb_random <= (tlb_random <= 6'd08)? 6'd63 : tlb_random - 6'd1;
241
end
242
 
243
reg [5:0] entryhi_asid_last;
244
always @(posedge clk or negedge rst_n) begin
245
    if(rst_n == 1'b0)   entryhi_asid_last <= 6'd0;
246
    else                entryhi_asid_last <= entryhi_asid;
247
end
248
 
249
assign micro_flush_do = (entryhi_asid_last != entryhi_asid) || exe_cmd_tlbwi || exe_cmd_tlbwr;
250
 
251
assign tlbw_index = (exe_cmd_tlbwi)? tlbr_index : tlb_random;
252
assign tlbw_value = (tlb_ram_read_result_ready)?
253
    { tlb_ram_read_result[49], tlb_ram_read_result[48], tlb_ram_read_result[47], tlb_ram_read_result[46], tlb_ram_read_result[45:40], tlb_ram_read_result[39:20], tlb_ram_read_result[19:0] } :
254
    { entrylo_g, entrylo_v, entrylo_d, entrylo_n, entryhi_asid, entrylo_pfn, entryhi_vpn };
255
 
256
//------------------------------------------------------------------------------
257
 
258
assign coproc0_output =
259
    (tlb_ram_read_result_ready && exe_instr[15:11] == 5'd2)?
260
                                    { tlb_ram_read_result[39:20], tlb_ram_read_result[46], tlb_ram_read_result[47], tlb_ram_read_result[48], tlb_ram_read_result[49], 8'd0 } :  //entry low just after tlbr
261
    (tlb_ram_read_result_ready && exe_instr[15:11] == 5'd10)?
262
                                    { tlb_ram_read_result[19:0], tlb_ram_read_result[45:40], 6'd0 } :                                                                           //entry high just after tlbr
263
 
264
    (exe_instr[15:11] == 5'd0)?     { tlb_probe, 17'd0, tlbr_index, 8'd0 } :                                    //tlb index
265
    (exe_instr[15:11] == 5'd1)?     { 18'd0, tlb_random, 8'd0 } :                                               //tlb random
266
    (exe_instr[15:11] == 5'd2)?     { entrylo_pfn, entrylo_n, entrylo_d, entrylo_v, entrylo_g, 8'd0 } :         //entry low
267
    (exe_instr[15:11] == 5'd4)?     { tlb_ptebase, tlb_badvpn, 2'b0 } :                                         //tlb context
268
    (exe_instr[15:11] == 5'd8)?     badvaddr :                                                                  //bad vaddr
269
    (exe_instr[15:11] == 5'd10)?    { entryhi_vpn, entryhi_asid, 6'd0 } :                                       //entry high
270
    (exe_instr[15:11] == 5'd12)?    { sr_coproc_usable, 2'b0, sr_reverse_endian, 2'b0, sr_bev, sr_tlb_shutdown, sr_parity_error, sr_cm, sr_parity_zero,
271
                                      config_switch_caches, config_isolate_cache, sr_im, 2'b0, sr_ku_ie } :     //SR
272
    (exe_instr[15:11] == 5'd13)?    { cause_bd, 1'b0, cause_ce, 12'd0, cause_ip, 1'b0, cause_exccode, 2'b0 } :  //cause
273
    (exe_instr[15:11] == 5'd14)?    epc :                                                                       //epc
274
    (exe_instr[15:11] == 5'd15)?    { 16'd0, 8'h02, 8'h30 } :                                                   //PRId
275
                                    32'd0;
276
 
277
//------------------------------------------------------------------------------
278
 
279
//input       [6:0]   mem_cmd,
280
//input               mem_branched,
281
//input       [31:0]  mem_badvpn
282
 
283
reg mem_stalled_last;
284
always @(posedge clk or negedge rst_n) begin
285
    if(rst_n == 1'b0)   mem_stalled_last <= `FALSE;
286
    else                mem_stalled_last <= mem_stalled;
287
end
288
 
289
wire exception_interrupt         = sr_ku_ie[0] && (cause_ip & sr_im) != 8'd0 && (mem_cmd != `CMD_null || (mem_stalled_last && ~(mem_stalled))) && ~(exception_not_interrupt) && ~(mem_stalled);
290
wire exception_badvaddr_update   = mem_cmd == `CMD_exc_load_tlb || mem_cmd == `CMD_exc_store_tlb || mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss || mem_cmd == `CMD_exc_tlb_modif;
291
wire exception_coprocessor_error = mem_cmd == `CMD_exc_coproc_unusable;
292
 
293
wire exception_not_interrupt = exception_coprocessor_error || exception_badvaddr_update || mem_cmd == `CMD_exc_int_overflow || mem_cmd == `CMD_break || mem_cmd == `CMD_syscall ||
294
                               mem_cmd == `CMD_exc_load_addr_err || mem_cmd == `CMD_exc_store_addr_err || mem_cmd == `CMD_exc_reserved_instr;
295
 
296
assign exception_start = exception_not_interrupt || exception_interrupt;
297
 
298
wire [31:0] exception_epc =
299
    (exception_interrupt && mem_branched == 2'd2)?  mem_branch_address :
300
    (exception_interrupt && mem_branched == 2'd0)?  mem_pc_plus4 :
301
    (mem_branched == 2'd2)?                         mem_pc_plus4 - 32'd8 :
302
                                                    mem_pc_plus4 - 32'd4;
303
 
304
wire [4:0] exception_cause =
305
    (mem_cmd == `CMD_exc_tlb_modif)?                                        5'd1 :
306
    (mem_cmd == `CMD_exc_load_tlb  || mem_cmd == `CMD_exc_tlb_load_miss)?   5'd2 :
307
    (mem_cmd == `CMD_exc_store_tlb || mem_cmd == `CMD_exc_tlb_store_miss)?  5'd3 :
308
    (mem_cmd == `CMD_exc_load_addr_err)?                                    5'd4 :
309
    (mem_cmd == `CMD_exc_store_addr_err)?                                   5'd5 :
310
    (mem_cmd == `CMD_syscall)?                                              5'd8 :
311
    (mem_cmd == `CMD_break)?                                                5'd9 :
312
    (mem_cmd == `CMD_exc_reserved_instr)?                                   5'd10 :
313
    (mem_cmd == `CMD_exc_coproc_unusable)?                                  5'd11 :
314
    (mem_cmd == `CMD_exc_int_overflow)?                                     5'd12 :
315
                                                                            5'd0;  //interrupt
316
 
317
assign exception_start_pc =
318
    (sr_bev && (mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss))?  32'hBFC00100 :
319
    (mem_cmd == `CMD_exc_tlb_load_miss || mem_cmd == `CMD_exc_tlb_store_miss)?              32'h80000000 :
320
    (sr_bev)?                                                                               32'hBFC00180 :
321
                                                                                            32'h80000080;
322
 
323
//------------------------------------------------------------------------------
324
// synthesis translate_off
325
wire _unused_ok = &{ 1'b0, exe_instr[31:16], exe_instr[10:0], exe_cmd_tlbr, exe_cmd_tlbwr, mem_instr[31:28], mem_instr[25:0], 1'b0 };
326
// synthesis translate_on
327
//------------------------------------------------------------------------------
328
 
329
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.