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 205

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

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

powered by: WebSVN 2.1.0

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