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

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [bench/] [formal/] [fwb_slave.v] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    fwb_slave.v
4
//
5
// Project:     Zip CPU -- a small, lightweight, RISC CPU soft core
6
//
7
// Purpose:     This file describes the rules of a wishbone interaction from the
8
//              perspective of a wishbone slave.  These formal rules may be used
9
//      with yosys-smtbmc to *prove* that the slave properly handles outgoing
10
//      responses to (assumed correct) incoming requests.
11
//
12
//      This module contains no functional logic.  It is intended for formal
13
//      verification only.  The outputs returned, the number of requests that
14
//      have been made, the number of acknowledgements received, and the number
15
//      of outstanding requests, are designed for further formal verification
16
//      purposes *only*.
17
//
18
//      This file is different from a companion formal_master.v file in that
19
//      assumptions are made about the inputs to the slave: i_wb_cyc,
20
//      i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, and i_wb_sel, while full
21
//      assertions are made about the outputs: o_wb_stall, o_wb_ack, o_wb_data,
22
//      o_wb_err.  In the formal_master.v, assertions are made about the
23
//      master outputs (slave inputs)), and assumptions are made about the
24
//      master inputs (the slave outputs).
25
//
26 16 dgisselq
//      In order to make it easier to compare the slave against the master,
27
//      assumptions with respect to the slave have been marked with the
28
//      `SLAVE_ASSUME macro.  Similarly, assertions the slave would make have
29
//      been marked with `SLAVE_ASSERT.  This allows the master to redefine
30
//      these two macros to be from his perspective, and therefore the
31
//      diffs between the two files actually show true differences, rather
32
//      than just these differences in perspective.
33 10 dgisselq
//
34
//
35
// Creator:     Dan Gisselquist, Ph.D.
36
//              Gisselquist Technology, LLC
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40 16 dgisselq
// Copyright (C) 2017-2018, Gisselquist Technology, LLC
41 10 dgisselq
//
42 16 dgisselq
// This file is part of the pipelined Wishbone to AXI converter project, a
43
// project that contains multiple bus bridging designs and formal bus property
44
// sets.
45 10 dgisselq
//
46 16 dgisselq
// The bus bridge designs and property sets are free RTL designs: you can
47
// redistribute them and/or modify any of them under the terms of the GNU
48
// Lesser General Public License as published by the Free Software Foundation,
49
// either version 3 of the License, or (at your option) any later version.
50 10 dgisselq
//
51 16 dgisselq
// The bus bridge designs and property sets are distributed in the hope that
52
// they will be useful, but WITHOUT ANY WARRANTY; without even the implied
53
// warranty of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54
// GNU Lesser General Public License for more details.
55
//
56
// You should have received a copy of the GNU Lesser General Public License
57
// along with these designs.  (It's in the $(ROOT)/doc directory.  Run make
58
// with no target there if the PDF file isn't present.)  If not, see
59 10 dgisselq
// <http://www.gnu.org/licenses/> for a copy.
60
//
61 16 dgisselq
// License:     LGPL, v3, as defined and found on www.gnu.org,
62
//              http://www.gnu.org/licenses/lgpl.html
63 10 dgisselq
//
64
////////////////////////////////////////////////////////////////////////////////
65
//
66
//
67
`default_nettype none
68
//
69
module  fwb_slave(i_clk, i_reset,
70
                // The Wishbone bus
71
                i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel,
72
                        i_wb_ack, i_wb_stall, i_wb_idata, i_wb_err,
73
                // Some convenience output parameters
74
                f_nreqs, f_nacks, f_outstanding);
75
        parameter               AW=32, DW=32;
76
        parameter               F_MAX_STALL = 0,
77
                                F_MAX_ACK_DELAY = 0;
78
        parameter               F_LGDEPTH = 4;
79
        parameter [(F_LGDEPTH-1):0] F_MAX_REQUESTS = 0;
80
        //
81
        // If true, allow the bus to be kept open when there are no outstanding
82
        // requests.  This is useful for any master that might execute a
83
        // read modify write cycle, such as an atomic add.
84
        parameter [0:0]           F_OPT_RMW_BUS_OPTION = 1;
85
        //
86
        // 
87
        // If true, allow the bus to issue multiple discontinuous requests.
88
        // Unlike F_OPT_RMW_BUS_OPTION, these requests may be issued while other
89
        // requests are outstanding
90
        parameter       [0:0]     F_OPT_DISCONTINUOUS = 0;
91
        //
92
        //
93 16 dgisselq
        // If true, insist that there be a minimum of a single clock delay
94
        // between request and response.  This defaults to off since the
95
        // wishbone specification specifically doesn't require this.  However,
96
        // some interfaces do, so we allow it as an option here.
97
        parameter       [0:0]     F_OPT_MINCLOCK_DELAY = 0;
98
        //
99
        //
100
        //
101 10 dgisselq
        localparam [(F_LGDEPTH-1):0] MAX_OUTSTANDING = {(F_LGDEPTH){1'b1}};
102
        localparam      MAX_DELAY = (F_MAX_STALL > F_MAX_ACK_DELAY)
103
                                ? F_MAX_STALL : F_MAX_ACK_DELAY;
104
        localparam      DLYBITS= (MAX_DELAY < 4) ? 2
105
                                : ((MAX_DELAY <    16) ? 4
106
                                : ((MAX_DELAY <    64) ? 6
107
                                : ((MAX_DELAY <   256) ? 8
108
                                : ((MAX_DELAY <  1024) ? 10
109
                                : ((MAX_DELAY <  4096) ? 12
110
                                : ((MAX_DELAY < 16384) ? 14
111
                                : ((MAX_DELAY < 65536) ? 16
112
                                : 32)))))));
113
        //
114
        input   wire                    i_clk, i_reset;
115
        // Input/master bus
116
        input   wire                    i_wb_cyc, i_wb_stb, i_wb_we;
117
        input   wire    [(AW-1):0]       i_wb_addr;
118
        input   wire    [(DW-1):0]       i_wb_data;
119
        input   wire    [(DW/8-1):0]     i_wb_sel;
120
        //
121
        input   wire                    i_wb_ack;
122
        input   wire                    i_wb_stall;
123
        input   wire    [(DW-1):0]       i_wb_idata;
124
        input   wire                    i_wb_err;
125
        //
126
        output  reg     [(F_LGDEPTH-1):0]        f_nreqs, f_nacks;
127
        output  wire    [(F_LGDEPTH-1):0]        f_outstanding;
128
 
129 16 dgisselq
`define SLAVE_ASSUME    assume
130
`define SLAVE_ASSERT    assert
131 10 dgisselq
        //
132
        // Let's just make sure our parameters are set up right
133
        //
134 16 dgisselq
        initial assert(F_MAX_REQUESTS < {(F_LGDEPTH){1'b1}});
135 10 dgisselq
 
136
        //
137
        // Wrap the request line in a bundle.  The top bit, named STB_BIT,
138
        // is the bit indicating whether the request described by this vector
139
        // is a valid request or not.
140
        //
141
        localparam      STB_BIT = 2+AW+DW+DW/8-1;
142
        wire    [STB_BIT:0]      f_request;
143
        assign  f_request = { i_wb_stb, i_wb_we, i_wb_addr, i_wb_data, i_wb_sel };
144
 
145
        //
146
        // A quick register to be used later to know if the $past() operator
147
        // will yield valid result
148
        reg     f_past_valid;
149
        initial f_past_valid = 1'b0;
150
        always @(posedge i_clk)
151
                f_past_valid <= 1'b1;
152
        always @(*)
153 16 dgisselq
        if (!f_past_valid)
154
                `SLAVE_ASSUME(i_reset);
155 10 dgisselq
        //
156
        //
157
        // Assertions regarding the initial (and reset) state
158
        //
159
        //
160
 
161
        //
162
        // Assume we start from a reset condition
163 16 dgisselq
        initial assert(i_reset);
164
        initial `SLAVE_ASSUME(!i_wb_cyc);
165
        initial `SLAVE_ASSUME(!i_wb_stb);
166 10 dgisselq
        //
167 16 dgisselq
        initial `SLAVE_ASSERT(!i_wb_ack);
168
        initial `SLAVE_ASSERT(!i_wb_err);
169 10 dgisselq
 
170
        always @(posedge i_clk)
171 16 dgisselq
        if ((!f_past_valid)||($past(i_reset)))
172 10 dgisselq
        begin
173 16 dgisselq
                `SLAVE_ASSUME(!i_wb_cyc);
174
                `SLAVE_ASSUME(!i_wb_stb);
175 10 dgisselq
                //
176 16 dgisselq
                `SLAVE_ASSERT(!i_wb_ack);
177
                `SLAVE_ASSERT(!i_wb_err);
178 10 dgisselq
        end
179
 
180 16 dgisselq
        always @(*)
181
        if (!f_past_valid)
182
                `SLAVE_ASSUME(!i_wb_cyc);
183 10 dgisselq
 
184
        //
185
        //
186
        // Bus requests
187
        //
188
        //
189
 
190
        // Following any bus error, the CYC line should be dropped to abort
191
        // the transaction
192
        always @(posedge i_clk)
193
        if ((f_past_valid)&&($past(i_wb_err))&&($past(i_wb_cyc)))
194 16 dgisselq
                `SLAVE_ASSUME(!i_wb_cyc);
195 10 dgisselq
 
196
        // STB can only be true if CYC is also true
197 16 dgisselq
        always @(*)
198
        if (i_wb_stb)
199
                `SLAVE_ASSUME(i_wb_cyc);
200 10 dgisselq
 
201
        // If a request was both outstanding and stalled on the last clock,
202
        // then nothing should change on this clock regarding it.
203
        always @(posedge i_clk)
204
        if ((f_past_valid)&&(!$past(i_reset))&&($past(i_wb_stb))
205
                        &&($past(i_wb_stall))&&(i_wb_cyc))
206
        begin
207 16 dgisselq
                `SLAVE_ASSUME(i_wb_stb);
208
                `SLAVE_ASSUME(i_wb_we   == $past(i_wb_we));
209
                `SLAVE_ASSUME(i_wb_addr == $past(i_wb_addr));
210
                `SLAVE_ASSUME(i_wb_sel  == $past(i_wb_sel));
211
                if (i_wb_we)
212
                        `SLAVE_ASSUME(i_wb_data == $past(i_wb_data));
213 10 dgisselq
        end
214
 
215
        // Within any series of STB/requests, the direction of the request
216
        // may not change.
217
        always @(posedge i_clk)
218 16 dgisselq
        if ((f_past_valid)&&($past(i_wb_stb))&&(i_wb_stb))
219
                `SLAVE_ASSUME(i_wb_we == $past(i_wb_we));
220 10 dgisselq
 
221
 
222
        // Within any given bus cycle, the direction may *only* change when
223
        // there are no further outstanding requests.
224
        always @(posedge i_clk)
225 16 dgisselq
        if ((f_past_valid)&&(f_outstanding > 0))
226
                `SLAVE_ASSUME(i_wb_we == $past(i_wb_we));
227 10 dgisselq
 
228
        // Write requests must also set one (or more) of i_wb_sel
229 16 dgisselq
        // always @(*)
230
        // if ((i_wb_stb)&&(i_wb_we))
231
        //      `SLAVE_ASSUME(|i_wb_sel);
232 10 dgisselq
 
233
 
234
        //
235
        //
236
        // Bus responses
237
        //
238
        //
239
 
240
        // If CYC was low on the last clock, then both ACK and ERR should be
241
        // low on this clock.
242
        always @(posedge i_clk)
243 16 dgisselq
        if ((f_past_valid)&&(!$past(i_wb_cyc))&&(!i_wb_cyc))
244 10 dgisselq
        begin
245 16 dgisselq
                `SLAVE_ASSERT(!i_wb_ack);
246
                `SLAVE_ASSERT(!i_wb_err);
247 10 dgisselq
                // Stall may still be true--such as when we are not
248
                // selected at some arbiter between us and the slave
249
        end
250
 
251 16 dgisselq
        always @(posedge i_clk)
252
        if ((f_past_valid)&&(!$past(i_reset))&&($past(i_wb_cyc))&&(!i_wb_cyc))
253
        begin
254
                if (($past(f_outstanding == 0))
255
                        &&((!$past(i_wb_stb && !i_wb_stall))
256
                                ||($past(i_wb_ack|i_wb_err))))
257
                begin
258
                        `SLAVE_ASSERT(!i_wb_ack);
259
                        `SLAVE_ASSERT(!i_wb_err);
260
                end
261
        end
262
 
263 10 dgisselq
        // ACK and ERR may never both be true at the same time
264
        always @(*)
265 16 dgisselq
                `SLAVE_ASSERT((!i_wb_ack)||(!i_wb_err));
266 10 dgisselq
 
267
        generate if (F_MAX_STALL > 0)
268
        begin : MXSTALL
269
                //
270
                // Assume the slave cannnot stall for more than F_MAX_STALL
271
                // counts.  We'll count this forward any time STB and STALL
272
                // are both true.
273
                //
274
                reg     [(DLYBITS-1):0]          f_stall_count;
275
 
276
                initial f_stall_count = 0;
277
                always @(posedge i_clk)
278 16 dgisselq
                if ((!i_reset)&&(i_wb_stb)&&(i_wb_stall))
279
                        f_stall_count <= f_stall_count + 1'b1;
280
                else
281
                        f_stall_count <= 0;
282
 
283
                always @(*)
284
                if (i_wb_cyc)
285
                        `SLAVE_ASSERT(f_stall_count < F_MAX_STALL);
286 10 dgisselq
        end endgenerate
287
 
288
        generate if (F_MAX_ACK_DELAY > 0)
289
        begin : MXWAIT
290
                //
291
                // Assume the slave will respond within F_MAX_ACK_DELAY cycles,
292
                // counted either from the end of the last request, or from the
293
                // last ACK received
294
                //
295
                reg     [(DLYBITS-1):0]          f_ackwait_count;
296
 
297
                initial f_ackwait_count = 0;
298
                always @(posedge i_clk)
299 16 dgisselq
                if ((!i_reset)&&(i_wb_cyc)&&(!i_wb_stb)
300
                                &&(!i_wb_ack)&&(!i_wb_err)
301
                                &&(f_outstanding > 0))
302
                        f_ackwait_count <= f_ackwait_count + 1'b1;
303
                else
304
                        f_ackwait_count <= 0;
305
 
306
                always @(*)
307
                if ((!i_reset)&&(i_wb_cyc)&&(!i_wb_stb)
308
                                        &&(!i_wb_ack)&&(!i_wb_err)
309
                                        &&(f_outstanding > 0))
310
                        `SLAVE_ASSERT(f_ackwait_count < F_MAX_ACK_DELAY);
311 10 dgisselq
        end endgenerate
312
 
313
        //
314
        // Count the number of requests that have been received
315
        //
316
        initial f_nreqs = 0;
317
        always @(posedge i_clk)
318 16 dgisselq
        if ((i_reset)||(!i_wb_cyc))
319
                f_nreqs <= 0;
320
        else if ((i_wb_stb)&&(!i_wb_stall))
321
                f_nreqs <= f_nreqs + 1'b1;
322 10 dgisselq
 
323
 
324
        //
325
        // Count the number of acknowledgements that have been returned
326
        //
327
        initial f_nacks = 0;
328
        always @(posedge i_clk)
329 16 dgisselq
        if (i_reset)
330
                f_nacks <= 0;
331
        else if (!i_wb_cyc)
332
                f_nacks <= 0;
333
        else if ((i_wb_ack)||(i_wb_err))
334
                f_nacks <= f_nacks + 1'b1;
335 10 dgisselq
 
336
        //
337
        // The number of outstanding requests is the difference between
338
        // the number of requests and the number of acknowledgements
339
        //
340
        assign  f_outstanding = (i_wb_cyc) ? (f_nreqs - f_nacks):0;
341
 
342 16 dgisselq
        always @(*)
343
        if ((i_wb_cyc)&&(F_MAX_REQUESTS > 0))
344
        begin
345
                if (i_wb_stb)
346
                        `SLAVE_ASSUME(f_nreqs < F_MAX_REQUESTS);
347
                else
348
                        `SLAVE_ASSUME(f_nreqs <= F_MAX_REQUESTS);
349
                `SLAVE_ASSERT(f_nacks <= f_nreqs);
350
                assert(f_outstanding < (1<<F_LGDEPTH)-1);
351
        end else
352
                assume(f_outstanding < (1<<F_LGDEPTH)-1);
353 10 dgisselq
 
354 16 dgisselq
        always @(*)
355
        if ((i_wb_cyc)&&(f_outstanding == 0))
356
        begin
357
                // If nothing is outstanding, then there should be
358
                // no acknowledgements ... however, an acknowledgement
359
                // *can* come back on the same clock as the stb is
360
                // going out.
361
                if (F_OPT_MINCLOCK_DELAY)
362 10 dgisselq
                begin
363 16 dgisselq
                        `SLAVE_ASSERT(!i_wb_ack);
364
                        `SLAVE_ASSERT(!i_wb_err);
365
                end else begin
366
                        `SLAVE_ASSERT((!i_wb_ack)||((i_wb_stb)&&(!i_wb_stall)));
367
                        // The same is true of errors.  They may not be
368
                        // created before the request gets through
369
                        `SLAVE_ASSERT((!i_wb_err)||((i_wb_stb)&&(!i_wb_stall)));
370 10 dgisselq
                end
371 16 dgisselq
        end
372 10 dgisselq
 
373
        generate if (!F_OPT_RMW_BUS_OPTION)
374
        begin
375
                // If we aren't waiting for anything, and we aren't issuing
376
                // any requests, then then our transaction is over and we
377
                // should be dropping the CYC line.
378 16 dgisselq
                always @(*)
379
                if (f_outstanding == 0)
380
                        `SLAVE_ASSUME((i_wb_stb)||(!i_wb_cyc));
381 10 dgisselq
                // Not all masters will abide by this restriction.  Some
382
                // masters may wish to implement read-modify-write bus
383
                // interactions.  These masters need to keep CYC high between
384
                // transactions, even though nothing is outstanding.  For
385
                // these busses, turn F_OPT_RMW_BUS_OPTION on.
386
        end endgenerate
387
 
388
        generate if ((!F_OPT_DISCONTINUOUS)&&(!F_OPT_RMW_BUS_OPTION))
389
        begin : INSIST_ON_NO_DISCONTINUOUS_STBS
390
                // Within my own code, once a request begins it goes to
391
                // completion and the CYC line is dropped.  The master
392
                // is not allowed to raise STB again after dropping it.
393
                // Doing so would be a *discontinuous* request.
394
                //
395
                // However, in any RMW scheme, discontinuous requests are
396
                // necessary, and the spec doesn't disallow them.  Hence we
397
                // make this check optional.
398
                always @(posedge i_clk)
399 16 dgisselq
                if ((f_past_valid)&&($past(i_wb_cyc))&&(!$past(i_wb_stb)))
400
                        `SLAVE_ASSUME(!i_wb_stb);
401 10 dgisselq
        end endgenerate
402
 
403
endmodule

powered by: WebSVN 2.1.0

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