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-3.1/] [rtl/] [verilog/] [mor1kx_fetch_tcm_prontoespresso.v] - Blame information for rev 38

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 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 pronto espresso fetch unit for TCM memories
8
 
9
  This is the fetch unit for the pipeline, so begins at the reset address and,
10
  in lock-step with the pipeline, provides the instructions according to the
11
  program flow.
12
 
13
  It is designed to interface to a single-cycle memory system (usually referred
14
  to as a tightly-coupled memory, or TCM - a ROM or a RAM). As such, it
15
  attempts to maximise throughput of the fetch stage to the pipeline.
16
 
17
  It responds to branch/exception indications from the control stage and
18
  delivers the appropriate instructions to the decode stage when the pipeline
19
  is ready to advance.
20
 
21
  It will go to "sleep" when it hits a jump-to-self instruction (0x00000000).
22
 
23
  Assumptions:
24
  Relies _heavily_ on being attached to a single-cycle memory.
25
  The ibus_adr_o requests byte-addresses, ibus_req_o is analogous to a
26
  read-enable signal, and the ibus_ack_i should be aligned with the read-data
27
  coming back.
28
 
29
  indicate ibus errors
30
 
31
  Copyright (C) 2013 Authors
32
 
33
  Author(s): Julius Baxter <juliusbaxter@gmail.com>
34
 
35
***************************************************************************** */
36
 
37
`include "mor1kx-defines.v"
38
 
39
module mor1kx_fetch_tcm_prontoespresso
40
  (/*AUTOARG*/
41
   // Outputs
42
   ibus_adr_o, ibus_req_o, decode_insn_o, fetched_pc_o, fetch_ready_o,
43
   fetch_rfa_adr_o, fetch_rfb_adr_o, fetch_rf_re_o, pc_fetch_next_o,
44
   decode_except_ibus_err_o, fetch_sleep_o,
45
   // Inputs
46
   clk, rst, ibus_err_i, ibus_ack_i, ibus_dat_i, padv_i,
47
   branch_occur_i, branch_dest_i, du_restart_i, du_restart_pc_i,
48
   fetch_take_exception_branch_i, execute_waiting_i, du_stall_i,
49
   stepping_i, flag_i, flag_clear_i, flag_set_i
50
   );
51
 
52
   parameter OPTION_OPERAND_WIDTH = 32;
53
   parameter OPTION_RF_ADDR_WIDTH = 5;
54
   parameter OPTION_RESET_PC = {{(OPTION_OPERAND_WIDTH-13){1'b0}},
55
                                `OR1K_RESET_VECTOR,8'd0};
56
 
57
   input clk, rst;
58
 
59
   // interface to ibus
60
   output [OPTION_OPERAND_WIDTH-1:0] ibus_adr_o;
61
   output                            ibus_req_o;
62
   input                             ibus_err_i;
63
   input                             ibus_ack_i;
64
   input [`OR1K_INSN_WIDTH-1:0]      ibus_dat_i;
65
 
66
   // pipeline control input
67
   input                              padv_i;
68
 
69
   // interface to decode unit
70
   output reg [`OR1K_INSN_WIDTH-1:0]  decode_insn_o;
71
 
72
   // PC of the current instruction, SPR_PPC basically
73
   output reg [OPTION_OPERAND_WIDTH-1:0] fetched_pc_o;
74
 
75
   // Indication to pipeline control that the fetch stage is ready
76
   output                                fetch_ready_o;
77
 
78
   // Signals going to register file to do the read access as we
79
   // register the instruction out to the decode stage
80
   output [OPTION_RF_ADDR_WIDTH-1:0]      fetch_rfa_adr_o;
81
   output [OPTION_RF_ADDR_WIDTH-1:0]      fetch_rfb_adr_o;
82
   output                                fetch_rf_re_o;
83
 
84
   // Signal back to the control which pc we're goint to
85
   // deliver next
86
   output [OPTION_OPERAND_WIDTH-1:0]      pc_fetch_next_o;
87
 
88
 
89
   // branch/jump indication
90
   input                                  branch_occur_i;
91
   input [OPTION_OPERAND_WIDTH-1:0]        branch_dest_i;
92
 
93
   // restart signals from debug unit
94
   input                                  du_restart_i;
95
   input [OPTION_OPERAND_WIDTH-1:0]        du_restart_pc_i;
96
 
97
   input                                  fetch_take_exception_branch_i;
98
 
99
   input                                  execute_waiting_i;
100
 
101
   // CPU is stalled
102
   input                                  du_stall_i;
103
 
104
   // We're single stepping - this should cause us to fetch only a single insn
105
   input                                  stepping_i;
106
 
107
   // Flag status information
108
   input                                  flag_i, flag_clear_i, flag_set_i;
109
 
110
   // instruction ibus error indication out
111
   output reg                             decode_except_ibus_err_o;
112
 
113
   // fetch sleep mode enabled (due to jump-to-self instruction
114
   output                                 fetch_sleep_o;
115
 
116
 
117
   reg [OPTION_OPERAND_WIDTH-1:0]          current_bus_pc;
118
   wire [OPTION_OPERAND_WIDTH-1:0]         next_bus_pc;
119
   reg [OPTION_OPERAND_WIDTH-1:0]          insn_buffer;
120
 
121
   wire                                   first_bus_req_cycle;
122
   reg                                    addr_pipelined;
123
   reg                                    bus_req, bus_req_r;
124
   wire [`OR1K_OPCODE_WIDTH-1:0]           next_insn_opcode;
125
   reg                                    next_insn_will_branch;
126
   reg                                    jump_insn_in_decode;
127
   reg                                    just_took_branch_addr;
128
   wire                                   taking_branch_addr;
129
   reg                                    insn_from_branch_on_input;
130
   reg                                    insn_from_branch_in_pipeline;
131
   reg                                    execute_waiting_r;
132
   wire                                   execute_waiting_deasserted;
133
   wire                                   execute_waiting_asserted;
134
   reg                                    execute_waiting_asserted_r;
135
   wire                                   execute_waited_single_cycle;
136
   reg                                    just_waited_single_cycle;
137
   reg                                    just_waited_single_cycle_r;
138
   reg                                    insn_buffered;
139
   wire                                   buffered_insn_is_jump;
140
   reg                                    push_buffered_jump_through_pipeline;
141
   wire                                   will_go_to_sleep;
142
   reg                                    sleep;
143
   reg                                    fetch_take_exception_branch_r;
144
   reg [3:0]                               padv_r;
145
   wire                                   long_stall;
146
 
147
 
148
   assign next_bus_pc = current_bus_pc + 4;
149
   assign ibus_adr_o = addr_pipelined ? next_bus_pc : current_bus_pc;
150
 
151
   assign pc_fetch_next_o = ibus_adr_o;
152
 
153
   assign ibus_req_o = bus_req & !(stepping_i & ibus_ack_i)  |
154
                       (execute_waiting_deasserted &
155
                        !(insn_buffered & next_insn_will_branch)) |
156
                       fetch_take_exception_branch_r;
157
 
158
   // Signal rising edge on bus request signal
159
   assign first_bus_req_cycle = ibus_req_o & !bus_req_r;
160
 
161
   assign taking_branch_addr = (branch_occur_i & padv_i) |
162
                               fetch_take_exception_branch_i;
163
 
164
   assign buffered_insn_is_jump = insn_buffered & next_insn_will_branch;
165
 
166
   always @(posedge clk `OR_ASYNC_RST)
167
     if (rst)
168
       begin
169
          current_bus_pc                <= OPTION_RESET_PC;
170
          just_took_branch_addr         <= 0;
171
       end
172
     else if (du_restart_i)
173
       begin
174
          current_bus_pc <= du_restart_pc_i;
175
          just_took_branch_addr         <= 0;
176
       end
177
     else if (fetch_take_exception_branch_i)
178
       begin
179
          current_bus_pc <= branch_dest_i;
180
          just_took_branch_addr         <= 1;
181
       end
182
     else if (branch_occur_i & padv_i)
183
       begin
184
          current_bus_pc <= branch_dest_i;
185
          just_took_branch_addr         <= 1;
186
       end
187
     else if (ibus_ack_i & (padv_i | (just_waited_single_cycle_r &&
188
                                      !({padv_r[0],padv_i}==2'b00))) &
189
              !execute_waited_single_cycle & !stepping_i)
190
       begin
191
          current_bus_pc <= next_bus_pc;
192
          just_took_branch_addr         <= 0;
193
       end
194
     else if (execute_waiting_asserted & ibus_ack_i & !just_took_branch_addr)
195
       begin
196
          current_bus_pc <= next_bus_pc;
197
       end
198
     else if (just_took_branch_addr)
199
       begin
200
          just_took_branch_addr <= 0;
201
       end
202
 
203
     else if (long_stall)
204
       begin
205
          // Long wait - this is a work around for an annoying bug which
206
          // I can't solve any other way!
207
          current_bus_pc <= fetched_pc_o + 4;
208
       end
209
 
210
   // BIG assumptions here - that the read only takes a single cycle!!
211
   always @(posedge clk `OR_ASYNC_RST)
212
     if (rst)
213
       begin
214
          insn_from_branch_on_input <= 0;
215
          insn_from_branch_in_pipeline <= 0;
216
       end
217
     else
218
       begin
219
          insn_from_branch_on_input <= just_took_branch_addr;
220
          insn_from_branch_in_pipeline <= insn_from_branch_on_input;
221
       end
222
 
223
 
224
   always @(posedge clk `OR_ASYNC_RST)
225
     if (rst)
226
       bus_req <= 1'b0;
227
     else if (stepping_i & ibus_ack_i)
228
       // Deassert on ack of stepping
229
       bus_req <= 1'b0;
230
     else if (du_stall_i)
231
       bus_req <= 1'b0;
232
     else if (ibus_err_i | decode_except_ibus_err_o)
233
       bus_req <= 1'b0;
234
     else if (sleep)
235
       bus_req <= 1'b0;
236
     else if (execute_waiting_i)
237
       bus_req <= 1'b0;
238
     else if (buffered_insn_is_jump)
239
       bus_req <= 1'b0;
240
     else
241
       bus_req <= 1'b1;
242
 
243
   always @(posedge clk `OR_ASYNC_RST)
244
     if (rst)
245
       bus_req_r <= 0;
246
     else
247
       bus_req_r <= ibus_req_o;
248
 
249
   always @(posedge clk `OR_ASYNC_RST)
250
     if (rst)
251
       addr_pipelined <= 0;
252
     else if (ibus_err_i | decode_except_ibus_err_o |
253
              fetch_take_exception_branch_i)
254
       addr_pipelined <= 0;
255
     else if (first_bus_req_cycle)
256
       addr_pipelined <= 1;
257
     else if (taking_branch_addr)
258
       addr_pipelined <= 0;
259
     else if (just_took_branch_addr)
260
       addr_pipelined <= 1;
261
     else if (just_waited_single_cycle)
262
       addr_pipelined <= 1;
263
     else if (!bus_req)
264
       addr_pipelined <= 0;
265
 
266
   always @(posedge clk `OR_ASYNC_RST)
267
     if (rst)
268
       begin
269
          decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
270
          fetched_pc_o  <= 0;
271
       end
272
     else if (sleep | (du_stall_i & !execute_waiting_i))
273
       begin
274
          decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
275
       end
276
     else if (fetch_take_exception_branch_i & !du_stall_i)
277
       begin
278
          decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
279
       end
280
     else if ((padv_i | stepping_i) & ibus_ack_i & (ibus_req_o | stepping_i) &
281
              ((!jump_insn_in_decode & !just_took_branch_addr) |
282
               (insn_from_branch_on_input))
283
              & !(execute_waited_single_cycle | just_waited_single_cycle))
284
       begin
285
          decode_insn_o <= ibus_dat_i;
286
          fetched_pc_o  <= current_bus_pc;
287
       end
288
     else if (just_waited_single_cycle_r & !execute_waiting_i)
289
       begin
290
          decode_insn_o <= ibus_dat_i;
291
          fetched_pc_o  <= current_bus_pc;
292
       end
293
     else if (execute_waiting_deasserted & insn_buffered)
294
       begin
295
          decode_insn_o <= insn_buffer;
296
          fetched_pc_o  <= fetched_pc_o + 4;
297
       end
298
     else if ((jump_insn_in_decode | branch_occur_i) & padv_i)
299
       // About to jump - remove this instruction from the pipeline
300
       decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
301
     else if (fetch_take_exception_branch_i)
302
       decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
303
     else if (push_buffered_jump_through_pipeline)
304
       decode_insn_o <= {`OR1K_OPCODE_NOP,26'd0};
305
 
306
   reg fetch_ready_r;
307
 
308
   always @(posedge clk `OR_ASYNC_RST)
309
     if (rst)
310
       fetch_ready_r <= 0;
311
     else
312
       fetch_ready_r <= fetch_ready_o;
313
 
314
   assign fetch_ready_o = (ibus_ack_i | insn_buffered ) &
315
                          !(just_took_branch_addr) &
316
                          !(just_waited_single_cycle) &
317
                          !du_stall_i |
318
                          push_buffered_jump_through_pipeline ;
319
 
320
   always @(posedge clk `OR_ASYNC_RST)
321
     if (rst)
322
       decode_except_ibus_err_o <= 0;
323
     else if ((padv_i | fetch_take_exception_branch_i) &
324
              branch_occur_i | du_stall_i)
325
       decode_except_ibus_err_o <= 0;
326
     else if (bus_req)
327
       decode_except_ibus_err_o <= ibus_err_i;
328
 
329
   assign fetch_sleep_o = sleep;
330
 
331
   always @(posedge clk `OR_ASYNC_RST)
332
     if (rst)
333
       execute_waiting_r <= 0;
334
     else
335
       execute_waiting_r <= execute_waiting_i;
336
 
337
   assign execute_waiting_deasserted = !execute_waiting_i & execute_waiting_r;
338
   assign execute_waiting_asserted = execute_waiting_i & !execute_waiting_r;
339
 
340
 
341
   // Register file control
342
   assign fetch_rfa_adr_o       = insn_buffered ? insn_buffer[`OR1K_RA_SELECT] :
343
                                  ibus_dat_i[`OR1K_RA_SELECT];
344
   assign fetch_rfb_adr_o       = insn_buffered ? insn_buffer[`OR1K_RB_SELECT] :
345
                                  ibus_dat_i[`OR1K_RB_SELECT];
346
   assign fetch_rf_re_o         = (ibus_ack_i | execute_waiting_deasserted) &
347
                                  (padv_i | stepping_i);
348
 
349
   // Pick out opcode of next instruction to go to decode stage
350
   assign next_insn_opcode      = insn_buffered ?
351
                                  insn_buffer[`OR1K_OPCODE_SELECT] :
352
                                  ibus_dat_i[`OR1K_OPCODE_SELECT];
353
 
354
   always @*
355
     if ((ibus_ack_i & !just_took_branch_addr) | insn_buffered)
356
       case (next_insn_opcode)
357
         `OR1K_OPCODE_J,
358
         `OR1K_OPCODE_JAL: begin
359
            next_insn_will_branch       = 1;
360
         end
361
         `OR1K_OPCODE_JR,
362
           `OR1K_OPCODE_JALR: begin
363
              next_insn_will_branch     = 1;
364
           end
365
         `OR1K_OPCODE_BNF: begin
366
            next_insn_will_branch       = !(flag_i | flag_set_i) | flag_clear_i;
367
         end
368
         `OR1K_OPCODE_BF: begin
369
            next_insn_will_branch       = !(!flag_i | flag_clear_i) |flag_set_i;
370
         end
371
         `OR1K_OPCODE_SYSTRAPSYNC,
372
           `OR1K_OPCODE_RFE: begin
373
              next_insn_will_branch     = 1;
374
           end
375
         default: begin
376
            next_insn_will_branch       = 0;
377
         end
378
       endcase // case (next_insn_opcode)
379
     else
380
       begin
381
          next_insn_will_branch         = 0;
382
       end
383
 
384
   always @(posedge clk `OR_ASYNC_RST)
385
     if (rst)
386
       jump_insn_in_decode <= 0;
387
     else if (sleep)
388
       jump_insn_in_decode <= 0;
389
     else if (!jump_insn_in_decode & next_insn_will_branch & ibus_ack_i)
390
       jump_insn_in_decode <= 1;
391
     else
392
       jump_insn_in_decode <= 0;
393
 
394
   always @(posedge clk `OR_ASYNC_RST)
395
     if (rst)
396
       insn_buffer <= 0;
397
     else if (execute_waiting_asserted & ibus_ack_i & !just_took_branch_addr)
398
       insn_buffer <= ibus_dat_i;
399
 
400
   always @(posedge clk `OR_ASYNC_RST)
401
     if (rst)
402
       insn_buffered <= 0;
403
     else if (execute_waiting_asserted & ibus_ack_i & !just_took_branch_addr)
404
       insn_buffered <= 1;
405
     else if (execute_waiting_deasserted)
406
       insn_buffered <= 0;
407
     else if (fetch_take_exception_branch_i)
408
       insn_buffered <= 0;
409
     else if (long_stall)
410
       insn_buffered <= 0;
411
 
412
   always @(posedge clk `OR_ASYNC_RST)
413
     if (rst)
414
       push_buffered_jump_through_pipeline  <= 0;
415
     else
416
       push_buffered_jump_through_pipeline <= buffered_insn_is_jump &
417
                                              execute_waiting_deasserted;
418
 
419
   always @(posedge clk `OR_ASYNC_RST)
420
     if (rst)
421
       fetch_take_exception_branch_r <= 0;
422
     else
423
       fetch_take_exception_branch_r <= fetch_take_exception_branch_i;
424
 
425
   always @(posedge clk `OR_ASYNC_RST)
426
     if (rst)
427
       sleep <= 1'b0;
428
     else if (fetch_take_exception_branch_i)
429
       sleep <= 1'b0;
430
     else if (will_go_to_sleep)
431
       sleep <= 1'b1;
432
 
433
   assign will_go_to_sleep = ibus_dat_i==0 & padv_i & ibus_ack_i &
434
                             ibus_req_o & ((!jump_insn_in_decode &
435
                                            !just_took_branch_addr) |
436
                                           (insn_from_branch_on_input));
437
 
438
   always @(posedge clk `OR_ASYNC_RST)
439
     if (rst)
440
       execute_waiting_asserted_r <= 0;
441
     else
442
       execute_waiting_asserted_r <= execute_waiting_asserted;
443
 
444
   assign execute_waited_single_cycle =  execute_waiting_asserted_r &
445
                                          !execute_waiting_i;
446
 
447
   always @(posedge clk `OR_ASYNC_RST)
448
     if (rst)
449
       begin
450
          just_waited_single_cycle <= 0;
451
          just_waited_single_cycle_r <= 0;
452
       end
453
     else
454
       begin
455
          just_waited_single_cycle <= execute_waited_single_cycle;
456
          just_waited_single_cycle_r <= just_waited_single_cycle;
457
       end
458
 
459
   always @(posedge clk `OR_ASYNC_RST)
460
     if (rst)
461
       padv_r <= 4'd0;
462
     else
463
       padv_r <= {padv_r[2:0],padv_i};
464
 
465
   assign long_stall = {padv_r,padv_i}==5'b10000 && execute_waiting_i;
466
 
467
endmodule // mor1kx_fetch_tcm_prontoespresso

powered by: WebSVN 2.1.0

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