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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [mp3/] [rtl/] [verilog/] [or1200.xcv/] [ifetch.v] - Blame information for rev 1773

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 266 lampret
 
2
//////////////////////////////////////////////////////////////////////
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.1.1.1  2001/10/06 10:18:36  igorm
49
// no message
50
//
51
// Revision 1.1  2001/08/09 13:39:33  lampret
52
// Major clean-up.
53
//
54
//
55
 
56
// synopsys translate_off
57
`include "timescale.v"
58
// synopsys translate_on
59
`include "defines.v"
60
 
61
module ifetch(
62
        // Clock and reset
63
        clk, rst,
64
 
65
        // External i/f to IC
66
        ic_insn, ic_addr, ic_stall, ic_fetchop,
67
 
68
        // Internal i/f
69
        if_freeze, if_insn, if_pc, branch_op, except_type,
70
        branch_addrofs, lr_restor, flag, taken, binsn_addr, except_start,
71
        epcr, force_dslot_fetch, if_stall, branch_stall,
72
        spr_dat_i, spr_pc_we
73
);
74
 
75
//
76
// I/O
77
//
78
 
79
//
80
// Clock and reset
81
//
82
input                           clk;
83
input                           rst;
84
 
85
//
86
// External i/f to IC
87
//
88
input   [31:0]                   ic_insn;
89
output  [31:0]                   ic_addr;
90
output  [`FETCHOP_WIDTH-1:0]     ic_fetchop;
91
input                           ic_stall;
92
 
93
//
94
// Internal i/f
95
//
96
input                           if_freeze;
97
output  [31:0]                   if_insn;
98
output  [31:0]                   if_pc;
99
input   [`BRANCHOP_WIDTH-1:0]    branch_op;
100
input   [`EXCEPT_WIDTH-1:0]      except_type;
101
input   [31:2]                  branch_addrofs;
102
input   [31:0]                   lr_restor;
103
input                           flag;
104
input   [31:2]                  binsn_addr;
105
output                          taken;
106
input                           except_start;
107
input   [31:0]                   epcr;
108
input                           force_dslot_fetch;
109
output                          if_stall;
110
output                          branch_stall;
111
input   [31:0]                   spr_dat_i;
112
input                           spr_pc_we;
113
 
114
//
115
// Internal wires and regs
116
//
117
reg     [31:2]                  pcreg;
118
reg     [32:2]                  dslot_pc;
119
reg     [32:0]                   if_saved;
120
reg     [31:0]                   pcaddr;
121
reg     [31:0]                   pc_saved;
122
reg                             taken;  /* Set to in case of jump or taken branch */
123
 
124
//
125
// Current registered PC (corresponds to fetched instruction)
126
//
127
//assign if_pc = {pcreg[31:2], 2'b00};
128
assign if_pc = (if_saved[32]) ? pc_saved : ic_addr;
129
assign ic_addr = dslot_pc[32] ? {dslot_pc[31:2], 2'b00} : pcaddr;
130
assign branch_stall = dslot_pc[32] & taken;
131
//assign if_stall = ic_stall | (~branch_stall & taken);
132
assign if_stall = ic_stall;
133
 
134
//
135
// Control access to IC subsystem
136
//
137
assign ic_fetchop = (if_saved[32] & !if_stall) ? `FETCHOP_NOP : `FETCHOP_LW;
138
 
139
//
140
// Just fetched instruction
141
//
142
assign if_insn = (if_saved[32]) ? if_saved[31:0] : (ic_stall) ? 32'h1500FFFF : ic_insn;
143
 
144
//
145
// Delay slot PC saved
146
//
147
always @(posedge clk or posedge rst)
148
        if (rst)
149
                dslot_pc <= #1 31'h00000000;
150
//      else if (force_dslot_fetch)
151
//              dslot_pc <= #1 {1'b1, pcaddr[31:2]};
152
        else if (!ic_stall)
153
                dslot_pc <= #1 31'h00000000;
154
 
155
//
156
// Async calculation of new PC value. This value is used for addressing the IC.
157
//
158
always @(pcreg or branch_addrofs or binsn_addr or flag or branch_op or except_type
159
        or except_start or lr_restor or epcr or spr_pc_we or spr_dat_i) begin
160
        casex ({spr_pc_we, except_start, branch_op})    // synopsys parallel_case
161
                {2'b00, `BRANCHOP_NOP}: begin
162
                        pcaddr = {pcreg + 'd1, 2'b0};
163
                        taken = 1'b0;
164
                end
165
                {2'b00, `BRANCHOP_J}: begin
166
`ifdef OR1200_VERBOSE
167
// synopsys translate_off
168
                        $display("%t: BRANCHOP_J: pcaddr <= branch_addrofs %h", $time, branch_addrofs);
169
// synopsys translate_on
170
`endif
171
                        pcaddr = {branch_addrofs, 2'b0};
172
                        taken = 1'b1;
173
                end
174
                {2'b00, `BRANCHOP_JR}: begin
175
`ifdef OR1200_VERBOSE
176
// synopsys translate_off
177
                        $display("%t: BRANCHOP_JR: pcaddr <= lr_restor %h", $time, lr_restor);
178
// synopsys translate_on
179
`endif
180
                        pcaddr = lr_restor;
181
                        taken = 1'b1;
182
                end
183
                {2'b00, `BRANCHOP_BAL}: begin
184
`ifdef OR1200_VERBOSE
185
// synopsys translate_off
186
                        $display("%t: BRANCHOP_BAL: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
187
// synopsys translate_on
188
`endif
189
                        pcaddr = {binsn_addr + branch_addrofs, 2'b0};
190
                        taken = 1'b1;
191
                end
192
                {2'b00, `BRANCHOP_BF}:
193
                        if (flag) begin
194
`ifdef OR1200_VERBOSE
195
// synopsys translate_off
196
                                $display("%t: BRANCHOP_BF: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
197
// synopsys translate_on
198
`endif
199
                                pcaddr = {binsn_addr + branch_addrofs, 2'b0};
200
                                taken = 1'b1;
201
                        end
202
                        else begin
203
`ifdef OR1200_VERBOSE
204
// synopsys translate_off
205
                                $display("%t: BRANCHOP_BF: not taken", $time);
206
// synopsys translate_on
207
`endif
208
                                pcaddr = {pcreg + 'd1, 2'b0};
209
                                taken = 1'b0;
210
                        end
211
                {2'b00, `BRANCHOP_BNF}:
212
                        if (flag) begin
213
                                pcaddr = {pcreg + 'd1, 2'b0};
214
`ifdef OR1200_VERBOSE
215
// synopsys translate_off
216
                                $display("%t: BRANCHOP_BNF: not taken", $time);
217
// synopsys translate_on
218
`endif
219
                                taken = 1'b0;
220
                        end
221
                        else begin
222
`ifdef OR1200_VERBOSE
223
// synopsys translate_off
224
                                $display("%t: BRANCHOP_BNF: pcaddr %h = binsn_addr %h + branch_addrofs %h", $time, binsn_addr + branch_addrofs, binsn_addr, branch_addrofs);
225
// synopsys translate_on
226
`endif
227
                                pcaddr = {binsn_addr + branch_addrofs, 2'b0};
228
                                taken = 1'b1;
229
                        end
230
                {2'b00, `BRANCHOP_RFE}: begin
231
`ifdef OR1200_VERBOSE
232
// synopsys translate_off
233
                        $display("%t: BRANCHOP_RFE: pcaddr <= epcr %h", $time, epcr);
234
// synopsys translate_on
235
`endif
236
                        pcaddr = epcr;
237
                        taken = 1'b1;
238
                end
239
                {2'b01, 3'bxxx}: begin
240
`ifdef OR1200_VERBOSE
241
// synopsys translate_off
242
                        $display("Starting exception: %h.", except_type);
243
// synopsys translate_on
244
`endif
245
                        pcaddr = { 20'h0_0000, except_type, 8'h00};
246
                        taken = 1'b1;
247
                end
248
                default: begin
249
`ifdef OR1200_VERBOSE
250
// synopsys translate_off
251
                        $display("l.mtspr writing into PC: %h.", spr_dat_i);
252
// synopsys translate_on
253
`endif
254
                        pcaddr = spr_dat_i;
255
                        taken = 1'b0;
256
                end
257
        endcase
258
end
259
 
260
//
261
// PC register
262
//
263
always @(posedge clk or posedge rst) begin
264
        if (rst)
265
                pcreg <= #1 30'd64;
266
        else if (spr_pc_we)
267
                pcreg <= #1 spr_dat_i[31:2];
268
        else if (!if_freeze && !ic_stall) begin
269
                pcreg <= #1 ic_addr[31:2];
270
`ifdef OR1200_VERBOSE
271
// synopsys translate_off
272
                $display("%t: pcreg incremented to %h", $time, {ic_addr[31:2], 2'b0});
273
// synopsys translate_on
274
`endif
275
        end
276
end
277
 
278
//
279
// Stores INSN when pipeline is frozen
280
//
281
always @(posedge clk or posedge rst)
282
        if (rst) begin
283
                if_saved <= #1 33'b0;
284
        end
285
        else if (if_freeze && !if_saved[32] && !ic_stall) begin  // && !taken
286
                if_saved <= #1 {1'b1, ic_insn};
287
`ifdef OR1200_VERBOSE
288
// synopsys translate_off
289
                $display("%t: if_saved <= %h", $time, {1'b1, ic_insn});
290
// synopsys translate_on
291
`endif
292
        end
293
        else if (!if_freeze) begin
294
                if_saved[32] <= #1 1'b0;
295
                if_saved[31:0] <= #1 32'h1500eeee;
296
`ifdef OR1200_VERBOSE
297
// synopsys translate_off
298
                $display("%t: if_saved[32] <= 0", $time);
299
// synopsys translate_on
300
`endif
301
        end
302
 
303
//
304
// Stores PC when pipeline is frozen
305
//
306
always @(posedge clk or posedge rst)
307
        if (rst) begin
308
                pc_saved <= #1 32'b0;
309
        end
310
        else if (if_freeze && !if_saved[32] && !ic_stall) begin  // && !taken
311
                pc_saved <= #1 ic_addr;
312
        end
313
        else if (!if_freeze) begin
314
                pc_saved <= #1 32'h00000000;
315
        end
316
 
317
endmodule

powered by: WebSVN 2.1.0

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