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

Subversion Repositories claw

[/] [claw/] [trunk/] [or1200_cpu/] [or1200_genpc.v] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 conte
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  OR1200's generate PC                                        ////
4
////                                                              ////
5
////  This file is part of the OpenRISC 1200 project              ////
6
////  http://www.opencores.org/cores/or1k/                        ////
7
////                                                              ////
8
////  Description                                                 ////
9
////  PC, interface to IC.                                        ////
10
////                                                              ////
11
////  To Do:                                                      ////
12
////   - make it smaller and faster                               ////
13
////                                                              ////
14
////  Author(s):                                                  ////
15
////      - Damjan Lampret, lampret@opencores.org                 ////
16
////                                                              ////
17
////  Modified by:                                                ////
18
////      - Balaji V. Iyer, bviyer@ncsu.edu                       ////
19
////  Advisor:                                                    ////
20
////      - Dr. Tom Conte                                         ////
21
////                                                              ////
22
//////////////////////////////////////////////////////////////////////
23
////                                                              ////
24
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
25
////                                                              ////
26
//// This source file may be used and distributed without         ////
27
//// restriction provided that this copyright statement is not    ////
28
//// removed from the file and that any derivative work contains  ////
29
//// the original copyright notice and the associated disclaimer. ////
30
////                                                              ////
31
//// This source file is free software; you can redistribute it   ////
32
//// and/or modify it under the terms of the GNU Lesser General   ////
33
//// Public License as published by the Free Software Foundation; ////
34
//// either version 2.1 of the License, or (at your option) any   ////
35
//// later version.                                               ////
36
////                                                              ////
37
//// This source is distributed in the hope that it will be       ////
38
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
39
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
40
//// PURPOSE.  See the GNU Lesser General Public License for more ////
41
//// details.                                                     ////
42
////                                                              ////
43
//// You should have received a copy of the GNU Lesser General    ////
44
//// Public License along with this source; if not, download it   ////
45
//// from http://www.opencores.org/lgpl.shtml                     ////
46
////                                                              ////
47
//////////////////////////////////////////////////////////////////////
48
//
49
// CVS Revision History
50
//
51
// $Log: not supported by cvs2svn $
52
// Revision 1.9  2004/04/05 08:29:57  lampret
53
// Merged branch_qmem into main tree.
54
//
55
// Revision 1.7.4.3  2003/12/17 13:43:38  simons
56
// Exception prefix configuration changed.
57
//
58
// Revision 1.7.4.2  2003/12/04 23:44:31  lampret
59
// Static exception prefix.
60
//
61
// Revision 1.7.4.1  2003/07/08 15:36:37  lampret
62
// Added embedded memory QMEM.
63
//
64
// Revision 1.7  2003/04/20 22:23:57  lampret
65
// No functional change. Only added customization for exception vectors.
66
//
67
// Revision 1.6  2002/03/29 15:16:55  lampret
68
// Some of the warnings fixed.
69
//
70
// Revision 1.5  2002/02/11 04:33:17  lampret
71
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
72
//
73
// Revision 1.4  2002/01/28 01:16:00  lampret
74
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
75
//
76
// Revision 1.3  2002/01/18 07:56:00  lampret
77
// No more low/high priority interrupts (PICPR removed). Added tick timer exception. Added exception prefix (SR[EPH]). Fixed single-step bug whenreading NPC.
78
//
79
// Revision 1.2  2002/01/14 06:18:22  lampret
80
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
81
//
82
// Revision 1.1  2002/01/03 08:16:15  lampret
83
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
84
//
85
// Revision 1.10  2001/11/20 18:46:15  simons
86
// Break point bug fixed
87
//
88
// Revision 1.9  2001/11/18 09:58:28  lampret
89
// Fixed some l.trap typos.
90
//
91
// Revision 1.8  2001/11/18 08:36:28  lampret
92
// For GDB changed single stepping and disabled trap exception.
93
//
94
// Revision 1.7  2001/10/21 17:57:16  lampret
95
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
96
//
97
// Revision 1.6  2001/10/14 13:12:09  lampret
98
// MP3 version.
99
//
100
// Revision 1.1.1.1  2001/10/06 10:18:36  igorm
101
// no message
102
//
103
// Revision 1.1  2001/08/09 13:39:33  lampret
104
// Major clean-up.
105
//
106
//
107
 
108
// synopsys translate_off
109
 `include "timescale.v"
110
// synopsys translate_on
111
 `include "or1200_defines.v"
112
 
113
module or1200_genpc(
114
        // Clock and reset
115
        clk, rst,
116
 
117
        // External i/f to IC
118
        icpu_adr_o, icpu_cycstb_o, icpu_sel_o, icpu_tag_o,
119
        icpu_rty_i, icpu_adr_i,
120
 
121
        // Internal i/f
122
        branch_op, except_type, except_prefix,
123
        branch_addrofs, lr_restor, flag, taken, except_start,
124
        binsn_addr, epcr, spr_dat_i, spr_pc_we, genpc_refetch,
125
        genpc_freeze, genpc_stop_prefetch, no_more_dslot,
126
        thread_out, branch_thread,wb_thread, except_thread
127
);
128
 
129
//
130
// I/O
131
//
132
 
133
//
134
// Clock and reset
135
//
136
input                           clk;
137
input                           rst;
138
 
139
//
140
// External i/f to IC
141
//
142
output  [31:0]                   icpu_adr_o;
143
output                          icpu_cycstb_o;
144
output  [3:0]                    icpu_sel_o;
145
output  [3:0]                    icpu_tag_o;
146
input                           icpu_rty_i;
147
input   [31:0]                   icpu_adr_i;
148
 
149
//
150
// Internal i/f
151
//
152
input   [`OR1200_BRANCHOP_WIDTH-1:0]     branch_op;
153
input   [`OR1200_EXCEPT_WIDTH-1:0]       except_type;
154
input                                   except_prefix;
155
input   [31:2]                  branch_addrofs;
156
input   [31:0]                   lr_restor;
157
input                           flag;
158
output                          taken;
159
input                           except_start;
160
input   [31:2]                  binsn_addr;
161
input   [31:0]                   epcr;
162
input   [31:0]                   spr_dat_i;
163
input                           spr_pc_we;
164
input                           genpc_refetch;
165
input                           genpc_stop_prefetch;
166
input                           genpc_freeze;
167
input                           no_more_dslot;
168
input [2:0]                      branch_thread;  // bviyer
169
input [2:0]                      except_thread;  // bviyer
170
input [2:0]                      wb_thread;      // bviyer
171
output [2:0]                     thread_out;     // bviyer
172
//
173
// Internal wires and regs
174
//
175
reg     [31:2]                  pcreg;
176
reg     [31:0]                   pc;
177
reg                             taken;  /* Set to in case of jump or taken branch */
178
reg                             genpc_refetch_r;
179
 reg [31:0]                      temp_icpu_adr_o;
180
//
181
// bviyer: Thread registers
182
//
183
 
184
// reg [2:0] thread_out;
185
reg [2:0] temp_thread_out;
186
reg [2:0] thread_out;
187
reg  [2:0] current_thread;
188
reg [2:0] some_thread;
189
reg [2:0] next_thread;
190
 
191
// bviyer: different registers
192
reg     [31:2]                  pcreg_1;
193
reg     [31:2]                  pcreg_2;
194
reg     [31:2]                  pcreg_3;
195
reg     [31:2]                  pcreg_4;
196
reg     [31:2]                  pcreg_5;
197
reg     [31:2]                  pcreg_6;
198
reg     [31:2]                  pcreg_7;
199
reg     [31:2]                  pcreg_8;
200
 
201
//
202
// Address of insn to be fecthed
203
//
204
// assign icpu_adr_o = !no_more_dslot & !except_start & !spr_pc_we & (icpu_rty_i | genpc_refetch) ? icpu_adr_i : pc;
205
// assign icpu_adr_o = !except_start & !spr_pc_we & (icpu_rty_i | genpc_refetch) ? icpu_adr_i : pc;
206
 
207
//
208
// Control access to IC subsystem
209
//
210
// assign icpu_cycstb_o = !genpc_freeze & !no_more_dslot;
211
assign icpu_cycstb_o = !genpc_freeze; // works, except remaining raised cycstb during long load/store
212
//assign icpu_cycstb_o = !(genpc_freeze | genpc_refetch & genpc_refetch_r);
213
//assign icpu_cycstb_o = !(genpc_freeze | genpc_stop_prefetch);
214
assign icpu_sel_o = 4'b1111;
215
assign icpu_tag_o = `OR1200_ITAG_NI;
216
assign icpu_adr_o = temp_icpu_adr_o;
217
// assign thread_out =   temp_thread_out; 
218
//
219
// genpc_freeze_r
220
//
221
 
222
 always @(posedge clk)
223
 begin
224
temp_icpu_adr_o = !no_more_dslot & !except_start & !spr_pc_we & (icpu_rty_i | genpc_refetch) ? icpu_adr_i : pc;
225
thread_out =   temp_thread_out;
226
// temp_thread_out = current_thread;
227
end
228
 
229
always @(posedge clk or posedge rst)
230
        if (rst)
231
                genpc_refetch_r <=  1'b0;
232
        else if (genpc_refetch)
233
                genpc_refetch_r <=  1'b1;
234
        else
235
                genpc_refetch_r <=  1'b0;
236
 
237
//
238
// Async calculation of new PC value. This value is used for addressing the IC.
239
// bviyer: modified for the multithreaded architecture
240
 always @(rst or branch_thread or except_thread or wb_thread or  current_thread or pcreg_1 or pcreg_2 or pcreg_3 or pcreg_4 or pcreg_5 or pcreg_6 or pcreg_7 or pcreg_8 or  branch_addrofs or binsn_addr or flag or branch_op or except_type or except_start or lr_restor or epcr or spr_pc_we or spr_dat_i or except_prefix) begin
241
 
242
// always @(posedge clk or posedge rst)
243
// begin
244
        if (rst) begin
245
           next_thread <= 3'd0;
246
           temp_thread_out <= 3'd0;
247
           pc <= {pcreg_1,2'b0}; end
248
        else
249
        begin
250
        casex ({spr_pc_we, except_start, branch_op})    // synopsys parallel_case
251
                {2'b00, `OR1200_BRANCHOP_NOP}: begin
252
                        taken <= 1'b0;
253
                        case (current_thread)   // synopsys parallel_case
254
                        3'd0:
255
                                pc <= {pcreg_1 + 2'd2, 2'b0};
256
                        3'd1:
257
                                pc <= {pcreg_2 + 2'd2, 2'b0};
258
                        3'd2:
259
                                pc <= {pcreg_3 + 2'd2, 2'b0};
260
                        3'd3:
261
                                pc <= {pcreg_4 + 2'd2, 2'b0};
262
                        3'd4:
263
                                pc <= {pcreg_5 + 2'd2, 2'b0};
264
                        3'd5:
265
                                pc <= {pcreg_6 + 2'd2, 2'b0};
266
                        3'd6:
267
                                pc <= {pcreg_7 + 2'd2, 2'b0};
268
                        3'd7:
269
                                pc <= {pcreg_8 + 2'd2, 2'b0};
270
                        endcase
271
                        temp_thread_out <= current_thread; // next_thread; // {temp_thread_out + 3'd1};
272
                        next_thread[0] <= !current_thread[0];
273
                        next_thread[1] <= current_thread[1] ^
274
                                          current_thread[0];
275
                        next_thread[2] <= current_thread[2] ^
276
                                        (current_thread[0] & current_thread[1]);
277
                        temp_thread_out <= current_thread; // next_thread; // {temp_thread_out + 3'd1};
278
/*
279
                        temp_thread_out[0] <= !temp_thread_out[0];
280
                        temp_thread_out[1] <= temp_thread_out[1] ^ temp_thread_out[0];
281
                        temp_thread_out[2] <= temp_thread_out[2] ^ (temp_thread_out[1] & temp_thread_out[0]);
282
*/
283
                end
284
                {2'b00, `OR1200_BRANCHOP_J}: begin
285
`ifdef OR1200_VERBOSE
286
// synopsys translate_off
287
                        $display("%t: BRANCHOP_J: pc <= branch_addrofs %h", $time, branch_addrofs);
288
// synopsys translate_on
289
`endif
290
                        pc <= {branch_addrofs, 2'b0};
291
                        taken <= 1'b1;
292
                        next_thread <= branch_thread;
293
                        temp_thread_out <= branch_thread; // current_thread;
294
                end
295
                {2'b00, `OR1200_BRANCHOP_JR}: begin
296
`ifdef OR1200_VERBOSE
297
// synopsys translate_off
298
                        $display("%t: BRANCHOP_JR: pc <= lr_restor %h", $time, lr_restor);
299
// synopsys translate_on
300
`endif
301
                        pc <= lr_restor;
302
                        taken <= 1'b1;
303
                        next_thread <= branch_thread;
304
                        temp_thread_out <= branch_thread; //  current_thread;
305
                end
306
                {2'b00, `OR1200_BRANCHOP_BAL}: begin
307
`ifdef OR1200_VERBOSE
308
// synopsys translate_off
309
                        $display("%t: BRANCHOP_BAL: pc %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
310
// synopsys translate_on
311
`endif
312
                        pc <= {binsn_addr + branch_addrofs, 2'b0};
313
                        taken <= 1'b1;
314
                        next_thread <= wb_thread;
315
                        temp_thread_out <= wb_thread; // current_thread;
316
                end
317
                {2'b00, `OR1200_BRANCHOP_BF}:
318
                        if (flag) begin
319
`ifdef OR1200_VERBOSE
320
// synopsys translate_off
321
                                $display("%t: BRANCHOP_BF: pc %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
322
// synopsys translate_on
323
`endif
324
                                pc <= {binsn_addr + branch_addrofs, 2'b0};
325
                                taken <= 1'b1;
326
                                next_thread <= wb_thread;
327
                                temp_thread_out <= wb_thread;
328
                        end
329
                        else begin
330
`ifdef OR1200_VERBOSE
331
// synopsys translate_off
332
                        $display("%t: BRANCHOP_BF: not taken", $time);
333
// synopsys translate_on
334
`endif
335
                                taken <= 1'b0;
336
                        case (current_thread) // synopsys parallel_case
337
                        3'd0:
338
                                pc <= {pcreg_1 + 2'd2, 2'b0};
339
                        3'd1:
340
                                pc <= {pcreg_2 + 2'd2, 2'b0};
341
                        3'd2:
342
                                pc <= {pcreg_3 + 2'd2, 2'b0};
343
                        3'd3:
344
                                pc <= {pcreg_4 + 2'd2, 2'b0};
345
                        3'd4:
346
                                pc <= {pcreg_5 + 2'd2, 2'b0};
347
                        3'd5:
348
                                pc <= {pcreg_6 + 2'd2, 2'b0};
349
                        3'd6:
350
                                pc <= {pcreg_7 + 2'd2, 2'b0};
351
                        3'd7:
352
                                pc <= {pcreg_8 + 2'd2, 2'b0};
353
                        endcase
354
                        next_thread  <= {current_thread+3'd1};
355
                        temp_thread_out <= current_thread;
356
                        end
357
                {2'b00, `OR1200_BRANCHOP_BNF}:
358
                        if (flag) begin
359
                        case (current_thread)   // synopsys parallel_case
360
                        3'd0:
361
                                pc <= {pcreg_1 + 2'd2, 2'b0};
362
                        3'd1:
363
                                pc <= {pcreg_2 + 2'd2, 2'b0};
364
                        3'd2:
365
                                pc <= {pcreg_3 + 2'd2, 2'b0};
366
                        3'd3:
367
                                pc <= {pcreg_4 + 2'd2, 2'b0};
368
                        3'd4:
369
                                pc <= {pcreg_5 + 2'd2, 2'b0};
370
                        3'd5:
371
                                pc <= {pcreg_6 + 2'd2, 2'b0};
372
                        3'd6:
373
                                pc <= {pcreg_7 + 2'd2, 2'b0};
374
                        3'd7:
375
                                pc <= {pcreg_8 + 2'd2, 2'b0};
376
                        endcase
377
 
378
                        next_thread  <= {current_thread+3'd1};
379
                        temp_thread_out <= current_thread;
380
`ifdef OR1200_VERBOSE
381
// synopsys translate_off
382
                                $display("%t: BRANCHOP_BNF: not taken", $time);
383
// synopsys translate_on
384
`endif
385
                                taken <= 1'b0;
386
                        end
387
                        else begin
388
`ifdef OR1200_VERBOSE
389
// synopsys translate_off
390
        $display("%t: BRANCHOP_BNF: pc %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
391
// synopsys translate_on
392
`endif
393
                                pc <= {binsn_addr + branch_addrofs, 2'b0};
394
                                taken <= 1'b1;
395
                                next_thread <= branch_thread;
396
                                temp_thread_out <= current_thread;
397
                                // current_thread = branch_thread;
398
                        end
399
                {2'b00, `OR1200_BRANCHOP_RFE}: begin
400
`ifdef OR1200_VERBOSE
401
// synopsys translate_off
402
                        $display("%t: BRANCHOP_RFE: pc <= epcr %h", $time, epcr);
403
// synopsys translate_on
404
`endif
405
                        pc <= epcr;
406
                        taken <= 1'b1;
407
                        next_thread <= branch_thread;
408
                        temp_thread_out <= current_thread;
409
                //      current_thread = branch_thread;
410
                end
411
                {2'b01, 3'bxxx}: begin
412
`ifdef OR1200_VERBOSE
413
// synopsys translate_off
414
                        $display("Starting exception: %h.", except_type);
415
// synopsys translate_on
416
`endif
417
                        pc <= {(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), except_type, `OR1200_EXCEPT_V};
418
                        taken <= 1'b1;
419
                        next_thread <= except_thread;
420
                        temp_thread_out <= current_thread; //  except_thread;
421
                        //current_thread = except_thread;
422
                end
423
                default: begin
424
`ifdef OR1200_VERBOSE
425
// synopsys translate_off
426
                        $display("l.mtspr writing into PC: %h.", spr_dat_i);
427
// synopsys translate_on
428
`endif
429
                        pc <= spr_dat_i;
430
                        taken <= 1'b0;
431
                        next_thread <= except_thread;
432
                        temp_thread_out <= current_thread;
433
                end
434
        endcase
435
        end
436
 end
437
//bviyer
438
// assign thread_out = next_thread;
439
 
440
//bviyer
441
 
442
 
443
always @(rst or some_thread)
444
begin
445
  if (rst)
446
     current_thread = 3'd0;
447
  else
448
    current_thread = some_thread;
449
end
450
 
451
//
452
// PC register
453
// bviyer: modified for multithreading
454
always @(posedge clk or posedge rst)
455
        if (rst) begin
456
        some_thread = 3'd0;
457
`ifdef BALAJI_TESTING
458
          pcreg<=32'b0;
459
          pcreg_1<=32'h10;
460
          pcreg_2<=32'h20;
461
          pcreg_3<=32'h30;
462
          pcreg_4<=32'h40;
463
          pcreg_5<=32'h50;
464
          pcreg_6<=32'h60;
465
          pcreg_7<=32'h70;
466
          pcreg_8<=32'h80;
467
`else
468
        pcreg <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
469
        pcreg_1 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
470
        pcreg_2 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
471
        pcreg_3 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
472
        pcreg_4 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
473
        pcreg_5 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
474
        pcreg_6 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
475
        pcreg_7 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
476
        pcreg_8 <=  ({(except_prefix ? `OR1200_EXCEPT_EPH1_P : `OR1200_EXCEPT_EPH0_P), `OR1200_EXCEPT_RESET, `OR1200_EXCEPT_V} - 1) >> 2;
477
`endif
478
        end
479
        else if (spr_pc_we) begin
480
        case (temp_thread_out)          // synopsys parallel_case
481
                3'd0:   pcreg_1 <=  spr_dat_i[31:2];
482
                3'd1:   pcreg_2 <=  spr_dat_i[31:2];
483
                3'd2:   pcreg_3 <=  spr_dat_i[31:2];
484
                3'd3:   pcreg_4 <=  spr_dat_i[31:2];
485
                3'd4:   pcreg_5 <=  spr_dat_i[31:2];
486
                3'd5:   pcreg_6 <=  spr_dat_i[31:2];
487
                3'd6:   pcreg_7 <=  spr_dat_i[31:2];
488
                3'd7:   pcreg_8 <=  spr_dat_i[31:2];
489
        endcase
490
        some_thread = next_thread;
491
        end
492
        else if (no_more_dslot | except_start | !genpc_freeze & !icpu_rty_i & !genpc_refetch) begin
493
        case (temp_thread_out)          // synopsys parallel_case
494
                3'd0:   pcreg_1 <=  pc[31:2];
495
                3'd1:   pcreg_2 <=  pc[31:2];
496
                3'd2:   pcreg_3 <=  pc[31:2];
497
                3'd3:   pcreg_4 <=  pc[31:2];
498
                3'd4:   pcreg_5 <=  pc[31:2];
499
                3'd5:   pcreg_6 <=  pc[31:2];
500
                3'd6:   pcreg_7 <=  pc[31:2];
501
                3'd7:   pcreg_8 <=  pc[31:2];
502
        endcase
503
        some_thread = next_thread;
504
        end
505
endmodule

powered by: WebSVN 2.1.0

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