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

Subversion Repositories or1k

[/] [or1k/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [ifetch.v] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 168 lampret
 
2 218 lampret
//////////////////////////////////////////////////////////////////////
3
////                                                              ////
4
////  OR1200's instruction fetch                                  ////
5
////                                                              ////
6
////  This file is part of the OpenRISC 1200 project              ////
7
////  http://www.opencores.org/cores/or1k/                        ////
8
////                                                              ////
9
////  Description                                                 ////
10
////  PC, instruction fetch, interface to IC.                     ////
11
////                                                              ////
12
////  To Do:                                                      ////
13
////   - make it smaller and faster                               ////
14
////                                                              ////
15
////  Author(s):                                                  ////
16
////      - Damjan Lampret, lampret@opencores.org                 ////
17
////                                                              ////
18
//////////////////////////////////////////////////////////////////////
19
////                                                              ////
20
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
21
////                                                              ////
22
//// This source file may be used and distributed without         ////
23
//// restriction provided that this copyright statement is not    ////
24
//// removed from the file and that any derivative work contains  ////
25
//// the original copyright notice and the associated disclaimer. ////
26
////                                                              ////
27
//// This source file is free software; you can redistribute it   ////
28
//// and/or modify it under the terms of the GNU Lesser General   ////
29
//// Public License as published by the Free Software Foundation; ////
30
//// either version 2.1 of the License, or (at your option) any   ////
31
//// later version.                                               ////
32
////                                                              ////
33
//// This source is distributed in the hope that it will be       ////
34
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
35
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
36
//// PURPOSE.  See the GNU Lesser General Public License for more ////
37
//// details.                                                     ////
38
////                                                              ////
39
//// You should have received a copy of the GNU Lesser General    ////
40
//// Public License along with this source; if not, download it   ////
41
//// from http://www.opencores.org/lgpl.shtml                     ////
42
////                                                              ////
43
//////////////////////////////////////////////////////////////////////
44
//
45
// CVS Revision History
46
//
47
// $Log: not supported by cvs2svn $
48
// Revision 1.6  2001/10/14 13:12:09  lampret
49
// MP3 version.
50
//
51
// Revision 1.1.1.1  2001/10/06 10:18:36  igorm
52
// no message
53
//
54
// Revision 1.1  2001/08/09 13:39:33  lampret
55
// Major clean-up.
56
//
57
//
58
 
59
// synopsys translate_off
60
`include "timescale.v"
61
// synopsys translate_on
62
`include "defines.v"
63
 
64
module ifetch(
65
        // Clock and reset
66
        clk, rst,
67
 
68
        // External i/f to IC
69
        ic_insn, ic_addr, ic_stall, ic_fetchop,
70
 
71
        // Internal i/f
72
        if_freeze, if_insn, if_pc, branch_op, except_type,
73
        branch_addrofs, lr_restor, flag, taken, binsn_addr, except_start,
74 215 lampret
        epcr, force_dslot_fetch, if_stall, branch_stall,
75
        spr_dat_i, spr_pc_we
76 218 lampret
);
77
 
78
//
79
// I/O
80
//
81
 
82
//
83
// Clock and reset
84
//
85
input                           clk;
86
input                           rst;
87
 
88
//
89
// External i/f to IC
90
//
91
input   [31:0]                   ic_insn;
92
output  [31:0]                   ic_addr;
93
output  [`FETCHOP_WIDTH-1:0]     ic_fetchop;
94
input                           ic_stall;
95
 
96
//
97
// Internal i/f
98
//
99
input                           if_freeze;
100
output  [31:0]                   if_insn;
101
output  [31:0]                   if_pc;
102
input   [`BRANCHOP_WIDTH-1:0]    branch_op;
103
input   [`EXCEPT_WIDTH-1:0]      except_type;
104
input   [31:2]                  branch_addrofs;
105
input   [31:0]                   lr_restor;
106
input                           flag;
107
input   [31:2]                  binsn_addr;
108
output                          taken;
109
input                           except_start;
110
input   [31:0]                   epcr;
111
input                           force_dslot_fetch;
112
output                          if_stall;
113
output                          branch_stall;
114 215 lampret
input   [31:0]                   spr_dat_i;
115
input                           spr_pc_we;
116 218 lampret
 
117
//
118
// Internal wires and regs
119
//
120
reg     [31:2]                  pcreg;
121
reg     [32:2]                  dslot_pc;
122
reg     [32:0]                   if_saved;
123
reg     [31:0]                   pcaddr;
124
reg     [31:0]                   pc_saved;
125
reg                             taken;  /* Set to in case of jump or taken branch */
126
 
127
//
128
// Current registered PC (corresponds to fetched instruction)
129
//
130
//assign if_pc = {pcreg[31:2], 2'b00};
131
assign if_pc = (if_saved[32]) ? pc_saved : ic_addr;
132
assign ic_addr = dslot_pc[32] ? {dslot_pc[31:2], 2'b00} : pcaddr;
133
assign branch_stall = dslot_pc[32] & taken;
134
//assign if_stall = ic_stall | (~branch_stall & taken);
135
assign if_stall = ic_stall;
136
 
137
//
138
// Control access to IC subsystem
139
//
140
assign ic_fetchop = (if_saved[32] & !if_stall) ? `FETCHOP_NOP : `FETCHOP_LW;
141
 
142
//
143
// Just fetched instruction
144
//
145
assign if_insn = (if_saved[32]) ? if_saved[31:0] : (ic_stall) ? 32'h1500FFFF : ic_insn;
146
 
147
//
148
// Delay slot PC saved
149
//
150
always @(posedge clk or posedge rst)
151
        if (rst)
152
                dslot_pc <= #1 31'h00000000;
153
//      else if (force_dslot_fetch)
154
//              dslot_pc <= #1 {1'b1, pcaddr[31:2]};
155
        else if (!ic_stall)
156
                dslot_pc <= #1 31'h00000000;
157
 
158
//
159
// Async calculation of new PC value. This value is used for addressing the IC.
160
//
161
always @(pcreg or branch_addrofs or binsn_addr or flag or branch_op or except_type
162
        or except_start or lr_restor or epcr or spr_pc_we or spr_dat_i) begin
163
        casex ({spr_pc_we, except_start, branch_op})    // synopsys parallel_case
164
                {2'b00, `BRANCHOP_NOP}: begin
165
                        pcaddr = {pcreg + 'd1, 2'b0};
166
                        taken = 1'b0;
167
                end
168
                {2'b00, `BRANCHOP_J}: begin
169
`ifdef OR1200_VERBOSE
170
// synopsys translate_off
171
                        $display("%t: BRANCHOP_J: pcaddr <= branch_addrofs %h", $time, branch_addrofs);
172
// synopsys translate_on
173
`endif
174
                        pcaddr = {branch_addrofs, 2'b0};
175
                        taken = 1'b1;
176
                end
177
                {2'b00, `BRANCHOP_JR}: begin
178
`ifdef OR1200_VERBOSE
179
// synopsys translate_off
180
                        $display("%t: BRANCHOP_JR: pcaddr <= lr_restor %h", $time, lr_restor);
181
// synopsys translate_on
182
`endif
183
                        pcaddr = lr_restor;
184
                        taken = 1'b1;
185
                end
186
                {2'b00, `BRANCHOP_BAL}: begin
187
`ifdef OR1200_VERBOSE
188
// synopsys translate_off
189
                        $display("%t: BRANCHOP_BAL: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
190
// synopsys translate_on
191
`endif
192
                        pcaddr = {binsn_addr + branch_addrofs, 2'b0};
193
                        taken = 1'b1;
194
                end
195
                {2'b00, `BRANCHOP_BF}:
196
                        if (flag) begin
197
`ifdef OR1200_VERBOSE
198
// synopsys translate_off
199
                                $display("%t: BRANCHOP_BF: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
200
// synopsys translate_on
201
`endif
202
                                pcaddr = {binsn_addr + branch_addrofs, 2'b0};
203
                                taken = 1'b1;
204
                        end
205
                        else begin
206
`ifdef OR1200_VERBOSE
207
// synopsys translate_off
208
                                $display("%t: BRANCHOP_BF: not taken", $time);
209
// synopsys translate_on
210
`endif
211
                                pcaddr = {pcreg + 'd1, 2'b0};
212
                                taken = 1'b0;
213
                        end
214
                {2'b00, `BRANCHOP_BNF}:
215
                        if (flag) begin
216
                                pcaddr = {pcreg + 'd1, 2'b0};
217
`ifdef OR1200_VERBOSE
218
// synopsys translate_off
219
                                $display("%t: BRANCHOP_BNF: not taken", $time);
220
// synopsys translate_on
221
`endif
222
                                taken = 1'b0;
223
                        end
224
                        else begin
225
`ifdef OR1200_VERBOSE
226
// synopsys translate_off
227
                                $display("%t: BRANCHOP_BNF: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
228
// synopsys translate_on
229
`endif
230
                                pcaddr = {binsn_addr + branch_addrofs, 2'b0};
231
                                taken = 1'b1;
232
                        end
233
                {2'b00, `BRANCHOP_RFE}: begin
234
`ifdef OR1200_VERBOSE
235
// synopsys translate_off
236
                        $display("%t: BRANCHOP_RFE: pcaddr <= epcr %h", $time, epcr);
237
// synopsys translate_on
238
`endif
239
                        pcaddr = epcr;
240
                        taken = 1'b1;
241
                end
242
                {2'b01, 3'bxxx}: begin
243
`ifdef OR1200_VERBOSE
244
// synopsys translate_off
245
                        $display("Starting exception: %h.", except_type);
246
// synopsys translate_on
247
`endif
248
                        pcaddr = { 20'h0_0000, except_type, 8'h00};
249
                        taken = 1'b1;
250
                end
251
                default: begin
252
`ifdef OR1200_VERBOSE
253
// synopsys translate_off
254
                        $display("l.mtspr writing into PC: %h.", spr_dat_i);
255
// synopsys translate_on
256
`endif
257
                        pcaddr = spr_dat_i;
258
                        taken = 1'b0;
259
                end
260
        endcase
261
end
262
 
263
//
264
// PC register
265
//
266
always @(posedge clk or posedge rst) begin
267
        if (rst)
268
                pcreg <= #1 30'd64;
269 215 lampret
        else if (spr_pc_we)
270 218 lampret
                pcreg <= #1 spr_dat_i[31:2];
271
        else if (!if_freeze && !ic_stall) begin
272
                pcreg <= #1 ic_addr[31:2];
273
`ifdef OR1200_VERBOSE
274
// synopsys translate_off
275
                $display("%t: pcreg incremented to %h", $time, {ic_addr[31:2], 2'b0});
276
// synopsys translate_on
277
`endif
278
        end
279
end
280
 
281
//
282
// Stores INSN when pipeline is frozen
283
//
284
always @(posedge clk or posedge rst)
285
        if (rst) begin
286
                if_saved <= #1 33'b0;
287
        end
288
        else if (if_freeze && !if_saved[32] && !ic_stall) begin  // && !taken
289
                if_saved <= #1 {1'b1, ic_insn};
290
`ifdef OR1200_VERBOSE
291
// synopsys translate_off
292
                $display("%t: if_saved <= %h", $time, {1'b1, ic_insn});
293
// synopsys translate_on
294
`endif
295
        end
296
        else if (!if_freeze) begin
297
                if_saved[32] <= #1 1'b0;
298
                if_saved[31:0] <= #1 32'h1500eeee;
299
`ifdef OR1200_VERBOSE
300
// synopsys translate_off
301
                $display("%t: if_saved[32] <= 0", $time);
302
// synopsys translate_on
303
`endif
304
        end
305
 
306
//
307
// Stores PC when pipeline is frozen
308
//
309
always @(posedge clk or posedge rst)
310
        if (rst) begin
311
                pc_saved <= #1 32'b0;
312
        end
313
        else if (if_freeze && !if_saved[32] && !ic_stall) begin  // && !taken
314
                pc_saved <= #1 ic_addr;
315
        end
316
        else if (!if_freeze) begin
317
                pc_saved <= #1 32'h00000000;
318
        end
319
 
320
endmodule

powered by: WebSVN 2.1.0

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