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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [ex/] [busdelay.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 209 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    busdelay.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     Delay any access to the wishbone bus by a single clock.
8
//
9
//      When the first Zip System would not meet the timing requirements of
10
//      the board it was placed upon, this bus delay was added to help out.
11
//      It may no longer be necessary, having cleaned some other problems up
12
//      first, but it will remain here as a means of alleviating timing
13
//      problems.
14
//
15
//      The specific problem takes place on the stall line: a wishbone master
16
//      *must* know on the first clock whether or not the bus will stall.
17
//
18
//
19
//      After a period of time, I started a new design where the timing
20
//      associated with this original bus clock just wasn't ... fast enough.
21
//      I needed to delay the stall line as well.  A new busdelay was then
22
//      written and debugged whcih delays the stall line.  (I know, you aren't
23
//      supposed to delay the stall line--but what if you *have* to in order
24
//      to meet timing?)  This new logic has been merged in with the old,
25
//      and the DELAY_STALL line can be set to non-zero to use it instead
26
//      of the original logic.  Don't use it if you don't need it: it will
27
//      consume resources and slow your bus down more, but if you do need
28
//      it--don't be afraid to use it.  
29
//
30
//      Both versions of the bus delay will maintain a single access per
31
//      clock when pipelined, they only delay the time between the strobe
32
//      going high and the actual command being accomplished.
33
//
34
//
35
// Creator:     Dan Gisselquist, Ph.D.
36
//              Gisselquist Technology, LLC
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40
// Copyright (C) 2015-2019, Gisselquist Technology, LLC
41
//
42
// This program is free software (firmware): you can redistribute it and/or
43
// modify it under the terms of  the GNU General Public License as published
44
// by the Free Software Foundation, either version 3 of the License, or (at
45
// your option) any later version.
46
//
47
// This program is distributed in the hope that it will be useful, but WITHOUT
48
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
49
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
50
// for more details.
51
//
52
// You should have received a copy of the GNU General Public License along
53
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
54
// target there if the PDF file isn't present.)  If not, see
55
// <http://www.gnu.org/licenses/> for a copy.
56
//
57
// License:     GPL, v3, as defined and found on www.gnu.org,
58
//              http://www.gnu.org/licenses/gpl.html
59
//
60
//
61
////////////////////////////////////////////////////////////////////////////////
62
//
63
//
64
`default_nettype        none
65
//
66
module  busdelay(i_clk, i_reset,
67
                // The input bus
68
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel,
69
                        o_wb_ack, o_wb_stall, o_wb_data, o_wb_err,
70
                // The delayed bus
71
                o_dly_cyc, o_dly_stb, o_dly_we, o_dly_addr,o_dly_data,o_dly_sel,
72
                        i_dly_ack, i_dly_stall, i_dly_data, i_dly_err);
73
        parameter               AW=32, DW=32;
74
        localparam              F_LGDEPTH=4;
75
        parameter        [0:0]    DELAY_STALL = 1;
76
        input   wire                    i_clk, i_reset;
77
        // Input/master bus
78
        input   wire                    i_wb_cyc, i_wb_stb, i_wb_we;
79
        input   wire    [(AW-1):0]       i_wb_addr;
80
        input   wire    [(DW-1):0]       i_wb_data;
81
        input   wire    [(DW/8-1):0]     i_wb_sel;
82
        output  reg                     o_wb_ack;
83
        output  wire                    o_wb_stall;
84
        output  reg     [(DW-1):0]       o_wb_data;
85
        output  reg                     o_wb_err;
86
        // Delayed bus
87
        output  reg                     o_dly_cyc, o_dly_stb, o_dly_we;
88
        output  reg     [(AW-1):0]       o_dly_addr;
89
        output  reg     [(DW-1):0]       o_dly_data;
90
        output  reg     [(DW/8-1):0]     o_dly_sel;
91
        input   wire                    i_dly_ack;
92
        input   wire                    i_dly_stall;
93
        input   wire    [(DW-1):0]       i_dly_data;
94
        input   wire                    i_dly_err;
95
 
96
`ifdef  FORMAL
97
        wire    [2+AW+DW+DW/8-1:0]       f_wpending;
98
`endif
99
 
100
        generate
101
        if (DELAY_STALL != 0)
102
        begin
103
                reg                     r_stb, r_we;
104
                reg     [(AW-1):0]       r_addr;
105
                reg     [(DW-1):0]       r_data;
106
                reg     [(DW/8-1):0]     r_sel;
107
 
108
                initial o_dly_cyc  = 1'b0;
109
                initial o_dly_stb  = 1'b0;
110
                initial o_dly_we   = 1'b0;
111
                initial o_dly_addr = 0;
112
                initial o_dly_data = 0;
113
                initial o_dly_sel  = 0;
114
                initial r_stb      = 1'b0;
115
                initial r_we       = 1'b0;
116
                initial r_addr     = 0;
117
                initial r_data     = 0;
118
                initial r_sel      = 0;
119
                initial o_wb_ack   = 1'b0;
120
                initial o_wb_err   = 1'b0;
121
                always @(posedge i_clk)
122
                begin
123
                        o_dly_cyc <= (i_wb_cyc)&&(!i_reset)&&(!o_wb_err)
124
                                &&((!i_dly_err)||(!o_dly_cyc));
125
 
126
                        if ((!i_dly_stall)||(!o_dly_stb))
127
                        begin
128
                                r_we   <= i_wb_we;
129
                                r_addr <= i_wb_addr;
130
                                r_data <= i_wb_data;
131
                                r_sel  <= i_wb_sel;
132
 
133
                                if (r_stb)
134
                                begin
135
                                        o_dly_we   <= r_we;
136
                                        o_dly_addr <= r_addr;
137
                                        o_dly_data <= r_data;
138
                                        o_dly_sel  <= r_sel;
139
                                        o_dly_stb  <= 1'b1;
140
                                end else begin
141
                                        o_dly_we   <= i_wb_we;
142
                                        o_dly_addr <= i_wb_addr;
143
                                        o_dly_data <= i_wb_data;
144
                                        o_dly_sel  <= i_wb_sel;
145
                                        o_dly_stb  <= i_wb_stb;
146
                                end
147
 
148
                                r_stb <= 1'b0;
149
                        end else if ((!r_stb)&&(!o_wb_stall))
150
                        begin
151
                                r_we   <= i_wb_we;
152
                                r_addr <= i_wb_addr;
153
                                r_data <= i_wb_data;
154
                                r_sel  <= i_wb_sel;
155
                                r_stb  <= i_wb_stb;
156
                        end
157
 
158
                        if ((!i_wb_cyc)||((i_dly_err)&&(o_dly_cyc))||(o_wb_err))
159
                        begin
160
                                o_dly_stb <= 1'b0;
161
                                r_stb <= 1'b0;
162
                        end
163
 
164
                        if ((i_reset)||(!i_wb_cyc)||(o_wb_err))
165
                                o_wb_ack <= 1'b0;
166
                        else
167
                                o_wb_ack  <= (i_dly_ack)&&(o_dly_cyc)&&(!i_dly_err);
168
                        o_wb_data <= i_dly_data;
169
 
170
                        if (!i_wb_cyc)
171
                                o_wb_err <= 1'b0;
172
                        else
173
                                o_wb_err  <= (i_dly_err)&&(o_dly_cyc);
174
 
175
                        if (i_reset)
176
                        begin
177
                                r_stb     <= 0;
178
                                r_we      <= 0;
179
                                o_dly_stb <= 0;
180
                                o_wb_err  <= 0;
181
                                o_wb_ack  <= 0;
182
                        end
183
                end
184
 
185
                assign  o_wb_stall = r_stb;
186
 
187
`ifdef  FORMAL
188
                assign  f_wpending = { r_stb, r_we, r_addr, r_data, r_sel };
189
`endif
190
        end else begin
191
 
192
                initial o_dly_cyc   = 1'b0;
193
                initial o_dly_stb   = 1'b0;
194
                initial o_dly_we    = 1'b0;
195
                initial o_dly_addr  = 0;
196
                initial o_dly_data  = 0;
197
                initial o_dly_sel   = 0;
198
                initial o_wb_ack    = 0;
199
                initial o_wb_err    = 0;
200
 
201
                always @(posedge i_clk)
202
                        if (i_reset)
203
                                o_dly_cyc <= 1'b0;
204
                        else if ((i_dly_err)&&(o_dly_cyc))
205
                                o_dly_cyc <= 1'b0;
206
                        else if ((o_wb_err)&&(i_wb_cyc))
207
                                o_dly_cyc <= 1'b0;
208
                        else
209
                                o_dly_cyc <= i_wb_cyc;
210
 
211
                // Add the i_wb_cyc criteria here, so we can simplify the
212
                // o_wb_stall criteria below, which would otherwise *and*
213
                // these two.
214
                always @(posedge i_clk)
215
                        if (i_reset)
216
                                o_dly_stb <= 1'b0;
217
                        else if ((i_dly_err)&&(o_dly_cyc))
218
                                o_dly_stb <= 1'b0;
219
                        else if ((o_wb_err)&&(i_wb_cyc))
220
                                o_dly_stb <= 1'b0;
221
                        else if (!i_wb_cyc)
222
                                o_dly_stb <= 1'b0;
223
                        else if (!o_wb_stall)
224
                                o_dly_stb <= (i_wb_stb);
225
 
226
                always @(posedge i_clk)
227
                        if (!o_wb_stall)
228
                                o_dly_we  <= i_wb_we;
229
                always @(posedge i_clk)
230
                        if (!o_wb_stall)
231
                                o_dly_addr<= i_wb_addr;
232
                always @(posedge i_clk)
233
                        if (!o_wb_stall)
234
                                o_dly_data <= i_wb_data;
235
                always @(posedge i_clk)
236
                        if (!o_wb_stall)
237
                                o_dly_sel <= i_wb_sel;
238
                always @(posedge i_clk)
239
                        if (i_reset)
240
                                o_wb_ack <= 1'b0;
241
                        else
242
                                o_wb_ack  <= ((i_dly_ack)&&(!i_dly_err)
243
                                        &&(o_dly_cyc)&&(i_wb_cyc))
244
                                        &&(!o_wb_err);
245
                always @(posedge i_clk)
246
                        if (i_reset)
247
                                o_wb_err <= 1'b0;
248
                        else if (!o_dly_cyc)
249
                                o_wb_err <= 1'b0;
250
                        else
251
                                o_wb_err  <= (o_wb_err)||(i_dly_err)&&(i_wb_cyc);
252
                always @(posedge i_clk)
253
                        o_wb_data <= i_dly_data;
254
 
255
                // Our only non-delayed line, yet still really delayed.  Perhaps
256
                // there's a way to register this?
257
                // o_wb_stall <= (i_wb_cyc)&&(i_wb_stb) ... or some such?
258
                // assign o_wb_stall=((i_wb_cyc)&&(i_dly_stall)&&(o_dly_stb));//&&o_cyc
259
                assign  o_wb_stall = (i_dly_stall)&&(o_dly_stb);
260
 
261
`ifdef  FORMAL
262
                // f_wpending isn't used if DELAY_STALL is zero, but we'll give
263
                // it a seemingly useful value anyway--if for no other reason
264
                // than to be sure we set it to the right number of bits
265
                assign  f_wpending = { i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel };
266
`endif
267
        end endgenerate
268
 
269
`ifdef  FORMAL
270
 
271
`ifdef  BUSDELAY
272
`define ASSUME  assume
273
`else
274
`define ASSUME  assert
275
`endif
276
 
277
        reg     f_past_valid;
278
        initial f_past_valid = 1'b0;
279
        always @(posedge i_clk)
280
                f_past_valid <= 1'b1;
281
        initial `ASSUME(i_reset);
282
        always @(*)
283
                if (!f_past_valid)
284
                        `ASSUME(i_reset);
285
 
286
        wire    [(F_LGDEPTH-1):0]        f_wb_nreqs,f_wb_nacks, f_wb_outstanding,
287
                                f_dly_nreqs, f_dly_nacks, f_dly_outstanding;
288
 
289
        localparam      ACK_DELAY = 5,
290
                        STALL_DELAY = 4;
291
        fwb_slave #(.AW(AW), .DW(DW),
292
                        .F_LGDEPTH(F_LGDEPTH),
293
                        .F_MAX_STALL(STALL_DELAY+1),
294
                        .F_MAX_ACK_DELAY(ACK_DELAY+1+2*STALL_DELAY),
295
                        .F_MAX_REQUESTS((1<<F_LGDEPTH)-2),
296
                        .F_OPT_RMW_BUS_OPTION(1),
297
                        .F_OPT_DISCONTINUOUS(1))
298
                f_wbs(i_clk, i_reset,
299
                        i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
300
                                i_wb_sel,
301
                        o_wb_ack, o_wb_stall, o_wb_data, o_wb_err,
302
                        f_wb_nreqs, f_wb_nacks, f_wb_outstanding);
303
 
304
        fwb_master #(.AW(AW), .DW(DW),
305
                        .F_LGDEPTH(F_LGDEPTH),
306
                        .F_MAX_STALL(STALL_DELAY),
307
                        .F_MAX_ACK_DELAY(ACK_DELAY),
308
                        .F_MAX_REQUESTS(0),
309
                        .F_OPT_RMW_BUS_OPTION(1),
310
                        .F_OPT_DISCONTINUOUS(1))
311
                f_wbm(i_clk, i_reset,
312
                        o_dly_cyc, o_dly_stb, o_dly_we, o_dly_addr, o_dly_data,
313
                                o_dly_sel,
314
                        i_dly_ack, i_dly_stall, i_dly_data, i_dly_err,
315
                        f_dly_nreqs, f_dly_nacks, f_dly_outstanding);
316
 
317
        wire    [2+AW+DW+DW/8-1:0]       f_wb_request, f_dly_request;
318
        assign  f_wb_request = { i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel };
319
        assign  f_dly_request={ o_dly_stb,o_dly_we,o_dly_addr,o_dly_data,o_dly_sel };
320
 
321
        localparam      STB_BIT = 2+AW+DW+DW/8-1;
322
        reg     [2+AW+DW+DW/8-1:0]       f_pending;
323
        initial f_pending = 0;
324
        always @(posedge i_clk)
325
        if (!DELAY_STALL)
326
                f_pending = 0;
327
        else if ((i_reset)||(!i_wb_cyc)||(i_dly_err))
328
                f_pending[STB_BIT] <= 1'b0;
329
        else if ((i_wb_stb)&&(!o_wb_stall))
330
        begin
331
                f_pending <= f_wb_request;
332
 
333
                if ((!i_dly_stall)||(!o_dly_stb))
334
                        f_pending[STB_BIT] <= 1'b0;
335
 
336
        end else if ((!i_dly_stall)&&(f_pending[STB_BIT]))
337
                f_pending[STB_BIT] <= 1'b0;
338
 
339
        wire    f_wb_busy, f_dly_busy, f_wb_req, f_dly_req;
340
        assign  f_wb_busy  = (i_wb_stb)&&(o_wb_stall);
341
        assign  f_dly_busy = (o_dly_stb)&&(i_dly_stall);
342
        assign  f_wb_req   = (i_wb_stb)&&(!o_wb_stall);
343
        assign  f_dly_req  = (o_dly_stb)&&(!i_dly_stall);
344
        always @(posedge i_clk)
345
        if (!DELAY_STALL)
346
        begin
347
                if ((f_past_valid)&&($past(f_wb_req))&&(!$past(i_reset))
348
                                &&(!$past(o_wb_err))&&(!o_wb_err))
349
                        assert(($past(f_wb_request) == f_dly_request));
350
                if ((f_past_valid)&&($past(i_reset)))
351
                        assert(!o_dly_stb);
352
                if ((f_past_valid)&&(!$past(i_wb_cyc)))
353
                        assert(!o_dly_stb);
354
                if ((o_dly_stb)&&(i_dly_stall))
355
                        assert(o_wb_stall);
356
        end else if ((DELAY_STALL)&&(f_past_valid))
357
        begin
358
                if ($past(i_reset))
359
                        assert(!f_pending[STB_BIT]);
360
                if (!$past(f_dly_busy))
361
                        assert(!f_pending[STB_BIT]);
362
                //
363
                if (($past(i_reset))||($past(i_dly_err)))
364
                begin
365
                        assert(!f_pending[STB_BIT]);
366
                end else if ($past(f_wb_req))
367
                begin
368
                        if ($past(f_dly_busy))
369
                                assert($past(f_wb_request) == f_pending);
370
                end else if ((!$past(i_dly_stall))&&($past(f_pending[STB_BIT]))
371
                                &&($past(i_wb_cyc)))
372
                begin
373
                        assert(f_dly_request == $past(f_pending));
374
                end
375
        end
376
 
377
        // Constrain the induction solver: whatever's in our f_pending
378
        // hold register should be identical to whatever is in the f_wpending
379
        // wires above.
380
        always @(posedge i_clk)
381
                if ((DELAY_STALL)&&(f_past_valid)&&(!$past(i_reset)))
382
                begin
383
                        if (!$past(i_wb_cyc))
384
                                assert((!f_pending[STB_BIT])
385
                                        &&(!f_wpending[STB_BIT]));
386
                        else if (($past(f_dly_busy))&&($past(f_wb_busy)))
387
                                assert(f_pending == f_wpending);
388
                        else if(($past(f_dly_busy))&&($past(f_pending[STB_BIT])))
389
                                assert(f_pending == f_wpending);
390
                end
391
 
392
        always @(posedge i_clk)
393
                if ((!DELAY_STALL)&&(f_past_valid)&&(!$past(i_reset))
394
                                &&($past(i_wb_stb))&&(!$past(o_wb_stall))
395
                                &&(!$past(o_wb_err))&&(!o_wb_err))
396
                        assert(f_dly_request == $past(f_wb_request));
397
 
398
        always @(posedge i_clk)
399
                if ((DELAY_STALL)&&(!i_reset)&&(!o_wb_err))
400
                        assert(f_pending[STB_BIT] == f_wpending[STB_BIT]);
401
 
402
        // Upon any request at the input, there should always be a request
403
        // on the output at the very next clock
404
        always @(posedge i_clk)
405
                if ((f_past_valid)&&($past(i_wb_stb))&&(i_wb_cyc))
406
                        assert((o_dly_stb)||(o_wb_err));
407
 
408
        // Following any dropping of CYC or raising of RESET, STB should
409
        // go down as well
410
        always @(posedge i_clk)
411
                if ((f_past_valid)&&(($past(!i_wb_cyc))||($past(i_reset))))
412
                        assert(!o_dly_stb);
413
 
414
        always @(posedge i_clk)
415
                if ((DELAY_STALL)&&(f_past_valid)
416
                                &&(!$past(i_reset))
417
                                &&($past(i_wb_cyc))
418
                                &&($past(f_pending[STB_BIT])))
419
                begin
420
                        if ($past(i_dly_err))
421
                                assert(!o_dly_stb);
422
                        else
423
                                assert(o_dly_stb);
424
                end
425
 
426
 
427
        // Make sure we get no more than one ack per request
428
        reg     [(F_LGDEPTH-1):0]        f_pending_acks;
429
        always @(*)
430
        if (DELAY_STALL)
431
        begin
432
                f_pending_acks <= 0;
433
                if ((f_past_valid)
434
                        &&((o_wb_err)||(o_wb_ack))
435
                        &&(o_dly_cyc))
436
                        f_pending_acks <= 1;
437
        end else
438
                f_pending_acks <= (((o_wb_ack)||(o_wb_err)) ? 1:0);
439
 
440
        reg     [(F_LGDEPTH-1):0]         f_pending_reqs;
441
        always @(*)
442
        if (DELAY_STALL)
443
        begin
444
                f_pending_reqs <= ((o_dly_stb) ? 1:0)
445
                        + ((f_pending[STB_BIT]) ? 1:0);
446
        end else begin
447
                f_pending_reqs <= (!f_past_valid) ? 0 :
448
                        ((o_dly_stb) ? 1:0);
449
        end
450
 
451
        reg     [(F_LGDEPTH-1):0]        f_expected, f_exp_nreqs, f_exp_nacks;
452
        always @(*)
453
                f_expected <= f_dly_outstanding + f_pending_reqs+f_pending_acks;
454
        always @(*)
455
                f_exp_nreqs<= f_dly_nreqs + f_pending_reqs;
456
        always @(*)
457
                f_exp_nacks<= f_dly_nacks - f_pending_acks;
458
        always @(*)
459
        if (i_wb_cyc)
460
                assert(f_dly_outstanding <= f_wb_outstanding);
461
 
462
        always @(posedge i_clk)
463
                if ((!i_reset)&&(i_wb_cyc)&&(o_dly_cyc)&&(!i_dly_err))
464
                        assert(f_expected == f_wb_outstanding);
465
 
466
        always @(posedge i_clk)
467
        if ((i_wb_cyc)&&(o_dly_cyc)&&(!i_reset)&&(!i_dly_err))
468
        begin
469
                assert(f_exp_nreqs == f_wb_nreqs);
470
                assert(f_exp_nacks == f_wb_nacks);
471
        end
472
`endif
473
endmodule

powered by: WebSVN 2.1.0

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