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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [rtl/] [peripherals/] [zipmmu.v] - Blame information for rev 209

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 201 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    zipmmu.v
4
//
5
// Project:     Zip CPU backend for the GNU Compiler Collection
6
//
7
// Purpose:     To provide a "bump-in-the-line" wishbone memory management
8
//              unit, that is configured from one wishbone bus and modifies a
9
//      separate wishbone bus.  Both busses will not be active at the same time.
10
//
11 209 dgisselq
//      The idea is that the CPU can use one portion of its peripheral
12 201 dgisselq
//      system memory space to configure the MMU, and another portion of its
13
//      memory space to access the MMU.  Even more, configuring the MMU is to
14
//      be done when the CPU is in supervisor mode.  This means that all
15
//      high-memory, system-peripheral accesses will be enabled *only* when
16
//      the CPU is in supervisor mode.
17
//
18
//      There is a very specific reason for this design choice: by designing
19
//      the MMU in this fashion, the MMU may then be inluded (or not) at the
20
//      discretion of the individual assembling the ZipSystem (or equivalent)
21
//      module.
22
//
23
// Design Goals:
24
//
25
//      Since we're trying to design this for disadvantaged, limited CPUs,
26
//      we should be able to offer such CPUs only as much MMU as they want.
27
//      Therefore, it should be possible to scale the MMU up and/or down in
28
//      LUT space.
29
//
30
// Memory space:
31
//      1. On access via the memory bus, the MMU should provide for a speed
32
//              going through it such that any access is delayed by only one
33
//              clock cycle.  Further, multiple accesses to the same page
34
//              should not take any longer than the one cycle delay.  Accesses
35
//              to other pages should take a minimum number of clocks.
36 209 dgisselq
//              Accesses from one page to the next, such as from one page to
37 201 dgisselq
//              the next subsequent one, should cost no delays.
38
//
39
//      2. One independent control word to set the current context
40
//
41
//        - When context = 0, virtual page = physical page, page table is an
42
//              unused pass through.
43
//        - When context != 0, MMU translation is active anytime the GIE is
44
//              set.  Pages must match context, as well as virtual address.
45
//
46
//        - Contains 4 RdOnly bits indicating the log address size for the
47
//              machine, offset by 17.  Thus, the build will have an address
48
//              bus of width (lgpage+17), or a memory space of (2^(lgpage+17)).
49
//              Under this formula, the number of valid address bits can range
50
//              from 17 to 32.
51 209 dgisselq
//        -  Contains 4 RdOnly bits indicating log_2 TLB table size.
52 201 dgisselq
//              Size is given by (2^(lgsize)).  I'm considering sizes of 6,7&8
53
//        -  Contains 4 RdOnly bits indicating the log page size, offset by
54
//              eight.  Page sizes are therefore given by (2^(lgpage+8)), and
55
//              the smallest page size is 256 words.
56
//        - Contains 4 RdOnly bits indicating the log context size, offset by 1.
57
//              The number of bits in the context word therefore run from 1 to
58
//              (lgcontext+1)-1, supporting between (2^1)-1=3 and
59
//              (2^16)-1 = 65535 contexts.  (The zero context is not being
60
//              counted here, as it is special.)
61
//
62
//      +------+------+------+------+--------------------+
63
//      |      |      |      |      |                    |
64
//      |  4b  |  4b  |  4b  |  4b  |       16-bit       |
65
//      | LGADR| LGTBL|LGPGSZ|LGCTXT|    Context word    |
66
//      |      |      |      |      |                    |
67
//      +------+------+------+------+--------------------+
68
//
69
//      Supervisor *cannot* have page table entries, since there are no
70
//      interrupts (page faults) allowed in supervisor context.
71
//
72 209 dgisselq
//      To be valid,
73 201 dgisselq
//        Context Size (1..16), NFlags (    4) < Page Size (8-23 bits)
74
//        Page size (8-23 bits)                > NFlags bits (4)
75
//
76
//      Small page sizes, then, mean fewer contexts are possible
77
//
78
//      3. One status word, which contains the address that failed and some
79
//              flags:
80
//
81 209 dgisselq
//      Top Virtual address bits indicate which page ... caused  a problem.
82 201 dgisselq
//              These will be the top N bits of the word, where N is the size
83
//              of the virtual address bits.  (Bits are cleared upon any write.)
84
//
85
//      Flags: (Up to 12 bits, all zeros means no fault.  Bits are cleared upon
86
//              write)
87
//              - 4: Multiple page table matches
88
//              - 2: Attempt to write a read-only page
89
//              - 1: Page not found
90 209 dgisselq
//
91 201 dgisselq
//      3. Two words per active page table entry, accessed through two bus
92
//              addresses.  This word contains:
93
//
94
//        16-bits       Page context
95
//        20-bits       Virtual address
96
//        20-bits       Physical address
97
//                              A physical address of all ones means that the
98
//                              page does not exist, and any attempt to access
99
//                              the virtual address associated with this page
100
//                              should fault.
101
//
102
//      Flags:
103
//         1-bit        Read-only / ~written (user set/read/written)
104
//                              If set, this page will cause a fault on any
105
//                              attempt to write this memory.
106 209 dgisselq
//         1-bit        This page may be executed
107
//         1-bit        Cacheable
108
//                              This is not a hardware page, but a memory page.
109
//                              Therefore, the values within this page may be
110
//                              cached.
111 201 dgisselq
//         1-bit        Accessed
112
//                              This an be used to implement a least-recently
113
//                              used measure.  The hardware will set this value
114
//                              when the page is accessed.  The user can also
115
//                              set or clear this at will.
116
//
117
//              (Loaded flag    Not necessary, just map the physical page to 0)
118
//
119
//      We could equivalently do a 16-bit V&P addresses, for a 28-bit total
120
//      address space, if we didn't want to support the entire 32-bit space.
121
//
122
//
123
//      4. Can read/write this word in two parts:
124
//
125 209 dgisselq
//              (20-bit Virtual )(8-bits lower context)(4-bit flags), and
126 201 dgisselq
//              (20-bit Physical)(8-bits upper context)(4-bit flags)
127
//
128
//              Actual bit lengths will vary as the MMU configuration changes,
129
//              however the flags will always be the low order four bits,
130
//              and the virtual/physical address flags will always consume
131
//              32 bits minus the page table size.  The context bits will
132
//              always be split into upper and lower context bits.  If there
133
//              are more context bits than can fit in the space, then the
134
//              upper bits of the context field will be filled with zeros.
135
//
136
//              On any write, the context bits will be set from the context
137
//              bits in the control register.
138
//
139
//      +----+----+-----+----+----+----+----+--+--+--+--+
140 209 dgisselq
//      |                         | Lower 8b| R| E| C| A|
141
//      |  20-bit Virtual page ID | Context | O| X| C| C|
142
//      |(top 20 bits of the addr)|   ID    | n| E| H| C|
143
//      |                         |         | W| F| E| S|
144 201 dgisselq
//      +----+----+-----+----+----+----+----+--+--+--+--+
145
//
146
//      +----+----+-----+----+----+----+----+--+--+--+--+
147
//      |                         | Upper 8b| R| A| C| T|
148
//      |  20-bit Physical pg ID  | Context | O| C| C| H|
149
//      |(top 20 bits of the      |   ID    | n| C| H| S|
150 209 dgisselq
//      |    physical address)    |         | W| S| E| P|
151 201 dgisselq
//      +----+----+-----+----+----+----+----+--+--+--+--+
152
//
153
//      5. PF Cache--handles words in both physical and virtual
154
//      - On any pf-read, the MMU returns the current pagetable/TBL mapping
155
//              This consists of [Context,Va,Pa].
156
//      - The PF cache stores this with the address tag.  (If the PF is reading,
157
//              the VP should match, only the physical page ID needs to be
158
//              sored ...)
159
//      - At the end of any cache line read, the page table/TBL mapping address
160
//              will have long been available, the "Valid" bit will be turned
161
//              on and associated with the physical mapping.
162
//      - On any data-write (pf doesn't write), MMU sends [Context,Va,Pa]
163 209 dgisselq
//              TLB mapping to the pf-cache.
164 201 dgisselq
//      - If the write matches any physical PF-cache addresses (???), the
165
//              pfcache declares that address line invalid, and just plain
166
//              clears the valid bit for that page.
167
//
168
//      Since the cache lines sizes are smaller than the page table sizes,
169
//      failure to match the address means ... what?
170
//
171
//
172
//      6. Normal operation and timing:
173
//        - One clock lost if still on the same page as last time, or in the
174
//              supervisor (physical pages only) context ...
175
//        - Two clocks (1-more delay) if opening a new page.
176
//              (1-clock to look up the entry--comparing against all entries,
177
//              1-clock to read it, next clock the access goes forward.)
178
//        - No more than two stalls for any access, pipelineable.  Thus, once
179
//              you've stalled by both clocks, you'll not stall again during
180
//              any pipeline operation.
181
//
182
//
183
//
184
// Creator:     Dan Gisselquist, Ph.D.
185
//              Gisselquist Technology, LLC
186
//
187
////////////////////////////////////////////////////////////////////////////////
188
//
189 209 dgisselq
// Copyright (C) 2016-2019, Gisselquist Technology, LLC
190 201 dgisselq
//
191
// This program is free software (firmware): you can redistribute it and/or
192
// modify it under the terms of  the GNU General Public License as published
193
// by the Free Software Foundation, either version 3 of the License, or (at
194
// your option) any later version.
195
//
196
// This program is distributed in the hope that it will be useful, but WITHOUT
197
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
198
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
199
// for more details.
200
//
201
// You should have received a copy of the GNU General Public License along
202
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
203
// target there if the PDF file isn't present.)  If not, see
204
// <http://www.gnu.org/licenses/> for a copy.
205
//
206
// License:     GPL, v3, as defined and found on www.gnu.org,
207
//              http://www.gnu.org/licenses/gpl.html
208
//
209
//
210
////////////////////////////////////////////////////////////////////////////////
211 209 dgisselq
//
212
//
213
`default_nettype        none
214
//
215
`define ROFLAG  3       // Read-only flag
216
`define EXEFLG  2       // No-execute flag (invalid for I-cache)
217
`define CHFLAG  1       // Cachable flag
218
`define AXFLAG  0        // Accessed flag
219
//
220
module zipmmu(i_clk, i_reset, i_wbs_cyc_stb, i_wbs_we, i_wbs_addr,
221
                                i_wbs_data, o_wbs_ack, o_wbs_stall, o_wbs_data,
222
                i_wbm_cyc, i_wbm_stb, i_wbm_we, i_wbm_exe,
223
                        i_wbm_addr, i_wbm_data, i_wbm_sel, i_gie,
224
                o_cyc, o_stb, o_we, o_addr, o_data, o_sel,
225 201 dgisselq
                        i_stall, i_ack, i_err, i_data,
226
                        o_rtn_stall, o_rtn_ack, o_rtn_err,
227
                                o_rtn_miss, o_rtn_data,
228
                pf_return_stb, pf_return_we,
229
                                pf_return_p, pf_return_v,
230
                                pf_return_cachable);
231 209 dgisselq
        parameter       // The size of the address bus.  Actual addressable
232
                        // size will likely be 2^(ADDRESS_WIDTH+2) octets
233
                        ADDRESS_WIDTH=28,
234
                        // Number of page table entries
235
`ifdef  FORMAL
236
                        LGTBL=4'h2,
237
`else
238
                        LGTBL=4'h6,
239
`endif
240
                        // The requested log page size in 8-bit bytes
241
                        PLGPGSZB=20,
242
                        // Number of bits describing context
243
`ifdef  FORMAL
244
                        PLGCTXT=2;
245
`else
246
                        PLGCTXT=16;
247
`endif
248
        parameter [0:0] OPT_DELAY_RETURN = 1'b0;
249 201 dgisselq
        localparam      // And for our derived parameters (don't set these ...)
250 209 dgisselq
                        // Width of the data bus is 32-bits.  This may be hard
251
                        // to change.
252
                        DW = 32,
253 201 dgisselq
                        // AW is just shorthand for the name ADDRESS_WIDTH
254
                        AW = ADDRESS_WIDTH,
255
                        // Page sizes must allow for a minimum of one context
256
                        // bit per page, plus four flag bits, hence the minimum
257
                        // number of bits for an address within a page is 5
258 209 dgisselq
                        LGPGSZB=(PLGPGSZB < 5)? 5:PLGPGSZB,     // in bytes
259
                        LGPGSZW=LGPGSZB-2,                      // in words
260
                        // The context value for a given page can be split
261
                        // across both virtual and physical words.  It cannot
262
                        // have so many bits to it that it takes more bits
263
                        // then are available.
264
                        LGCTXT=((2*LGPGSZB-4)>PLGCTXT)?
265
                                PLGCTXT:(2*LGPGSZB-4),
266 201 dgisselq
                        // LGLCTX is the number of context bits in the low word
267 209 dgisselq
                        LGLCTX=(LGCTXT > (LGPGSZB-4))?(LGPGSZB-4):LGCTXT,
268 201 dgisselq
                        // LGHCTX is the number of context bits in the high word
269 209 dgisselq
                        LGHCTX= (LGCTXT-LGLCTX>0)?(LGCTXT-LGLCTX):0,
270
                        VAW=(DW-LGPGSZB), //  Virtual address width, in bytes
271
                        PAW=(AW-LGPGSZW), // Physical address width, in words
272 201 dgisselq
                        TBL_BITS = LGTBL,       // Bits necessary to addr tbl
273
                        TBL_SIZE=(1<<TBL_BITS);// Number of table entries
274 209 dgisselq
        input   wire            i_clk, i_reset;
275 201 dgisselq
        //
276 209 dgisselq
        input   wire            i_wbs_cyc_stb;
277
        input   wire            i_wbs_we;
278
        input   wire    [(LGTBL+1):0]    i_wbs_addr;
279
        input   wire    [(DW-1):0]       i_wbs_data;
280
        output  reg                     o_wbs_ack;
281
        output  wire                    o_wbs_stall;
282
        output  reg     [(DW-1):0]       o_wbs_data;
283 201 dgisselq
        //
284 209 dgisselq
        input   wire            i_wbm_cyc, i_wbm_stb;
285 201 dgisselq
        //
286 209 dgisselq
        input   wire                    i_wbm_we, i_wbm_exe;
287
        input   wire [(DW-2-1):0]        i_wbm_addr;
288
        input   wire [(DW-1):0]          i_wbm_data;
289
        input   wire [(DW/8-1):0]        i_wbm_sel;
290
        input   wire                    i_gie;
291 201 dgisselq
        //
292
        // Here's where we drive the slave side of the bus
293
        output  reg                     o_cyc;
294
        output  wire                    o_stb, o_we;
295
        output  reg     [(AW-1):0]       o_addr;
296
        output  reg     [(DW-1):0]       o_data;
297 209 dgisselq
        output  reg     [(DW/8-1):0]     o_sel;
298 201 dgisselq
        // and get our return information from driving the slave ...
299 209 dgisselq
        input   wire                    i_stall, i_ack, i_err;
300
        input   wire    [(DW-1):0]       i_data;
301 201 dgisselq
        //
302
        // Here's where we return information on either our slave/control bus
303
        // or the memory bus we are controlled from.  Note that we share these
304
        // wires ...
305
        output  wire            o_rtn_stall;
306 209 dgisselq
        output  wire            o_rtn_ack;
307 201 dgisselq
        output  wire            o_rtn_err, o_rtn_miss;
308 209 dgisselq
        output  wire [(DW-1):0]  o_rtn_data;
309 201 dgisselq
        // Finally, to allow the prefetch to snoop on the MMU conversion ...
310
        output  wire                    pf_return_stb, // snoop data is valid
311
                                        pf_return_we; // snoop data is chnging
312
        output  wire    [(PAW-1):0]      pf_return_p;
313
        output  wire    [(VAW-1):0]      pf_return_v;
314
        output  wire                    pf_return_cachable;
315
        //
316
        //
317
 
318
//
319
//
320
//
321 209 dgisselq
        reg     [3:0]                    tlb_flags       [0:(TBL_SIZE-1)];
322
        wire    [3:0]                    s_tlb_flags;
323 201 dgisselq
        reg     [(LGCTXT-1):0]           tlb_cdata       [0:(TBL_SIZE-1)];
324 209 dgisselq
        reg     [(VAW-1):0]              tlb_vdata       [0:(TBL_SIZE-1)];
325
        reg     [(PAW-1):0]              tlb_pdata       [0:(TBL_SIZE-1)];
326
        reg     [(TBL_SIZE-1):0] tlb_valid, tlb_accessed;
327 201 dgisselq
 
328 209 dgisselq
        wire    adr_control, adr_vtable, adr_ptable;
329
        wire    wr_control, wr_vtable, wr_ptable;
330 201 dgisselq
        wire    [(LGTBL-1):0]    wr_tlb_addr;
331 209 dgisselq
        assign  wr_tlb_addr= i_wbs_addr[(LGTBL):1]; // Leave bottom for V/P
332
        assign  adr_control= (i_wbs_cyc_stb)&&(~i_wbs_addr[(LGTBL+1)])&&(~i_wbs_addr[0]);
333
        assign  adr_vtable = (i_wbs_cyc_stb)&&( i_wbs_addr[(LGTBL+1)])&&(~i_wbs_addr[0]);
334
        assign  adr_ptable = (i_wbs_cyc_stb)&&( i_wbs_addr[(LGTBL+1)])&&( i_wbs_addr[0]);
335
        assign  wr_control = (adr_control)&&(i_wbs_we);
336
        assign  wr_vtable  = (adr_vtable )&&(i_wbs_we);
337
        assign  wr_ptable  = (adr_ptable )&&(i_wbs_we);
338 201 dgisselq
 
339 209 dgisselq
        reg                     z_context;
340
        wire                    kernel_context;
341
        reg     [(LGCTXT-1):0]   r_context_word;
342 201 dgisselq
        //
343 209 dgisselq
        wire    [31:0]           w_control_data, w_ptable_reg;
344
        reg     [31:0]           w_vtable_reg;
345 201 dgisselq
        reg     [31:0]   status_word;
346
        //
347
        //
348 209 dgisselq
        reg                     r_pending, r_we, r_exe, r_valid,
349
                                last_page_valid, last_ro, last_exe;
350
        reg     [(DW-3):0]       r_addr;
351 201 dgisselq
        reg     [(DW-1):0]       r_data;
352 209 dgisselq
        wire    [(VAW-1):0]      vpage;
353
        wire    [AW-LGPGSZW-1:0] ppage;
354
        reg     [(DW/8-1):0]     r_sel;
355 201 dgisselq
        reg     [(PAW-1):0]      last_ppage;
356
        reg     [(VAW-1):0]      last_vpage;
357
        //
358
        wire    [(TBL_SIZE-1):0] r_tlb_match;
359 209 dgisselq
        reg     [(LGTBL-1):0]            s_tlb_addr, last_tlb;
360 201 dgisselq
        reg                             s_tlb_miss, s_tlb_hit, s_pending;
361
        //
362 209 dgisselq
        wire    ro_flag, exe_flag, simple_miss, ro_miss, exe_miss, table_err, cachable;
363
        reg     pf_stb, pf_cachable;
364
        reg     miss_pending;
365 201 dgisselq
        //
366
        reg     rtn_err;
367
 
368
 
369 209 dgisselq
        wire    this_page_valid, pending_page_valid;
370
        assign  this_page_valid = ((last_page_valid)
371
                                &&(i_wbm_addr[(DW-3):(DW-2-VAW)]==last_vpage)
372
                                &&((!last_ro)||(!i_wbm_we))
373
                                &&((!last_exe)||(!i_wbm_exe)));
374
        assign  pending_page_valid = ((s_pending)&&(s_tlb_hit)
375
                                &&((!r_we)||(!ro_flag))
376
                                &&((!r_exe)||(exe_flag)));
377
 
378 201 dgisselq
        //////////////////////////////////////////
379
        //
380
        //
381 209 dgisselq
        // Step one -- handle the control bus--i_wbs_cyc_stb
382 201 dgisselq
        //
383
        //
384
        //////////////////////////////////////////
385
        always @(posedge i_clk)
386
        begin
387
                // Write to the Translation lookaside buffer
388
                if (wr_vtable)
389 209 dgisselq
                        tlb_vdata[wr_tlb_addr]<=i_wbs_data[(DW-1):LGPGSZB];
390 201 dgisselq
                if (wr_ptable)
391 209 dgisselq
                        tlb_pdata[wr_tlb_addr]<=i_wbs_data[(AW+1):LGPGSZB];
392 201 dgisselq
                // Set the context register for the page
393
                if (wr_vtable)
394 209 dgisselq
                        tlb_flags[wr_tlb_addr] <= { i_wbs_data[3:1], 1'b0 };
395
                if (wr_vtable)
396
                        tlb_cdata[wr_tlb_addr][(LGLCTX-1):0]
397
                                <= i_wbs_data[(LGLCTX+4-1):4];
398 201 dgisselq
        end
399 209 dgisselq
 
400
        initial tlb_accessed = 0;
401
        always @(posedge i_clk)
402
        if (i_reset)
403
                tlb_accessed <= 0;
404
        else begin
405
                if (wr_vtable)
406
                        tlb_accessed[wr_tlb_addr] <= 1'b0;
407
                // Otherwise, keep track of the accessed bit if we
408
                // ever access this page
409
                else if ((!kernel_context)&&(pending_page_valid))
410
                        tlb_accessed[s_tlb_addr] <= 1'b1;
411
                else if ((!kernel_context)&&(this_page_valid))
412
                        tlb_accessed[last_tlb] <= 1'b1;
413
        end
414
 
415
        generate if (LGHCTX > 0)
416
        begin : HCTX
417
                always @(posedge i_clk)
418
                if (wr_ptable)
419
                        tlb_cdata[wr_tlb_addr][(LGCTXT-1):LGLCTX]
420
                                <= i_wbs_data[(LGHCTX+4-1):4];
421
        end endgenerate
422
 
423 201 dgisselq
        // Writing to the control word
424
        initial z_context = 1'b1;
425
        initial r_context_word = 0;
426
        always @(posedge i_clk)
427
        if (wr_control)
428
                begin
429 209 dgisselq
                r_context_word <= i_wbs_data[(LGCTXT-1):0];
430
                z_context      <= (i_wbs_data[(LGCTXT-1):0] == {(LGCTXT){1'b0}});
431 201 dgisselq
                end
432 209 dgisselq
        assign  kernel_context = (z_context)||(!i_gie);
433 201 dgisselq
        // Status words cannot be written to
434
 
435 209 dgisselq
        always @(posedge i_clk)
436
        if (i_reset)
437
                tlb_valid <= 0;
438
        else if (wr_ptable)
439
                tlb_valid[wr_tlb_addr]<=1'b1; //(i_wbs_data[(AW+1):LGPGSZB]!=0);
440
 
441
        /* v*rilator lint_off WIDTH */
442
        assign  w_control_data[31:28] = AW[3:0]-4'd1;
443
        assign  w_control_data[27:24] = LGTBL[3:0];
444
        assign  w_control_data[23:20] = LGPGSZB[3:0]-4'd10;
445
        assign  w_control_data[19:16] = LGCTXT[3:0]-1'b1;
446
        /* v*rilator lint_on WIDTH */
447 201 dgisselq
        assign  w_control_data[15: 0] = {{(16-LGCTXT){1'b0}}, r_context_word};
448
        //
449 209 dgisselq
        always @(*)
450
        begin
451
                w_vtable_reg = 0;
452
                w_vtable_reg[(DW-1):LGPGSZB] = tlb_vdata[wr_tlb_addr];
453
                w_vtable_reg[(LGLCTX+4-1):4] = { tlb_cdata[wr_tlb_addr][(LGLCTX-1):0] };
454
                w_vtable_reg[ 3:0]  = { tlb_flags[wr_tlb_addr][3:1],
455
                                        tlb_accessed[wr_tlb_addr] };
456
        end
457 201 dgisselq
        //
458 209 dgisselq
        assign  w_ptable_reg[(DW-1):LGPGSZB] = { {(DW-PAW-LGPGSZB){1'b0}},
459 201 dgisselq
                                        tlb_pdata[wr_tlb_addr] };
460 209 dgisselq
        assign  w_ptable_reg[ 3:0]  = 4'h0;
461 201 dgisselq
        //
462
        generate
463
                if (4+LGHCTX-1>4)
464
                        assign  w_ptable_reg[(4+LGHCTX-1):4] =  {
465
                                tlb_cdata[wr_tlb_addr][(LGCTXT-1):LGLCTX] };
466 209 dgisselq
                if (LGPGSZB > LGLCTX+4)
467
                        assign  w_vtable_reg[(LGPGSZB-1):(LGLCTX+4)] = 0;
468
                if (LGPGSZB > LGHCTX+4)
469
                        assign  w_ptable_reg[(LGPGSZB-1):(LGHCTX+4)] = 0;
470 201 dgisselq
        endgenerate
471
 
472 209 dgisselq
        //
473 201 dgisselq
        // Now, reading from the bus
474 209 dgisselq
        /*
475
        wire    [(LGCTXT-1):0]  w_ctable_reg;
476
        assign  w_ctable_reg = tlb_cdata[wr_tlb_addr];
477
        reg                     setup_this_page_flag;
478
        reg     [(LGCTXT-1):0]  setup_page;
479
        initial setup_this_page_flag = 1'b0;
480 201 dgisselq
        always @(posedge i_clk)
481
                setup_page <= w_ctable_reg;
482
        always @(posedge i_clk)
483 209 dgisselq
                setup_this_page_flag <= (!i_reset)&&(i_wbs_cyc_stb)&&(i_wbs_addr[LGTBL+1]);
484
        */
485 201 dgisselq
 
486
 
487
 
488
        //////////////////////////////////////////
489
        //
490
        //
491
        // Step two -- handle the page lookup on the master bus
492
        //
493
        //
494
        //////////////////////////////////////////
495
 
496
        //
497
        //
498
        // First clock, and the r_ register, copies the bus data from the bus.
499
        // While this increases the bus latency, it also gives us a moment to
500
        // work.
501
        //
502
        //
503 209 dgisselq
        wire    [(VAW-1):0]      r_vpage;
504
        wire    [(PAW-1):0]      r_ppage;
505
        assign  r_vpage = (r_addr[(DW-3):(DW-2-VAW)]);
506
        assign  r_ppage = (o_addr[(AW-1):LGPGSZW]);
507
 
508
        initial s_pending = 1'b0;
509 201 dgisselq
        initial r_pending = 1'b0;
510
        initial r_valid   = 1'b0;
511
        always @(posedge i_clk)
512 209 dgisselq
        if (i_reset)
513 201 dgisselq
        begin
514 209 dgisselq
                r_pending <= 1'b0;
515
                r_valid   <= 1'b0;
516
                o_addr    <= 0;
517
                r_we      <= 0;
518
                r_exe     <= 0;
519
                r_addr    <= 0;
520
                r_data    <= 0;
521
                r_sel     <= 0;
522
                //
523
                s_pending <= 1'b0;
524
        end else
525
        begin
526 201 dgisselq
                if (!o_rtn_stall)
527
                begin
528 209 dgisselq
                        r_pending <= (i_wbm_stb)&&(!kernel_context)
529
                                                &&(!this_page_valid);
530
                        r_we      <= i_wbm_we;
531
                        r_exe     <= i_wbm_exe;
532
                        o_addr    <= { { (kernel_context)?
533
                                i_wbm_addr[(AW-1):LGPGSZW] : last_ppage },
534
                                i_wbm_addr[(LGPGSZW-1):0] };
535
                        r_addr    <= i_wbm_addr;
536
                        r_data    <= i_wbm_data;
537
                        r_sel     <= i_wbm_sel;
538
                        r_valid   <= (i_wbm_stb)&&((kernel_context)||(this_page_valid));
539 201 dgisselq
                        s_pending <= 1'b0;
540 209 dgisselq
                end else if (!r_valid) begin
541
                        r_valid <= (pending_page_valid);
542
                        o_addr <= { ppage , r_addr[(LGPGSZW-1):0] };
543
                        r_pending<= (r_pending)&&(!pending_page_valid);
544
                        s_pending <=(r_pending)&&(!pending_page_valid);
545 201 dgisselq
                end else begin
546 209 dgisselq
                        r_pending <= 1'b0;
547
                        s_pending <= 1'b0;
548 201 dgisselq
                end
549
 
550 209 dgisselq
                if ((!i_wbm_cyc)||(o_rtn_err)||((o_cyc)&&(i_err)))
551
                begin
552
                        s_pending <= 1'b0;
553 201 dgisselq
                        r_pending <= 1'b0;
554 209 dgisselq
                        r_valid   <= 1'b0;
555
                end
556 201 dgisselq
        end
557 209 dgisselq
 
558
`ifdef  FORMAL
559
        reg     f_past_valid;
560
 
561
        always @(posedge i_clk)
562
        if ((f_past_valid)&&($past(r_pending))&&(r_pending)&&($past(o_rtn_stall))&&(i_wbm_cyc)&&(!o_stb))
563
                assert(s_pending);
564
`endif
565
 
566 201 dgisselq
        // Second clock: know which buffer entry this belong in.
567
        // If we don't already know, then the pipeline must be stalled for a
568
        // while ...
569
        genvar k, s;
570
        generate
571 209 dgisselq
        for(k=0; k<TBL_SIZE; k = k + 1)
572 201 dgisselq
                assign r_tlb_match[k] =
573 209 dgisselq
                        // The page  must be valid
574
                        (tlb_valid[k])
575 201 dgisselq
                        // Virtual address must match
576 209 dgisselq
                        &&(tlb_vdata[k] == r_vpage)
577 201 dgisselq
                        // Context must match as well
578 209 dgisselq
                        &&(tlb_cdata[k][LGCTXT-1:1] == r_context_word[LGCTXT-1:1])
579
                        &&((!tlb_cdata[k][0])||(r_context_word[0]));
580 201 dgisselq
        endgenerate
581
 
582
        initial s_tlb_miss = 1'b0;
583
        initial s_tlb_hit  = 1'b0;
584
        generate
585 209 dgisselq
                integer i;
586 201 dgisselq
        always @(posedge i_clk)
587
        begin // valid when s_ becomes valid
588
                s_tlb_addr <= {(LGTBL){1'b0}};
589 209 dgisselq
                for(i=0; i<TBL_SIZE; i=i+1)
590
                        if (r_tlb_match[i])
591
                                s_tlb_addr <= i[(LGTBL-1):0];
592
                s_tlb_miss <= (r_pending)&&(r_tlb_match == 0);
593 201 dgisselq
                s_tlb_hit <= 1'b0;
594 209 dgisselq
                for(i=0; i<TBL_SIZE; i=i+1)
595
                        if (r_tlb_match == (1<<i))
596
                                s_tlb_hit <= (r_pending)&&(!r_valid)&&(i_wbm_cyc);
597 201 dgisselq
        end endgenerate
598
 
599
        // Third clock: Read from the address the virtual table offset,
600
        // whether read-only, etc.
601 209 dgisselq
        assign  s_tlb_flags = tlb_flags[s_tlb_addr];
602
        assign  ro_flag     = s_tlb_flags[`ROFLAG];
603
        assign  exe_flag    = s_tlb_flags[`EXEFLG];
604
        assign  cachable    = s_tlb_flags[`CHFLAG];
605 201 dgisselq
        assign  simple_miss = (s_pending)&&(s_tlb_miss);
606
        assign  ro_miss     = (s_pending)&&(s_tlb_hit)&&(r_we)&&(ro_flag);
607 209 dgisselq
        assign  exe_miss    = (s_pending)&&(s_tlb_hit)&&(r_exe)&&(!exe_flag);
608 201 dgisselq
        assign  table_err   = (s_pending)&&(!s_tlb_miss)&&(!s_tlb_hit);
609 209 dgisselq
        assign  vpage       = tlb_vdata[s_tlb_addr];
610
        assign  ppage       = tlb_pdata[s_tlb_addr];
611
 
612
        initial pf_cachable = 1'b0;
613
        always @(posedge i_clk)
614
        if (i_reset)
615
                pf_cachable <= 1'b0;
616
        else
617
                pf_cachable <= cachable;
618
 
619 201 dgisselq
        initial pf_stb = 1'b0;
620 209 dgisselq
        initial last_ppage = 0;
621
        initial last_vpage = 0;
622 201 dgisselq
        always @(posedge i_clk)
623 209 dgisselq
        if (i_reset)
624 201 dgisselq
        begin
625 209 dgisselq
                pf_stb <= 1'b0;
626
                last_ppage <= 0;
627
                last_vpage <= 0;
628
                last_tlb   <= 0;
629
        end else if ((!kernel_context)&&(r_pending)&&(!last_page_valid))
630
        begin
631
                last_tlb   <= s_tlb_addr;
632
                last_ppage <= ppage;
633
                last_vpage <= vpage;
634
                last_exe   <= exe_flag;
635
                last_ro    <= ro_flag;
636
                pf_stb <= 1'b1;
637
        end else
638
                pf_stb <= 1'b0;
639 201 dgisselq
 
640 209 dgisselq
        initial status_word = 0;
641
        always @(posedge i_clk)
642
        if (i_reset)
643
                status_word <= 0;
644
        else if (wr_control)
645
                status_word <= 0;
646
        else if ((table_err)||(ro_miss)||(simple_miss)||(exe_miss))
647
                status_word <= { r_vpage,
648
                                {(LGPGSZB-4){1'b0}},
649
                                (table_err), (exe_miss),
650
                                (ro_miss), (simple_miss) };
651 201 dgisselq
 
652 209 dgisselq
        initial last_page_valid = 1'b0;
653
        always @(posedge i_clk)
654
        if (i_reset)
655
                last_page_valid <= 1'b0;
656
        else if ((i_wbs_cyc_stb)&&(i_wbs_we))
657
                last_page_valid <= 1'b0;
658
        else if (!kernel_context)
659
        begin
660
                if (!o_rtn_stall)
661
                        // A new bus request
662
                        last_page_valid <= (last_page_valid)
663
                                &&(i_wbm_addr[(DW-3):(DW-2-VAW)] == last_vpage);
664
                else if ((r_pending)&&(!last_page_valid))
665
                        last_page_valid <= (s_pending)&&(s_tlb_hit);
666 201 dgisselq
        end
667
 
668 209 dgisselq
        parameter       LGFIFO = 6;
669
        reg     [LGFIFO-1:0]     bus_outstanding;
670
        initial bus_outstanding = 0;
671
        always @(posedge i_clk)
672
        if (i_reset)
673
                bus_outstanding <= 0;
674
        else if (!o_cyc)
675
                bus_outstanding <= 0;
676
        else case({ (o_stb)&&(!i_stall), (i_ack)||(i_err) } )
677
        2'b01: bus_outstanding <= bus_outstanding - 1'b1;
678
        2'b10: bus_outstanding <= bus_outstanding + 1'b1;
679
        default: begin end
680
        endcase
681
 
682
        reg     bus_pending;
683
        initial bus_pending = 0;
684
        always @(posedge i_clk)
685
        if (i_reset)
686
                bus_pending <= 0;
687
        else if (!o_cyc)
688
                bus_pending <= 1'b0;
689
        else case({ (o_stb)&&(!i_stall), ((i_ack)||(i_err)) })
690
        2'b01: bus_pending <= (bus_outstanding > 1);
691
        2'b10: bus_pending <= 1'b1;
692
        default: begin end
693
        endcase
694
 
695 201 dgisselq
        initial rtn_err = 1'b0;
696 209 dgisselq
        initial o_cyc   = 1'b0;
697 201 dgisselq
        always @(posedge i_clk)
698 209 dgisselq
        if (i_reset)
699 201 dgisselq
        begin
700 209 dgisselq
                o_cyc <= 1'b0;
701
                rtn_err   <= 1'b0;
702
        end else begin
703
                o_cyc <=  (i_wbm_cyc)&&(!o_rtn_err)&&((!i_err)||(!o_cyc)); /// &&((o_cyc)||(r_valid));
704 201 dgisselq
 
705 209 dgisselq
                rtn_err  <= (i_wbm_cyc)&&(i_err)&&(o_cyc);
706 201 dgisselq
        end
707 209 dgisselq
 
708
        generate if (OPT_DELAY_RETURN)
709
        begin
710
                reg             r_rtn_ack;
711
                reg     [31:0]   r_rtn_data;
712
 
713
                initial r_rtn_data = 0;
714
                initial r_rtn_ack  = 0;
715
                always @(posedge i_clk)
716
                if (i_reset)
717
                begin
718
                        r_rtn_ack  <= 0;
719
                        r_rtn_data <= 0;
720
                end else begin
721
                        r_rtn_ack  <= (i_wbm_cyc)&&(i_ack)&&(o_cyc);
722
                        r_rtn_data <= i_data;
723
                end
724
 
725
                assign  o_rtn_ack  = r_rtn_ack;
726
                assign  o_rtn_data = r_rtn_data;
727
        end else begin
728
 
729
                assign  o_rtn_ack  = (i_ack)&&(o_cyc);
730
                assign  o_rtn_data = i_data;
731
        end endgenerate
732
 
733 201 dgisselq
        assign  o_stb = (r_valid);
734
        assign  o_we  =  (r_we);
735 209 dgisselq
        assign  o_rtn_stall = (i_wbm_cyc)&&(
736
                        (o_rtn_err)
737
                        ||((r_pending)&&(!r_valid))
738
                        ||((o_stb)&&(i_stall))
739
                        ||(miss_pending));
740 201 dgisselq
 
741 209 dgisselq
        initial miss_pending = 0;
742
        always @(posedge i_clk)
743
        if (i_reset)
744
                miss_pending <= 0;
745
        else if (!i_wbm_cyc)
746
                miss_pending <= 0;
747
        else
748
                miss_pending <= (i_wbm_cyc)&&(
749
                                (simple_miss)||(ro_miss)||(exe_miss)
750
                                ||((s_pending)&&(!s_tlb_miss)&&(!s_tlb_hit)));
751
 
752
        assign  o_rtn_miss  = (miss_pending)&&(!bus_pending);
753
        assign  o_rtn_err   = (rtn_err);
754
 
755
        assign  o_sel  = r_sel;
756 201 dgisselq
        assign  o_data = r_data;
757
 
758
        //
759 209 dgisselq
        assign  o_wbs_stall = 1'b0;
760
        initial o_wbs_ack = 1'b0;
761
        always @(posedge i_clk)
762
        if (i_reset)
763
                o_wbs_ack <= 1'b0;
764
        else
765
                o_wbs_ack <= (i_wbs_cyc_stb);
766
        always @(posedge i_clk)
767
        if (i_reset)
768
                o_wbs_data <= 0;
769
        else case({i_wbs_addr[LGTBL+1],i_wbs_addr[0]})
770
        2'b00: o_wbs_data <= w_control_data;
771
        2'b01: o_wbs_data <= status_word;
772
        2'b10: o_wbs_data <= w_vtable_reg;
773
        2'b11: o_wbs_data <= w_ptable_reg;
774
        endcase
775
 
776
        //
777 201 dgisselq
        // Bus snooping returns ...
778
        //
779
        assign  pf_return_stb = pf_stb;
780
        assign  pf_return_we = r_we;
781
        assign  pf_return_p  = last_ppage;
782
        assign  pf_return_v  = last_vpage;
783
        assign  pf_return_cachable = pf_cachable;
784
 
785 209 dgisselq
        // Also requires being told when/if the page changed
786
        // So, on a page change,
787
        // pf_return_we = 1
788
        // pf_stb = 1
789
        // and pf_return_p has the physical address
790
 
791
        // Make verilator happy
792
        // verilator lint_off UNUSED
793
        wire [(PAW-1):0] unused;
794
        assign  unused = r_ppage;
795
        generate if (4+LGCTXT < LGPGSZB)
796
        begin
797
                wire    [LGPGSZB-(4+LGCTXT)-1:0] unused_data;
798
                assign  unused_data = i_wbs_data[LGPGSZB-1:4+LGCTXT];
799
        end endgenerate
800
 
801
        wire    unused_always;
802
        assign  unused_always = s_tlb_flags[0];
803
        // verilator lint_on  UNUSED
804
 
805
`ifdef  FORMAL
806
        initial f_past_valid = 0;
807
        always @(posedge i_clk)
808
                f_past_valid <= 1'b1;
809
 
810
        initial assume(i_reset);
811
        always @(*)
812
                if (!f_past_valid)
813
                        assume(i_reset);
814
 
815
        always @(*)
816
                if (i_reset)
817
                        assume(!i_wbs_cyc_stb);
818
        always @(posedge i_clk)
819
        if (f_past_valid)
820
                assert(o_wbs_ack == $past(i_wbs_cyc_stb));
821
        always @(*)
822
                assert(o_wbs_stall == 1'b0);
823
 
824
        always @(*)
825
                assume((!i_wbm_cyc)||(!i_wbs_cyc_stb));
826
 
827
        localparam      F_LGDEPTH = 6;
828
        reg     [F_LGDEPTH-1:0]  fv_nreqs, fv_nacks, fv_outstanding,
829
                        fp_nreqs, fp_nacks, fp_outstanding;
830
 
831
        localparam      F_MAX_STALL = 3,
832
                        F_MAX_WAIT  = 2,
833
                        F_MAX_REQ   = 9;
834
 
835
        //
836
        // The stall period needs to be long enough to allow all in-progress
837
        // transactions to complete, as in the case of a page miss.  Hence,
838
        // the max stall amount depends upon the max wait time for the
839
        // physical half of the interaction.  It is artificially limited here
840
        // in order to limit the amount of proof time required.
841
        //
842
        fwb_slave #(.F_MAX_STALL(F_MAX_STALL+(F_MAX_WAIT*F_MAX_REQ)+2),
843
                        .AW(DW-2),
844
                        .F_MAX_ACK_DELAY(F_MAX_STALL+F_MAX_WAIT+5),
845
                        .F_MAX_REQUESTS(F_MAX_REQ),
846
                        .F_LGDEPTH(F_LGDEPTH),
847
                        .F_OPT_MINCLOCK_DELAY(0))
848
                busslave(i_clk, i_reset,
849
                                i_wbm_cyc, i_wbm_stb, i_wbm_we, i_wbm_addr,
850
                                        i_wbm_data, i_wbm_sel,
851
                                o_rtn_ack, o_rtn_stall, o_rtn_data,
852
                                        o_rtn_err|o_rtn_miss,
853
                                fv_nreqs, fv_nacks, fv_outstanding);
854
 
855
        fwb_master #(.F_MAX_STALL(F_MAX_STALL),
856
                        .AW(ADDRESS_WIDTH),
857
                        .F_MAX_ACK_DELAY(F_MAX_WAIT),
858
                        .F_MAX_REQUESTS(F_MAX_REQ),
859
                        .F_LGDEPTH(F_LGDEPTH),
860
                        .F_OPT_MINCLOCK_DELAY(0))
861
                busmaster(i_clk, i_reset,
862
                                o_cyc, o_stb, o_we, o_addr,
863
                                        o_data, o_sel,
864
                                i_ack, i_stall, i_data, i_err,
865
                                fp_nreqs, fp_nacks, fp_outstanding);
866
 
867
        always @(*)
868
                assert((!o_cyc)||(fp_outstanding == bus_outstanding));
869
 
870
        always @(*)
871
                assume(fv_nreqs < F_MAX_REQ);
872
        always @(*)
873
        if ((i_wbm_cyc)&&(o_cyc)&&(fv_outstanding == fp_outstanding))
874
                assert(fv_nreqs == fp_nreqs);
875
        always @(*)
876
        if ((i_wbm_cyc)&&(o_cyc))
877
        begin
878
                assert(fp_nreqs <= fv_nreqs);
879
                assert(fp_nacks >= fv_nacks);
880
        end
881
 
882
        reg     [F_LGDEPTH-1:0]  f_expected, f_ex_nreqs, f_ex_nacks;
883
        always @(*)
884
        if (!i_wbm_cyc)
885
        begin
886
                f_ex_nreqs <= 0;
887
                f_ex_nacks <= 0;
888
                f_expected <= 0;
889
        end else if (OPT_DELAY_RETURN)
890
        begin
891
                if (r_pending)
892
                begin
893
                        f_ex_nreqs <= fp_nreqs + 1'b1;
894
                        f_ex_nacks <= fp_nacks + o_rtn_ack;
895
                        f_expected <= fp_outstanding + 1'b1
896
                                                + o_rtn_ack;
897
                end else begin
898
                        f_expected <= fp_outstanding + (o_stb)
899
                                + (o_rtn_ack);
900
                        f_ex_nreqs <= fp_nreqs + o_stb;
901
                        f_ex_nacks <= fp_nacks + o_rtn_ack;
902
                end
903
        end else begin
904
                if (r_pending)
905
                begin
906
                        f_ex_nreqs <= fp_nreqs + 1'b1;
907
                        f_ex_nacks <= fp_nacks;
908
                        f_expected <= fp_outstanding + 1'b1;
909
                end else begin
910
                        f_ex_nreqs <= fp_nreqs + o_stb;
911
                        f_ex_nacks <= fp_nacks;
912
                        f_expected <= fp_outstanding + (o_stb);
913
                end
914
        end
915
 
916
        reg     f_kill_input;
917
        initial f_kill_input = 1'b0;
918
        always @(posedge i_clk)
919
                f_kill_input <= (i_wbm_cyc)&&(
920
                        (i_reset)
921
                        ||(o_rtn_miss)
922
                        ||(o_rtn_err));
923
        always @(*)
924
                if (f_kill_input)
925
                        assume(!i_wbm_cyc);
926
 
927
        always @(posedge i_clk)
928
        if ((f_past_valid)&&($past(o_rtn_miss))&&($past(i_wbm_cyc)))
929
        begin
930
                assume(!o_cyc);
931
                assume(!i_wbm_cyc);
932
        end
933
 
934
        wire    fv_is_one, fp_is_zero;
935
        assign  fv_is_one  = (fv_outstanding == 1);
936
        assign  fp_is_zero = (fp_outstanding == 0);
937
        always @(*)
938
        if ((i_wbm_cyc)&&(o_cyc))
939
        begin
940
                if (o_rtn_miss)
941
                begin
942
                        assert(fp_outstanding == 0);
943
                        assert(fv_outstanding == 1);
944
                        assert(fv_is_one);
945
                        assert(fp_is_zero);
946
                end else begin
947
                        assert(fv_nreqs == f_ex_nreqs);
948
                        assert(fv_nacks == f_ex_nacks);
949
                        assert(fv_outstanding >= fp_outstanding);
950
                        assert(fv_outstanding == f_expected);
951
                end
952
        end
953
 
954
        always @(*)
955
                assert(z_context == (r_context_word == 0));
956
        always @(*)
957
                assert(kernel_context == ( ((r_context_word == 0)||(!i_gie)) ? 1'b1 : 1'b0));
958
        always @(posedge i_clk)
959
        if ((f_past_valid)&&($past(i_wbs_cyc_stb)))
960
                assume(!i_wbm_cyc);
961
        always @(*)
962
        if (o_wbs_ack)
963
                assume(!i_wbm_cyc);
964
 
965
        always @(*)
966
                assert((!i_wbm_cyc)||(!o_wbs_ack));
967
        always @(posedge i_clk)
968
        if ((f_past_valid)&&(r_pending)&&($past(kernel_context))
969
                        &&($past(i_wbm_stb))&&(!$past(i_stall))&&(i_wbm_cyc)
970
                        &&(!o_rtn_stall))
971
                assert(o_addr[(AW-1):0] == $past(i_wbm_addr[(AW-1):0]));
972
        always @(*)
973
                assert(bus_pending == (bus_outstanding > 0));
974
 
975
        always @(*)
976
        if ((s_pending)&&(!s_tlb_miss))
977
                assert(r_tlb_match[s_tlb_addr]);
978
 
979
        // Check out all of the criteria which should clear these flags
980
        always @(posedge i_clk)
981
        if ((f_past_valid)&&(($past(i_reset))
982
                        ||(!$past(i_wbm_cyc))
983
                        ||(!$past(o_rtn_stall))))
984
        begin
985
                assert(!simple_miss);
986
                assert(!ro_miss);
987
                assert(!exe_miss);
988
                assert(!table_err);
989
                if (!$past(i_wbm_we))
990
                        assert(!ro_miss);
991
 
992
                if (!kernel_context)
993
                begin
994
                        assert((!o_stb)||(!(simple_miss|ro_miss|table_err)));
995
                        // This doesn't belong on the clear list, but on the
996
                        // should be set list
997
                        // assert((!o_stb)||(!s_tlb_hit));
998
                end
999
        end
1000
 
1001
        always @(posedge i_clk)
1002
        if ((f_past_valid)&&(!$past(i_reset))&&($past(i_wbm_cyc))
1003
                        &&(!$past(o_rtn_stall)))
1004
        begin
1005
                if ((!$past(kernel_context))&&(o_stb))
1006
                        assert((last_page_valid)||(s_tlb_hit));
1007
        end
1008
 
1009
        reg     [(LGTBL-1):0]            f_last_page;
1010
        always @(posedge i_clk)
1011
        if ((f_past_valid)&&(!kernel_context)&&(r_pending)&&(!last_page_valid))
1012
                f_last_page <= s_tlb_addr;
1013
 
1014
        wire    [3:0]    tlb_flag_last_page;
1015
        assign  tlb_flag_last_page = tlb_flags[f_last_page];
1016
        always @(*)
1017
        if (last_page_valid)
1018
        begin
1019
                assert(tlb_valid[f_last_page]);
1020
                assert(last_tlb   == f_last_page);
1021
                assert(last_ppage == tlb_pdata[f_last_page]);
1022
                assert(last_vpage == tlb_vdata[f_last_page]);
1023
                assert(last_ro    == tlb_flag_last_page[`ROFLAG]);
1024
                assert(last_exe   == tlb_flag_last_page[`EXEFLG]);
1025
                assert(r_context_word[LGCTXT-1:1] == tlb_cdata[f_last_page][LGCTXT-1:1]);
1026
                if (!r_context_word[0])
1027
                        assert(!tlb_cdata[f_last_page][0]);
1028
                assert((!r_context_word[0])||(r_context_word[0]));
1029
        end
1030
 
1031
        always @(posedge i_clk)
1032
        if ((f_past_valid)&&(!$past(i_reset))
1033
                        &&($past(last_page_valid))&&(!$past(kernel_context))
1034
                        &&($past(o_stb))&&($past(i_wbm_cyc)))
1035
                assert(tlb_accessed[$past(last_tlb)]);
1036
 
1037
        always @(posedge i_clk)
1038
        if ((f_past_valid)&&(!$past(i_reset))
1039
                        &&($past(pending_page_valid))&&(!$past(kernel_context))
1040
                        &&($past(o_stb))&&($past(i_wbm_cyc)))
1041
                assert(tlb_accessed[$past(s_tlb_addr)]);
1042
 
1043
        always @(posedge i_clk)
1044
        if ((f_past_valid)&&(!$past(kernel_context))&&(o_stb))
1045
        begin
1046
                assert(last_page_valid);
1047
                assert(r_ppage == last_ppage);
1048
                assert((!last_ro)||(!o_we));
1049
        end
1050
 
1051
        always @(posedge i_clk)
1052
        if ((f_past_valid)&&($past(o_stb))&&(o_stb)&&(i_wbm_cyc))
1053
                assert((last_page_valid)||(kernel_context));
1054
 
1055
        always @(*)
1056
                assert((!s_tlb_hit)||(!s_tlb_miss));
1057
        // always @(*)
1058
        // if ((fp_outstanding > 0)&&(o_cyc)&&(!o_stb)&&(!r_pending)&&(!kernel_context))
1059
                // assert(last_page_valid);
1060
        // always @(*) assume(kernel_context);
1061
        always @(*)
1062
                assume((!i_wbs_cyc_stb)||(!i_gie));
1063
 
1064
        reg     f_past_gie, f_past_wbm_cyc;
1065
 
1066
        initial f_past_gie = 1'b0;
1067
        always @(posedge i_clk)
1068
                f_past_gie <= i_gie;
1069
 
1070
        initial f_past_wbm_cyc = 1'b0;
1071
        always @(posedge i_clk)
1072
                f_past_wbm_cyc <= i_wbm_cyc;
1073
        always @(*)
1074
        if ((f_past_valid)&&(bus_pending))
1075
                assume(i_gie == f_past_gie);
1076
        always @(*)
1077
        if ((f_past_wbm_cyc)&&(i_wbm_cyc))
1078
                assume(i_gie == f_past_gie);
1079
 
1080
        always @(posedge i_clk)
1081
        if ((f_past_valid)&&(i_wbm_cyc)&&($past(i_wbm_cyc)))
1082
                assume(i_gie == $past(i_gie));
1083
        always @(posedge i_clk)
1084
        if ((f_past_valid)&&($past(i_reset)))
1085
                assume(!i_gie);
1086
 
1087
        always @(posedge i_clk)
1088
        if ((f_past_valid)&&(!$past(i_reset))&&($past(i_wbm_cyc))
1089
                        &&($past(!kernel_context))
1090
                        &&($past(r_pending))
1091
                        &&(!$past(last_page_valid)))
1092
        begin
1093
                if (($past(s_tlb_hit))
1094
                                &&(!$past(ro_miss))
1095
                                &&(!$past(exe_miss)))
1096
                begin
1097
                        assert(last_vpage == $past(r_vpage));
1098
                        assert(last_page_valid);
1099
                        assert(!miss_pending);
1100
                        assert(tlb_accessed[s_tlb_addr]);
1101
                end else if (($past(s_tlb_hit))&&($past(ro_miss)))
1102
                begin
1103
                        assert(miss_pending);
1104
                        assert(last_page_valid);
1105
                        assert(status_word[3:0] == 4'h2);
1106
                end else if (($past(s_tlb_hit))&&($past(exe_miss)))
1107
                begin
1108
                        assert(miss_pending);
1109
                        assert(last_page_valid);
1110
                        assert(status_word[3:0] == 4'h4);
1111
                end else if (($past(s_tlb_hit))&&($past(simple_miss)))
1112
                begin
1113
                        assert(miss_pending);
1114
                        assert(last_page_valid);
1115
                        assert(status_word[3:0] == 4'h1);
1116
                end else if (!$past(s_tlb_hit))
1117
                begin
1118
                        assert(!last_page_valid);
1119
                end
1120
        end
1121
 
1122
        always @(*)
1123
                assert((!ro_miss)||(!exe_miss)||(!simple_miss)||(!table_err));
1124
 
1125
        reg     [4:0]    f_tlb_pipe;
1126
 
1127
        initial f_tlb_pipe = 5'h0;
1128
        always @(posedge i_clk)
1129
        if (i_reset)
1130
                f_tlb_pipe <= 5'h0;
1131
        else if ((!r_pending)||(o_stb))
1132
                f_tlb_pipe <= 5'h0;
1133
        else if ((r_pending)&&(!r_valid)&&(!miss_pending))
1134
                f_tlb_pipe <= { f_tlb_pipe[3:0], 1'b1 };
1135
 
1136
        always @(*)
1137
                assert(f_tlb_pipe != 5'h1f);
1138
 
1139
        always @(*) // WE or EXE, never both
1140
        assume((!i_wbm_stb)||(!i_wbm_we)||(!i_wbm_exe));
1141
        always @(posedge i_clk)
1142
        if ((f_past_valid)&&($past(i_wbm_stb))&&($past(o_rtn_stall)))
1143
                assume(i_wbm_exe == $past(i_wbm_exe));
1144
 
1145
        always @(*)
1146
                assert((!r_pending)||(!o_stb));
1147
        always @(*)
1148
                assert((!s_pending)||(!o_stb));
1149
        always @(*)
1150
                assert((!s_pending)||(r_pending));
1151
        always @(posedge i_clk)
1152
        if ((f_past_valid)&&($past(i_wbm_cyc)))
1153
                assume(!i_wbs_cyc_stb);
1154
 
1155
        always @(posedge i_clk)
1156
        if ((f_past_valid)&&(|status_word[3:0])&&(!$past(i_wbm_cyc)))
1157
                assume(!i_gie);
1158
`endif
1159 201 dgisselq
endmodule

powered by: WebSVN 2.1.0

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