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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [core/] [prefetch.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    prefetch.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This is a very simple instruction fetch approach.  It gets
8
//              one instruction at a time.  Future versions should pipeline
9 209 dgisselq
//      fetches and perhaps even cache results--this doesn't do that.  It
10
//      should, however, be simple enough to get things running.
11 2 dgisselq
//
12 209 dgisselq
//      The interface is fascinating.  The 'i_pc' input wire is just a
13
//      suggestion of what to load.  Other wires may be loaded instead. i_pc
14
//      is what must be output, not necessarily input.
15 2 dgisselq
//
16 209 dgisselq
//   20150919 -- Added support for the WB error signal.  When reading an
17
//      instruction results in this signal being raised, the pipefetch module
18
//      will set an illegal instruction flag to be returned to the CPU together
19
//      with the instruction.  Hence, the ZipCPU can trap on it if necessary.
20 36 dgisselq
//
21 209 dgisselq
//   20171020 -- Added a formal proof to prove that the module works.  This
22
//      also involved adding a req_addr register, and the logic associated
23
//      with it.
24
//
25
//   20171113 -- Removed the req_addr register, replacing it with a bus abort
26
//      capability.
27
//
28 2 dgisselq
// Creator:     Dan Gisselquist, Ph.D.
29 69 dgisselq
//              Gisselquist Technology, LLC
30 2 dgisselq
//
31
////////////////////////////////////////////////////////////////////////////////
32
//
33 209 dgisselq
// Copyright (C) 2015,2017-2019, Gisselquist Technology, LLC
34 2 dgisselq
//
35
// This program is free software (firmware): you can redistribute it and/or
36
// modify it under the terms of  the GNU General Public License as published
37
// by the Free Software Foundation, either version 3 of the License, or (at
38
// your option) any later version.
39
//
40
// This program is distributed in the hope that it will be useful, but WITHOUT
41
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
42
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
43
// for more details.
44
//
45 201 dgisselq
// You should have received a copy of the GNU General Public License along
46
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
47
// target there if the PDF file isn't present.)  If not, see
48
// <http://www.gnu.org/licenses/> for a copy.
49
//
50 2 dgisselq
// License:     GPL, v3, as defined and found on www.gnu.org,
51
//              http://www.gnu.org/licenses/gpl.html
52
//
53
//
54
////////////////////////////////////////////////////////////////////////////////
55
//
56 201 dgisselq
//
57 209 dgisselq
`default_nettype        none
58
//
59
//
60
module  prefetch(i_clk, i_reset, i_new_pc, i_clear_cache, i_stalled_n, i_pc,
61
                        o_insn, o_pc, o_valid, o_illegal,
62 2 dgisselq
                o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data,
63 36 dgisselq
                        i_wb_ack, i_wb_stall, i_wb_err, i_wb_data);
64 209 dgisselq
        parameter               ADDRESS_WIDTH=30, DATA_WIDTH=32;
65
        localparam              AW=ADDRESS_WIDTH,
66
                                DW=DATA_WIDTH;
67
        input   wire                    i_clk, i_reset;
68
        // CPU interaction wires
69
        input   wire                    i_new_pc, i_clear_cache, i_stalled_n;
70
        // We ignore i_pc unless i_new_pc is true as well
71
        input   wire    [(AW+1):0]       i_pc;
72
        output  reg     [(DW-1):0]       o_insn; // Instruction read from WB
73
        output  wire    [(AW+1):0]       o_pc;   // Address of that instruction
74
        output  reg                     o_valid; // If the output is valid
75
        output  reg                     o_illegal; // Result is from a bus err
76 2 dgisselq
        // Wishbone outputs
77 48 dgisselq
        output  reg                     o_wb_cyc, o_wb_stb;
78
        output  wire                    o_wb_we;
79
        output  reg     [(AW-1):0]       o_wb_addr;
80 209 dgisselq
        output  wire    [(DW-1):0]       o_wb_data;
81 2 dgisselq
        // And return inputs
82 209 dgisselq
        input   wire                    i_wb_ack, i_wb_stall, i_wb_err;
83
        input   wire    [(DW-1):0]       i_wb_data;
84 2 dgisselq
 
85 209 dgisselq
        // Declare local variables
86
        reg                     invalid;
87
 
88
        // These are kind of obligatory outputs when dealing with a bus, that
89
        // we'll set them here.  Nothing's going to pay attention to these,
90
        // though, this is primarily for form.
91 2 dgisselq
        assign  o_wb_we = 1'b0;
92
        assign  o_wb_data = 32'h0000;
93
 
94
        // Let's build it simple and upgrade later: For each instruction
95
        // we do one bus cycle to get the instruction.  Later we should
96
        // pipeline this, but for now let's just do one at a time.
97
        initial o_wb_cyc = 1'b0;
98
        initial o_wb_stb = 1'b0;
99
        always @(posedge i_clk)
100 209 dgisselq
        if ((i_reset)||((o_wb_cyc)&&((i_wb_ack)||(i_wb_err))))
101
        begin
102
                // End any bus cycle on a reset, or a return ACK
103
                // or error.
104
                o_wb_cyc <= 1'b0;
105
                o_wb_stb <= 1'b0;
106
        end else if ((!o_wb_cyc)&&(
107
                        // Start if the last instruction output was
108
                        // accepted, *and* it wasn't a bus error
109
                        // response
110
                        ((i_stalled_n)&&(!o_illegal))
111
                        // Start if the last bus result ended up
112
                        // invalid
113
                        ||(invalid)
114
                        // Start on any request for a new address
115
                        ||(i_new_pc)))
116
        begin
117
                // Initiate a bus transaction
118
                o_wb_cyc <= 1'b1;
119
                o_wb_stb <= 1'b1;
120
        end else if (o_wb_cyc)
121
        begin
122
                // If our request has been accepted, then drop the
123
                // strobe line
124
                if (!i_wb_stall)
125
                        o_wb_stb <= 1'b0;
126
 
127
                // Abort on new-pc
128
                // ... clear_cache  is identical, save that it will
129
                // immediately be followed by a new PC, so we don't
130
                // need to worry about that other than to drop
131
                // CYC and STB here.
132
                if (i_new_pc)
133 2 dgisselq
                begin
134
                        o_wb_cyc <= 1'b0;
135 63 dgisselq
                        o_wb_stb <= 1'b0;
136 2 dgisselq
                end
137 209 dgisselq
        end
138 2 dgisselq
 
139 209 dgisselq
        //
140
        // If during the current bus request, a command came in from the CPU
141
        // that will invalidate the results of that request, then we need to
142
        // keep track of an "invalid" flag to remember that and so squash
143
        // the result.
144
        //
145 205 dgisselq
        initial invalid = 1'b0;
146 2 dgisselq
        always @(posedge i_clk)
147 209 dgisselq
        if ((i_reset)||(!o_wb_cyc))
148
                invalid <= 1'b0;
149
        else if (i_new_pc)
150
                invalid <= 1'b1;
151 205 dgisselq
 
152 209 dgisselq
        // The wishbone request address, o_wb_addr
153
        //
154
        // The rule regarding this address is that it can *only* be changed
155
        // when no bus request is active.  Further, since the CPU is depending
156
        // upon this value to know what "PC" is associated with the instruction
157
        // it is processing, we can't change until either the CPU has accepted
158
        // our result, or it is requesting a new PC (and hence not using the
159
        // output).
160
        //
161
        initial o_wb_addr= 0;
162 205 dgisselq
        always @(posedge i_clk)
163 209 dgisselq
        if (i_new_pc)
164
                o_wb_addr  <= i_pc[AW+1:2];
165
        else if ((o_valid)&&(i_stalled_n)&&(!o_illegal))
166
                o_wb_addr  <= o_wb_addr + 1'b1;
167 205 dgisselq
 
168 209 dgisselq
        // The instruction returned is given by the data returned from the bus.
169 63 dgisselq
        always @(posedge i_clk)
170 209 dgisselq
        if ((o_wb_cyc)&&(i_wb_ack))
171
                o_insn <= i_wb_data;
172 205 dgisselq
 
173 209 dgisselq
        //
174
        // Finally, the flags associated with the prefetch.  The rule is that
175
        // if the output represents a return from the bus, then o_valid needs
176
        // to be true.  o_illegal will be true any time the last bus request
177
        // resulted in an error.  o_illegal is only relevant to the CPU when
178
        // o_valid is also true, hence o_valid will be true even in the case
179
        // of a bus error in our request.
180
        //
181 69 dgisselq
        initial o_valid   = 1'b0;
182
        initial o_illegal = 1'b0;
183
        always @(posedge i_clk)
184 209 dgisselq
        if ((i_reset)||(i_new_pc)||(i_clear_cache))
185
        begin
186
                // On any reset, request for a new PC (i.e. a branch),
187
                // or a request to clear our cache (i.e. the data
188
                // in memory may have changed), we invalidate any
189
                // output.
190
                o_valid   <= 1'b0;
191
                o_illegal <= 1'b0;
192
        end else if ((o_wb_cyc)&&((i_wb_ack)||(i_wb_err)))
193
        begin
194
                // Otherwise, at the end of our bus cycle, the
195
                // answer will be valid.  Well, not quite.  If the
196
                // user requested something mid-cycle (i_new_pc)
197
                // or (i_clear_cache), then we'll have to redo the
198
                // bus request, so we aren't valid.
199
                //
200
                o_valid   <= 1'b1;
201
                o_illegal <= ( i_wb_err);
202
        end else if (i_stalled_n)
203
        begin
204
                // Once the CPU accepts any result we produce, clear
205
                // the valid flag, lest we send two identical
206
                // instructions to the CPU.
207
                //
208
                o_valid <= 1'b0;
209
                //
210
                // o_illegal doesn't change ... that way we don't
211
                // access the bus again until a new address request
212
                // is given to us, via i_new_pc, or we are asked
213
                //  to check again via i_clear_cache
214
                //
215
                // o_illegal <= (!i_stalled_n);
216
        end
217 2 dgisselq
 
218 209 dgisselq
        // The o_pc output shares its value with the (last) wishbone address
219
        assign  o_pc = { o_wb_addr, 2'b00 };
220
 
221
        // Make verilator happy
222
        // verilator lint_off UNUSED
223
        wire    [1:0]    unused;
224
        assign  unused = i_pc[1:0];
225
        // verilator lint_on  UNUSED
226
`ifdef  FORMAL
227
        localparam      F_LGDEPTH=2;
228
        reg     f_past_valid;
229
        wire    [(F_LGDEPTH-1):0]        f_nreqs, f_nacks,
230
                                        f_outstanding;
231
        reg     [(AW-1):0]       f_last_pc;
232
        reg                     f_last_pc_valid;
233
        reg     [(AW-1):0]       f_req_addr;
234
 
235
//
236
//
237
// Generic setup
238
//
239
//
240
`ifdef  PREFETCH
241
`define ASSUME  assume
242
`else
243
`define ASSUME  assert
244
`endif
245
 
246
        // Assume a clock
247
 
248
        // Keep track of a flag telling us whether or not $past()
249
        // will return valid results
250
        initial f_past_valid = 1'b0;
251
        always @(posedge i_clk)
252
                f_past_valid = 1'b1;
253
 
254
        /////////////////////////////////////////////////
255
        //
256
        //
257
        // Assumptions about our inputs
258
        //
259
        //
260
        /////////////////////////////////////////////////
261
 
262
        // Assume we start from a reset condition
263
        initial `ASSUME(i_reset);
264
        always @(*)
265
        if (!f_past_valid)
266
                `ASSUME(i_reset);
267
        // Some things to know from the CPU ... there will always be a
268
        // i_new_pc request following any reset
269
        always @(posedge i_clk)
270
        if ((f_past_valid)&&($past(i_reset)))
271
                `ASSUME(i_new_pc);
272
 
273
        // There will also be a i_new_pc request following any request to clear
274
        // the cache.
275
        always @(posedge i_clk)
276
        if ((f_past_valid)&&($past(i_clear_cache)))
277
                `ASSUME(i_new_pc);
278
 
279
        //
280
        //
281
        // Let's make some assumptions about how long it takes our
282
        // phantom bus and phantom CPU to respond.
283
        //
284
        // These delays need to be long enough to flush out any potential
285
        // errors, yet still short enough that the formal method doesn't
286
        // take forever to solve.
287
        //
288
        localparam      F_CPU_DELAY = 4;
289
        reg     [4:0]    f_cpu_delay;
290
        // First, let's assume that any response from the bus comes back
291
        // within F_WB_DELAY clocks
292
 
293
                // Here's our delay assumption: We'll assume that the
294
        // wishbone will always respond within F_WB_DELAY clock ticks
295
        // of the beginning of any cycle.
296
        //
297
        // This includes both dropping the stall line, as well as
298
        // acknowledging any request.  While this may not be
299
        // a reasonable assumption for a piped master, it should
300
        // work here for us.
301
 
302
        // Count the number of clocks it takes the CPU to respond to our
303
        // instruction.
304
        always @(posedge i_clk)
305
        // If no instruction is ready, then keep our counter at zero
306
        if ((i_reset)||(!o_valid)||(i_stalled_n))
307
                f_cpu_delay <= 0;
308
        else
309
                // Otherwise, count the clocks the CPU takes to respond
310
                f_cpu_delay <= f_cpu_delay + 1'b1;
311
 
312
`ifdef  PREFETCH
313
        // Only *assume* that we are less than F_CPU_DELAY if we are not
314
        // integrated into the CPU
315
        always @(posedge i_clk)
316
                assume(f_cpu_delay < F_CPU_DELAY);
317
`endif
318
 
319
        fwb_master #(.AW(AW), .DW(DW),.F_LGDEPTH(F_LGDEPTH),
320
                        .F_MAX_REQUESTS(1), .F_OPT_SOURCE(1),
321
                        .F_OPT_RMW_BUS_OPTION(0),
322
                        .F_OPT_DISCONTINUOUS(0))
323
                f_wbm(i_clk, i_reset,
324
                        o_wb_cyc, o_wb_stb, o_wb_we, o_wb_addr, o_wb_data, 4'h0,
325
                        i_wb_ack, i_wb_stall, i_wb_data, i_wb_err,
326
                        f_nreqs, f_nacks, f_outstanding);
327
 
328
        /////////////////////////////////////////////////
329
        //
330
        //
331
        // Assertions about our outputs
332
        //
333
        //
334
        /////////////////////////////////////////////////
335
        //
336
        // Assertions about our wishbone control outputs first
337
        // Prefetches don't write
338
        always @(posedge i_clk)
339
        if (o_wb_stb)
340
                assert(!o_wb_we);
341
        always @(posedge i_clk)
342
        if ((f_past_valid)&&($past(f_past_valid))
343
                        &&($past(i_clear_cache,2))
344
                        &&($past(o_wb_cyc,2)))
345
                // Make sure any clear-cache transaction is aborted,
346
                // *and* that no valid instructions get sent to the
347
                // CPU
348
                assert((!$past(o_wb_cyc))||(!o_wb_cyc));
349
 
350
        always @(posedge i_clk)
351
        if ((f_past_valid)&&($past(o_valid))&&(o_valid))
352
                assert(o_wb_addr == $past(o_wb_addr));
353
 
354
        always @(posedge i_clk)
355
        if ((f_past_valid)&&($past(!i_reset))&&($past(invalid)))
356
                assert(o_wb_cyc);
357
 
358
        // Any time the CPU accepts an instruction, assert that on the
359
        // valid line will be low on the next clock
360
        always @(posedge i_clk)
361
        if ((f_past_valid)&&($past(o_valid))&&($past(i_stalled_n)))
362
                assert(!o_valid);
363
 
364
        // Since we only change our output on a response from the bus, we
365
        // need to insist that the item has been read by the CPU before
366
        // we go looking/asking for a next value.
367
        //
368
        // This routine should never be requesting a new instruction when
369
        // one is valid--lest the CPU never accept the old instruction and we
370
        // have nothing to do with the data when the bus request returns.
371
        always @(*)
372
        if (o_wb_cyc)
373
                assert(!o_valid);
374
 
375
        // If we just got a valid instruction from the wishbone, assert that
376
        // the instruction is listed as valid on the next instruction cycle
377
        always @(posedge i_clk)
378
        if ((f_past_valid)&&(!$past(i_reset))
379
                &&($past(o_wb_cyc))
380
                &&($past(!i_clear_cache))
381
                &&($past(i_wb_ack))&&(!$past(i_wb_err)))
382
        begin
383
                if (!invalid)
384
                        assert(o_valid);
385
        end
386
 
387
        always @(posedge i_clk)
388
        if ((f_past_valid)&&($past(i_clear_cache)))
389
                assert(!o_valid);
390
 
391
        always @(posedge i_clk)
392
        if ((f_past_valid)&&($past(f_past_valid))
393
                        &&($past(i_clear_cache,2))
394
                        &&($past(o_wb_cyc,2)))
395
                // Make sure any clear-cache transaction is aborted,
396
                // *and* that no valid instructions get sent to the
397
                // CPU
398
                assert(!o_valid);
399
 
400
        //
401
        // Assertions about our return responses
402
        //
403
        always @(posedge i_clk)
404
        if ((f_past_valid)&&(!$past(i_reset))
405
                        &&(!$past(i_new_pc))&&(!$past(i_clear_cache))
406
                        &&($past(o_valid))&&(!$past(i_stalled_n)))
407
                assert(o_valid == $past(o_valid));
408
 
409
        always @(posedge i_clk)
410
        if ((f_past_valid)&&($past(o_valid))&&(o_valid))
411
        begin
412
                assert($stable(o_pc));
413
                assert($stable(o_insn));
414
                assert($stable(o_illegal));
415
        end
416
 
417
        //
418
        // The o_illegal line is the one we use to remind us not to go
419
        // back and retry the last value if it returned a bus error.  Hence,
420
        // let's assert that this line stays constant any time o_wb_cyc
421
        // is low, and we haven't received any new requests.
422
        always @(posedge i_clk)
423
        if ((f_past_valid)&&(!$past(i_reset))
424
                        &&(!$past(i_new_pc))&&(!$past(i_clear_cache))
425
                        &&($past(!o_wb_cyc)))
426
                assert(o_illegal == $past(o_illegal));
427
 
428
 
429
        //
430
        //
431
        // Let's examine whether or not we "walk" though PC addresses one
432
        // at a time like we expect.
433
        //
434
        initial f_last_pc_valid = 1'b0;
435
        always @(posedge i_clk)
436
        if ((i_reset)||(i_clear_cache)||(i_new_pc)||(invalid))
437
                f_last_pc_valid <= 1'b0;
438
        else if (o_valid)
439
                f_last_pc_valid <= (!o_illegal);
440
 
441
        // initial      f_last_pc = 0;
442
        always @(posedge i_clk)
443
        if (o_valid)
444
                f_last_pc  <= o_pc[AW+1:2];
445
        else if (f_last_pc_valid)
446
                assert(o_pc[AW+1:2] == f_last_pc + 1'b1);
447
 
448
        always @(*)
449
                assert(o_pc[1:0] == 2'b00);
450
 
451
        // If we are producing a new result, and no new-pc or clear cache
452
        // has come through (i.e. f_last_pc_valid is true), then the resulting
453
        // PC should be one more than the last time.
454
        //
455
        // The o_valid && !$past(o_valid) is necessary because f_last_pc_valid
456
        // will be different by the second o_valid.
457
        always @(posedge i_clk)
458
        if ((f_past_valid)&&(o_valid)
459
                        &&(!$past(o_valid))&&(f_last_pc_valid))
460
                assert(o_pc[AW+1:2] == (f_last_pc + 1'b1));
461
 
462
        // Let's also keep track of the address the CPU wants us to return.
463
        // Any time the CPU branches to a new_pc, we'll record that request.
464
        // Likewise, any time an instruction is returned from the bus,
465
        // we'll increment this address so as to automatically walk through
466
        // memory.
467
        //
468
        always @(*)
469
                assume(i_pc[1:0] == 2'b00);
470
        initial f_req_addr = 0;
471
        always @(posedge i_clk)
472
        if (i_new_pc)
473
                f_req_addr <= i_pc[AW+1:2];
474
        else if ((!invalid)&&(o_wb_cyc)&&(i_wb_ack)&&(!i_wb_err))
475
                f_req_addr <= f_req_addr + 1'b1;
476
 
477
        // Let's also keep the formal methods on track.  Any time we are
478
        // requesting a value, it should either be from the req_addr, or if
479
        // not a new value should've come in rendering this one invalid.
480
        always @(posedge i_clk)
481
        if (o_wb_cyc)
482
                assert((invalid)||(f_req_addr == o_wb_addr));
483
        // This isn't good enough for induction, so we'll need to
484
        // constrain this further
485
        else if ((!o_valid)&&(!i_new_pc)&&(!i_reset))
486
                assert(f_req_addr == o_wb_addr);
487
 
488
        // In this version, invalid should only ever be high for one cycle.
489
        // CYC should be high on the cycle following--if ever.
490
        always @(posedge i_clk)
491
        if ((f_past_valid)&&($past(invalid)))
492
                assert(!invalid);
493
 
494
        (* anyconst *) reg      [AW:0]           const_addr;
495
        (* anyconst *) reg      [DW-1:0] const_insn;
496
 
497
        wire    f_this_addr, f_this_pc, f_this_req, f_this_data;
498
        assign  f_this_addr = (o_wb_addr ==   const_addr[AW-1:0]);
499
        assign  f_this_pc   = (o_pc      == { const_addr[AW-1:0], 2'b00 });
500
        assign  f_this_req  = (i_pc      == { const_addr[AW-1:0], 2'b00 });
501
        assign  f_this_data = (i_wb_data ==   const_insn);
502
 
503
        reg     f_addr_pending;
504
        initial f_addr_pending = 1'b0;
505
        always @(posedge i_clk)
506
        if (i_reset)
507
                f_addr_pending <= 1'b0;
508
        else if (!o_wb_cyc)
509
                f_addr_pending <= 1'b0;
510
        else if ((o_wb_stb)&&(f_this_addr))
511
        begin
512
                if ((!i_wb_ack)&&(!i_wb_err))
513
                        f_addr_pending <= 1'b1;
514
        end
515
 
516
        always @(*)
517
        if ((o_wb_stb)&&(f_this_addr)&&(!i_wb_stall))
518
        begin
519
                if (!const_addr[AW])
520
                        assume(!i_wb_err);
521
                else
522
                        assume(!i_wb_ack);
523
                if (i_wb_ack)
524
                        assume(f_this_data);
525
        end else if ((o_wb_cyc)&&(f_addr_pending))
526
        begin
527
                if (!const_addr[AW])
528
                        assume(!i_wb_err);
529
                else
530
                        assume(!i_wb_ack);
531
                if (i_wb_ack)
532
                        assume(f_this_data);
533
        end
534
 
535
        always @(*)
536
        if ((o_valid)&&(f_this_pc)&&(!o_illegal))
537
                assert(o_insn == const_insn);
538
        always @(*)
539
        if ((o_valid)&&(f_this_pc))
540
                assert(o_illegal == const_addr[AW]);
541
 
542
        reg     f_insn_pending;
543
 
544
        initial f_insn_pending = 1'b0;
545
        always @(posedge i_clk)
546
        if (i_reset)
547
                f_insn_pending <= 1'b0;
548
        else if (i_clear_cache)
549
                f_insn_pending <= 1'b0;
550
        else if ((i_new_pc)&&(f_this_req))
551
                f_insn_pending <= 1'b1;
552
        else if ((o_valid)||(i_new_pc))
553
                f_insn_pending <= 1'b0;
554
 
555
        always @(posedge i_clk)
556
        if ((f_past_valid)&&($past(o_wb_cyc))&&(o_wb_cyc)&&(f_insn_pending))
557
                assert(f_this_pc);
558
 
559
        always @(posedge i_clk)
560
        if (((f_past_valid)&&($past(o_wb_cyc))&&($past(f_insn_pending)))
561
                &&(!$past(i_reset))&&(!$past(i_clear_cache))
562
                &&(!$past(i_new_pc)))
563
        begin
564
                if(!o_wb_cyc)
565
                        assert((o_valid)&&(f_this_pc));
566
        end
567
 
568
        always @(posedge i_clk)
569
        if ((f_past_valid)&&(!$past(o_wb_cyc))&&(!o_wb_cyc))
570
                assert(!f_insn_pending);
571
 
572
        always @(posedge i_clk)
573
        if ((f_past_valid)&&($past(o_wb_cyc))&&(o_wb_cyc)&&(f_this_addr))
574
                assert(f_addr_pending);
575
 
576
        always @(posedge i_clk)
577
        if ((f_past_valid)&&($past(o_wb_cyc))&&(f_insn_pending))
578
                assert(f_this_addr);
579
`endif
580 2 dgisselq
endmodule
581 209 dgisselq
//
582
// Usage:       (this)  (mid)   (past)
583
//    Cells     167     230     175
584
//      FDRE     67      97      69
585
//      LUT1      1       1       1
586
//      LUT2      1       3       3
587
//      LUT3     31      63      33
588
//      LUT4      5       3       3
589
//      LUT5      1       3       3
590
//      LUT6      2       1       3
591
//      MUXCY    29      29      31
592
//      XORCY    30      30      32

powered by: WebSVN 2.1.0

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