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

Subversion Repositories wb2axip

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

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

powered by: WebSVN 2.1.0

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