OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [src_processor/] [mor1kx-5.0/] [rtl/] [verilog/] [mor1kx_fetch_espresso.v] - Blame information for rev 48

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 48 alirezamon
/* ****************************************************************************
2
  This Source Code Form is subject to the terms of the
3
  Open Hardware Description License, v. 1.0. If a copy
4
  of the OHDL was not distributed with this file, You
5
  can obtain one at http://juliusbaxter.net/ohdl/ohdl.txt
6
 
7
  Description: mor1kx espresso fetch unit
8
 
9
  Fetch insn, advance PC (or take new branch address) on padv_i.
10
 
11
  What we might want to do is have a 1-insn buffer here, so when the current
12
  insn is fetched, but the main pipeline doesn't want it yet
13
 
14
  indicate ibus errors
15
 
16
  Copyright (C) 2012 Authors
17
 
18
  Author(s): Julius Baxter <juliusbaxter@gmail.com>
19
 
20
***************************************************************************** */
21
 
22
`include "mor1kx-defines.v"
23
 
24
module mor1kx_fetch_espresso
25
  (/*AUTOARG*/
26
   // Outputs
27
   ibus_adr_o, ibus_req_o, ibus_burst_o, decode_insn_o,
28
   next_fetch_done_o, fetch_rfa_adr_o, fetch_rfb_adr_o, pc_fetch_o,
29
   pc_fetch_next_o, decode_except_ibus_err_o, fetch_advancing_o,
30
   // Inputs
31
   clk, rst, ibus_err_i, ibus_ack_i, ibus_dat_i, padv_i,
32
   branch_occur_i, branch_dest_i, du_restart_i, du_restart_pc_i,
33
   fetch_take_exception_branch_i, execute_waiting_i, du_stall_i,
34
   stepping_i
35
   );
36
 
37
   parameter OPTION_OPERAND_WIDTH = 32;
38
   parameter OPTION_RF_ADDR_WIDTH = 5;
39
   parameter OPTION_RESET_PC = {{(OPTION_OPERAND_WIDTH-13){1'b0}},
40
                                `OR1K_RESET_VECTOR,8'd0};
41
 
42
 
43
   input clk, rst;
44
 
45
   // interface to ibus
46
   output [OPTION_OPERAND_WIDTH-1:0] ibus_adr_o;
47
   output                             ibus_req_o;
48
   output                             ibus_burst_o;
49
   input                              ibus_err_i;
50
   input                              ibus_ack_i;
51
   input [`OR1K_INSN_WIDTH-1:0]       ibus_dat_i;
52
 
53
   // pipeline control input
54
   input                              padv_i;
55
 
56
   // interface to decode unit
57
   output reg [`OR1K_INSN_WIDTH-1:0]      decode_insn_o;
58
   // Indication to pipeline control that the fetch is valid
59
   output                                next_fetch_done_o;
60
 
61
   output [OPTION_RF_ADDR_WIDTH-1:0]      fetch_rfa_adr_o;
62
   output [OPTION_RF_ADDR_WIDTH-1:0]      fetch_rfb_adr_o;
63
 
64
   // Signal back to the control
65
   output [OPTION_OPERAND_WIDTH-1:0]      pc_fetch_o;
66
   output [OPTION_OPERAND_WIDTH-1:0]      pc_fetch_next_o;
67
 
68
 
69
   // branch/jump indication
70
   input                                  branch_occur_i;
71
   input [OPTION_OPERAND_WIDTH-1:0]        branch_dest_i;
72
 
73
   // restart signals from debug unit
74
   input                                  du_restart_i;
75
   input [OPTION_OPERAND_WIDTH-1:0]        du_restart_pc_i;
76
 
77
   input                                  fetch_take_exception_branch_i;
78
 
79
   input                                  execute_waiting_i;
80
 
81
   // CPU is stalled
82
   input                                  du_stall_i;
83
 
84
   // We're single stepping - this should cause us to fetch only a single insn
85
   input                                  stepping_i;
86
 
87
 
88
   // instruction ibus error indication out
89
   output reg                             decode_except_ibus_err_o;
90
 
91
   output                                 fetch_advancing_o;
92
 
93
   // registers
94
   reg [OPTION_OPERAND_WIDTH-1:0]          pc_fetch;
95
   reg                                    fetch_req;
96
   reg                                    next_insn_buffered;
97
   reg [OPTION_OPERAND_WIDTH-1:0]          insn_buffer;
98
   reg                                    branch_occur_r;
99
   reg                                    bus_access_done_re_r;
100
   reg                                    advancing_into_branch;
101
   reg                                    bus_access_done_r;
102
   reg                                    wait_for_exception_after_ibus_err;
103
 
104
   wire [OPTION_OPERAND_WIDTH-1:0]         pc_fetch_next;
105
   wire                                   bus_access_done;
106
   wire                                   bus_access_done_fe;
107
   wire                                   branch_occur_re;
108
   wire                                   awkward_transition_to_branch_target;
109
   wire                                   taking_branch;
110
   wire                                   jal_buffered;
111
   wire                                   retain_fetch_pc;
112
 
113
   assign taking_branch = branch_occur_i & padv_i;
114
 
115
   assign bus_access_done =  (ibus_ack_i | ibus_err_i) & !(taking_branch);
116
 
117
   assign pc_fetch_next = pc_fetch + 4;
118
 
119
   assign ibus_adr_o = pc_fetch;
120
   assign ibus_req_o = fetch_req;
121
   assign ibus_burst_o = 0;
122
 
123
   assign fetch_advancing_o = (padv_i | fetch_take_exception_branch_i |
124
                               stepping_i) &
125
                              next_fetch_done_o;
126
 
127
   // Early RF address fetch
128
   assign fetch_rfa_adr_o = insn_buffer[`OR1K_RA_SELECT];
129
   assign fetch_rfb_adr_o = insn_buffer[`OR1K_RB_SELECT];
130
 
131
   assign jal_buffered = insn_buffer[`OR1K_OPCODE_SELECT]==`OR1K_OPCODE_JALR ||
132
                         insn_buffer[`OR1K_OPCODE_SELECT]==`OR1K_OPCODE_JAL;
133
 
134
   assign retain_fetch_pc = jal_buffered & bus_access_done;
135
 
136
   always @(posedge clk `OR_ASYNC_RST)
137
     if (rst)
138
       pc_fetch <= OPTION_RESET_PC;
139
     else if (fetch_take_exception_branch_i |
140
              (((bus_access_done & !ibus_err_i) | taking_branch) &
141
               (!execute_waiting_i | !next_insn_buffered) &
142
               !retain_fetch_pc) |
143
              awkward_transition_to_branch_target |
144
              du_restart_i)
145
       // next PC - are we going somewhere else or advancing?
146
       pc_fetch <= du_restart_i ? du_restart_pc_i :
147
                   (fetch_take_exception_branch_i | taking_branch) ?
148
                   branch_dest_i : pc_fetch_next;
149
 
150
   // Actually goes to pipeline control
151
   assign pc_fetch_o = pc_fetch;
152
   assign pc_fetch_next_o = pc_fetch_next;
153
 
154
   always @(posedge clk `OR_ASYNC_RST)
155
     if (rst)
156
       fetch_req <= 1;
157
     else if (fetch_take_exception_branch_i | du_restart_i)
158
       fetch_req <= 1;
159
     else if (padv_i)
160
       // Force de-assert of req signal when branching.
161
       // This is to stop (ironically) the case where we've got the
162
       // instruction we're branching to already coming in on the bus,
163
       // which we usually don't assume will happen.
164
       // TODO: fix things so that we don't have to force a penalty to make
165
       // it work properly.
166
       fetch_req <= !branch_occur_i & !du_stall_i;
167
     else if (du_stall_i)
168
       fetch_req <= fetch_req & !bus_access_done;
169
     else if (!fetch_req & !execute_waiting_i &
170
              !wait_for_exception_after_ibus_err & !retain_fetch_pc &
171
              !du_stall_i & !stepping_i)
172
       fetch_req <= 1;
173
     else if (bus_access_done & (fetch_take_exception_branch_i |
174
                                 execute_waiting_i | ibus_err_i | stepping_i))
175
       fetch_req <= 0;
176
 
177
   always @(posedge clk `OR_ASYNC_RST)
178
     if (rst)
179
       begin
180
          bus_access_done_r <= 0;
181
          branch_occur_r <= 0;
182
       end
183
     else
184
       begin
185
          bus_access_done_r <= bus_access_done;
186
          branch_occur_r <= branch_occur_i;
187
       end
188
 
189
   always @(posedge clk `OR_ASYNC_RST)
190
     if (rst)
191
       advancing_into_branch <= 0;
192
     else
193
       advancing_into_branch <= fetch_advancing_o & branch_occur_i;
194
 
195
   assign next_fetch_done_o = (bus_access_done_r | next_insn_buffered) &
196
                              // Whenever we've just changed the fetch PC to
197
                              // take a branch this will gate off any ACKs we
198
                              // might get (legit or otherwise) from where we're
199
                              // getting our instructions from (bus/cache).
200
                              !(advancing_into_branch);
201
 
202
   assign branch_occur_re = branch_occur_i & !branch_occur_r;
203
 
204
   /* When this occurs we had the insn burst stream finish just as we
205
    had a new branch address requested. Because the control logic will
206
    immediately continue onto the delay slot instruction, the branch target
207
    is only valid for 1 cycle. The PC out to the bus/cache will then need
208
    to change 1 cycle after it requested the insn after the delay slot.
209
    This is annoying for the bus control/cache logic, but should result in
210
    less cycles wasted fetching something we don't need, and as well reduce
211
    the number of flops as we don't need to save the target PC which we had
212
    for only 1 cycle */
213
   assign awkward_transition_to_branch_target = branch_occur_re &
214
                                                bus_access_done_fe;
215
 
216
   always @(posedge clk `OR_ASYNC_RST)
217
     if (rst)
218
       decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
219
     else if (fetch_take_exception_branch_i | (du_stall_i & !execute_waiting_i))
220
       // Put a NOP in the pipeline when starting exception - remove any state
221
       // which may be causing the exception
222
       decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
223
     else if ((padv_i & (
224
                         bus_access_done_r |
225
                         bus_access_done |
226
                         next_insn_buffered
227
                         ) &
228
               !branch_occur_r ) |
229
              // This case is when we stalled to get the delay-slot instruction
230
              // and we don't get enough padv to push it through the buffer
231
              (branch_occur_i & padv_i & bus_access_done_re_r) |
232
              (bus_access_done_fe & stepping_i))
233
       decode_insn_o <= insn_buffer;
234
 
235
   always @(posedge clk `OR_ASYNC_RST)
236
     if (rst)
237
       decode_except_ibus_err_o <= 0;
238
     else if ((padv_i | fetch_take_exception_branch_i) & branch_occur_i |
239
              du_stall_i)
240
       decode_except_ibus_err_o <= 0;
241
     else if (fetch_req)
242
       decode_except_ibus_err_o <= ibus_err_i;
243
 
244
   // Register rising edge on bus_access_done
245
    always @(posedge clk `OR_ASYNC_RST)
246
     if (rst)
247
       bus_access_done_re_r <= 0;
248
     else
249
       bus_access_done_re_r <= bus_access_done & !bus_access_done_r;
250
 
251
   assign bus_access_done_fe = !bus_access_done & bus_access_done_r;
252
 
253
   /* If insn_buffer contains the next insn we need, save that information
254
    here */
255
   always @(posedge clk `OR_ASYNC_RST)
256
     if (rst)
257
       next_insn_buffered <= 0;
258
     else if (fetch_take_exception_branch_i)
259
       next_insn_buffered <= 0;
260
     else if (padv_i)
261
       // Next instruction is usually buffered when we've got bus ack and
262
       // pipeline advance, except when we're branching (usually throw
263
       // away the fetch when branch is being indicated)
264
       next_insn_buffered <= ibus_ack_i & !branch_occur_i;
265
     else if (ibus_ack_i & execute_waiting_i)
266
       next_insn_buffered <= 1;
267
 
268
   always @(posedge clk `OR_ASYNC_RST)
269
     if (rst)
270
       insn_buffer <= {`OR1K_OPCODE_NOP,26'd0};
271
     else if (ibus_ack_i & (!execute_waiting_i | !next_insn_buffered) &
272
              // Don't buffer instruction after delay slot instruction
273
              // (usually we're receiving it as taking branch is asserted)
274
              // it could be another jump instruction and having it in
275
              // the insn_buffer has annoying side-effects.
276
              !taking_branch)
277
       insn_buffer <= ibus_dat_i;
278
 
279
   always @(posedge clk `OR_ASYNC_RST)
280
     if (rst)
281
       wait_for_exception_after_ibus_err <= 0;
282
     else if (fetch_take_exception_branch_i)
283
       wait_for_exception_after_ibus_err <= 0;
284
     else if (ibus_err_i)
285
       wait_for_exception_after_ibus_err <= 1;
286
 
287
endmodule // mor1kx_fetch_espresso

powered by: WebSVN 2.1.0

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