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

Subversion Repositories wb2axip

[/] [wb2axip/] [trunk/] [rtl/] [wbm2axisp.v] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3 8 dgisselq
// Filename:    wbm2axisp.v (Wishbone master to AXI slave, pipelined)
4 2 dgisselq
//
5
// Project:     Pipelined Wishbone to AXI converter
6
//
7
// Purpose:     The B4 Wishbone SPEC allows transactions at a speed as fast as
8
//              one per clock.  The AXI bus allows transactions at a speed of
9
//      one read and one write transaction per clock.  These capabilities work
10
//      by allowing requests to take place prior to responses, such that the
11
//      requests might go out at once per clock and take several clocks, and
12
//      the responses may start coming back several clocks later.  In other
13
//      words, both protocols allow multiple transactions to be "in flight" at
14
//      the same time.  Current wishbone to AXI converters, however, handle only
15
//      one transaction at a time: initiating the transaction, and then waiting
16
//      for the transaction to complete before initiating the next.
17
//
18
//      The purpose of this core is to maintain the speed of both busses, while
19
//      transiting from the Wishbone (as master) to the AXI bus (as slave) and
20
//      back again.
21
//
22 8 dgisselq
//      Since the AXI bus allows transactions to be reordered, whereas the
23 2 dgisselq
//      wishbone does not, this core can be configured to reorder return
24
//      transactions as well.
25
//
26
// Creator:     Dan Gisselquist, Ph.D.
27
//              Gisselquist Technology, LLC
28
//
29
////////////////////////////////////////////////////////////////////////////////
30
//
31 16 dgisselq
// Copyright (C) 2016-2019, Gisselquist Technology, LLC
32 2 dgisselq
//
33
// This program is free software (firmware): you can redistribute it and/or
34
// modify it under the terms of  the GNU General Public License as published
35
// by the Free Software Foundation, either version 3 of the License, or (at
36
// your option) any later version.
37
//
38
// This program is distributed in the hope that it will be useful, but WITHOUT
39
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
40
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
41
// for more details.
42
//
43
// You should have received a copy of the GNU General Public License along
44
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
45
// target there if the PDF file isn't present.)  If not, see
46
// <http://www.gnu.org/licenses/> for a copy.
47
//
48
// License:     GPL, v3, as defined and found on www.gnu.org,
49
//              http://www.gnu.org/licenses/gpl.html
50
//
51
//
52
////////////////////////////////////////////////////////////////////////////////
53
//
54
//
55 8 dgisselq
`default_nettype        none
56
//
57 2 dgisselq
module wbm2axisp #(
58 13 dgisselq
        parameter C_AXI_ID_WIDTH        =   3, // The AXI id width used for R&W
59 2 dgisselq
                                             // This is an int between 1-16
60 13 dgisselq
        parameter C_AXI_DATA_WIDTH      = 128,// Width of the AXI R&W data
61
        parameter C_AXI_ADDR_WIDTH      =  28,  // AXI Address width (log wordsize)
62
        parameter DW                    =  32,  // Wishbone data width
63
        parameter AW                    =  26,  // Wishbone address width (log wordsize)
64 16 dgisselq
        parameter [0:0] STRICT_ORDER      = 1     // Reorder, or not? 0 -> Reorder
65 2 dgisselq
        ) (
66 13 dgisselq
        input   wire                    i_clk,  // System clock
67 14 dgisselq
        input   wire                    i_reset,// Reset signal,drives AXI rst
68 2 dgisselq
 
69
// AXI write address channel signals
70 13 dgisselq
        input   wire                    i_axi_awready, // Slave is ready to accept
71 6 dgisselq
        output  reg     [C_AXI_ID_WIDTH-1:0]     o_axi_awid,     // Write ID
72
        output  reg     [C_AXI_ADDR_WIDTH-1:0]   o_axi_awaddr,   // Write address
73 5 dgisselq
        output  wire    [7:0]            o_axi_awlen,    // Write Burst Length
74
        output  wire    [2:0]            o_axi_awsize,   // Write Burst size
75
        output  wire    [1:0]            o_axi_awburst,  // Write Burst type
76 6 dgisselq
        output  wire    [0:0]             o_axi_awlock,   // Write lock type
77 5 dgisselq
        output  wire    [3:0]            o_axi_awcache,  // Write Cache type
78
        output  wire    [2:0]            o_axi_awprot,   // Write Protection type
79
        output  wire    [3:0]            o_axi_awqos,    // Write Quality of Svc
80
        output  reg                     o_axi_awvalid,  // Write address valid
81 8 dgisselq
 
82 2 dgisselq
// AXI write data channel signals
83 13 dgisselq
        input   wire                    i_axi_wready,  // Write data ready
84 5 dgisselq
        output  reg     [C_AXI_DATA_WIDTH-1:0]   o_axi_wdata,    // Write data
85
        output  reg     [C_AXI_DATA_WIDTH/8-1:0] o_axi_wstrb,    // Write strobes
86 13 dgisselq
        output  wire                    o_axi_wlast,    // Last write transaction   
87 5 dgisselq
        output  reg                     o_axi_wvalid,   // Write valid
88 8 dgisselq
 
89 2 dgisselq
// AXI write response channel signals
90 13 dgisselq
        input wire [C_AXI_ID_WIDTH-1:0]  i_axi_bid,      // Response ID
91
        input   wire [1:0]               i_axi_bresp,    // Write response
92
        input   wire                    i_axi_bvalid,  // Write reponse valid
93 5 dgisselq
        output  wire                    o_axi_bready,  // Response ready
94 8 dgisselq
 
95 2 dgisselq
// AXI read address channel signals
96 13 dgisselq
        input   wire                    i_axi_arready,  // Read address ready
97 5 dgisselq
        output  wire    [C_AXI_ID_WIDTH-1:0]     o_axi_arid,     // Read ID
98 6 dgisselq
        output  wire    [C_AXI_ADDR_WIDTH-1:0]   o_axi_araddr,   // Read address
99 5 dgisselq
        output  wire    [7:0]            o_axi_arlen,    // Read Burst Length
100
        output  wire    [2:0]            o_axi_arsize,   // Read Burst size
101
        output  wire    [1:0]            o_axi_arburst,  // Read Burst type
102 6 dgisselq
        output  wire    [0:0]             o_axi_arlock,   // Read lock type
103 5 dgisselq
        output  wire    [3:0]            o_axi_arcache,  // Read Cache type
104
        output  wire    [2:0]            o_axi_arprot,   // Read Protection type
105
        output  wire    [3:0]            o_axi_arqos,    // Read Protection type
106
        output  reg                     o_axi_arvalid,  // Read address valid
107 8 dgisselq
 
108 13 dgisselq
// AXI read data channel signals   
109
        input wire [C_AXI_ID_WIDTH-1:0]  i_axi_rid,     // Response ID
110
        input   wire    [1:0]            i_axi_rresp,   // Read response
111
        input   wire                    i_axi_rvalid,  // Read reponse valid
112
        input wire [C_AXI_DATA_WIDTH-1:0] i_axi_rdata,    // Read data
113
        input   wire                    i_axi_rlast,    // Read last
114 5 dgisselq
        output  wire                    o_axi_rready,  // Read Response ready
115 2 dgisselq
 
116
        // We'll share the clock and the reset
117 13 dgisselq
        input   wire                    i_wb_cyc,
118
        input   wire                    i_wb_stb,
119
        input   wire                    i_wb_we,
120
        input   wire    [(AW-1):0]       i_wb_addr,
121
        input   wire    [(DW-1):0]       i_wb_data,
122
        input   wire    [(DW/8-1):0]     i_wb_sel,
123 3 dgisselq
        output  reg                     o_wb_ack,
124
        output  wire                    o_wb_stall,
125 6 dgisselq
        output  reg     [(DW-1):0]       o_wb_data,
126 3 dgisselq
        output  reg                     o_wb_err
127 2 dgisselq
);
128
 
129
//*****************************************************************************
130
// Parameter declarations
131
//*****************************************************************************
132
 
133 8 dgisselq
        localparam      LG_AXI_DW       = ( C_AXI_DATA_WIDTH ==   8) ? 3
134
                                        : ((C_AXI_DATA_WIDTH ==  16) ? 4
135
                                        : ((C_AXI_DATA_WIDTH ==  32) ? 5
136
                                        : ((C_AXI_DATA_WIDTH ==  64) ? 6
137
                                        : ((C_AXI_DATA_WIDTH == 128) ? 7
138
                                        : 8))));
139 2 dgisselq
 
140 8 dgisselq
        localparam      LG_WB_DW        = ( DW ==   8) ? 3
141
                                        : ((DW ==  16) ? 4
142
                                        : ((DW ==  32) ? 5
143
                                        : ((DW ==  64) ? 6
144
                                        : ((DW == 128) ? 7
145
                                        : 8))));
146
        localparam      LGFIFOLN = C_AXI_ID_WIDTH;
147
        localparam      FIFOLN = (1<<LGFIFOLN);
148
 
149
 
150 2 dgisselq
//*****************************************************************************
151
// Internal register and wire declarations
152
//*****************************************************************************
153
 
154
// Things we're not changing ...
155 8 dgisselq
        assign o_axi_awlen   = 8'h0;    // Burst length is one
156
        assign o_axi_awsize  = 3'b101;  // maximum bytes per burst is 32
157 5 dgisselq
        assign o_axi_awburst = 2'b01;   // Incrementing address (ignored)
158
        assign o_axi_arburst = 2'b01;   // Incrementing address (ignored)
159 6 dgisselq
        assign o_axi_awlock  = 1'b0;    // Normal signaling
160
        assign o_axi_arlock  = 1'b0;    // Normal signaling
161 5 dgisselq
        assign o_axi_awcache = 4'h2;    // Normal: no cache, no buffer
162
        assign o_axi_arcache = 4'h2;    // Normal: no cache, no buffer
163 6 dgisselq
        assign o_axi_awprot  = 3'b010;  // Unpriviledged, unsecure, data access
164
        assign o_axi_arprot  = 3'b010;  // Unpriviledged, unsecure, data access
165 8 dgisselq
        assign o_axi_awqos   = 4'h0;    // Lowest quality of service (unused)
166
        assign o_axi_arqos   = 4'h0;    // Lowest quality of service (unused)
167 2 dgisselq
 
168 16 dgisselq
        reg     wb_mid_cycle, wb_last_cyc_stb, wb_mid_abort, wb_cyc_stb;
169 13 dgisselq
        wire    wb_abort;
170
 
171 2 dgisselq
// Command logic
172 8 dgisselq
// Transaction ID logic
173
        wire    [(LGFIFOLN-1):0] fifo_head;
174
        reg     [(C_AXI_ID_WIDTH-1):0]   transaction_id;
175
 
176
        initial transaction_id = 0;
177
        always @(posedge i_clk)
178 14 dgisselq
        if (i_reset)
179
                transaction_id <= 0;
180
        else if ((i_wb_stb)&&(!o_wb_stall))
181
                transaction_id <= transaction_id + 1'b1;
182 8 dgisselq
 
183
        assign  fifo_head = transaction_id;
184
 
185
        wire    [(DW/8-1):0]                     no_sel;
186
        wire    [(LG_AXI_DW-4):0]        axi_bottom_addr;
187
        assign  no_sel = 0;
188
        assign  axi_bottom_addr = 0;
189
 
190
 
191 2 dgisselq
// Write address logic
192
 
193 8 dgisselq
        initial o_axi_awvalid = 0;
194 2 dgisselq
        always @(posedge i_clk)
195 14 dgisselq
        if (i_reset)
196
                o_axi_awvalid <= 0;
197
        else
198 5 dgisselq
                o_axi_awvalid <= (!o_wb_stall)&&(i_wb_stb)&&(i_wb_we)
199 8 dgisselq
                        ||(o_axi_awvalid)&&(!i_axi_awready);
200 2 dgisselq
 
201 6 dgisselq
        generate
202 8 dgisselq
 
203
        initial o_axi_awid = -1;
204
        always @(posedge i_clk)
205 14 dgisselq
        if (i_reset)
206
                o_axi_awid <= -1;
207
        else if ((i_wb_stb)&&(!o_wb_stall))
208
                o_axi_awid <= transaction_id;
209 8 dgisselq
 
210
        if (C_AXI_DATA_WIDTH == DW)
211 6 dgisselq
        begin
212
                always @(posedge i_clk)
213 14 dgisselq
                if ((i_wb_stb)&&(!o_wb_stall)) // 26 bit address becomes 28 bit ...
214
                        o_axi_awaddr <= { i_wb_addr[AW-1:0], axi_bottom_addr };
215 8 dgisselq
        end else if (C_AXI_DATA_WIDTH / DW == 2)
216 6 dgisselq
        begin
217 8 dgisselq
 
218 6 dgisselq
                always @(posedge i_clk)
219 14 dgisselq
                if ((i_wb_stb)&&(!o_wb_stall)) // 26 bit address becomes 28 bit ...
220
                        o_axi_awaddr <= { i_wb_addr[AW-1:1], axi_bottom_addr };
221 8 dgisselq
 
222
        end else if (C_AXI_DATA_WIDTH / DW == 4)
223
        begin
224
                always @(posedge i_clk)
225 13 dgisselq
                if ((i_wb_stb)&&(!o_wb_stall)) // 26 bit address becomes 28 bit ...
226
                        o_axi_awaddr <= { i_wb_addr[AW-1:2], axi_bottom_addr };
227 6 dgisselq
        end endgenerate
228
 
229 2 dgisselq
 
230
// Read address logic
231 8 dgisselq
        assign  o_axi_arid   = o_axi_awid;
232 5 dgisselq
        assign  o_axi_araddr = o_axi_awaddr;
233
        assign  o_axi_arlen  = o_axi_awlen;
234
        assign  o_axi_arsize = 3'b101;  // maximum bytes per burst is 32
235 8 dgisselq
        initial o_axi_arvalid = 1'b0;
236 2 dgisselq
        always @(posedge i_clk)
237 14 dgisselq
        if (i_reset)
238
                o_axi_arvalid <= 1'b0;
239
        else
240 5 dgisselq
                o_axi_arvalid <= (!o_wb_stall)&&(i_wb_stb)&&(!i_wb_we)
241 8 dgisselq
                        ||(o_axi_arvalid)&&(!i_axi_arready);
242 2 dgisselq
 
243
// Write data logic
244 4 dgisselq
        generate
245 8 dgisselq
        if (C_AXI_DATA_WIDTH == DW)
246 4 dgisselq
        begin
247 8 dgisselq
 
248 4 dgisselq
                always @(posedge i_clk)
249 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall))
250
                                o_axi_wdata <= i_wb_data;
251
 
252 4 dgisselq
                always @(posedge i_clk)
253 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall))
254
                                o_axi_wstrb<= i_wb_sel;
255
 
256
        end else if (C_AXI_DATA_WIDTH/2 == DW)
257
        begin
258
 
259
                always @(posedge i_clk)
260
                        if ((i_wb_stb)&&(!o_wb_stall))
261
                                o_axi_wdata <= { i_wb_data, i_wb_data };
262
 
263
                always @(posedge i_clk)
264
                        if ((i_wb_stb)&&(!o_wb_stall))
265
                        case(i_wb_addr[0])
266
                        1'b0:o_axi_wstrb<={  no_sel,i_wb_sel };
267
                        1'b1:o_axi_wstrb<={i_wb_sel,  no_sel };
268 4 dgisselq
                        endcase
269 8 dgisselq
 
270
        end else if (C_AXI_DATA_WIDTH/4 == DW)
271 4 dgisselq
        begin
272 8 dgisselq
 
273 4 dgisselq
                always @(posedge i_clk)
274 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall))
275
                                o_axi_wdata <= { i_wb_data, i_wb_data, i_wb_data, i_wb_data };
276
 
277 4 dgisselq
                always @(posedge i_clk)
278 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall))
279
                        case(i_wb_addr[1:0])
280
                        2'b00:o_axi_wstrb<={   no_sel,   no_sel,   no_sel, i_wb_sel };
281
                        2'b01:o_axi_wstrb<={   no_sel,   no_sel, i_wb_sel,   no_sel };
282
                        2'b10:o_axi_wstrb<={   no_sel, i_wb_sel,   no_sel,   no_sel };
283
                        2'b11:o_axi_wstrb<={ i_wb_sel,   no_sel,   no_sel,   no_sel };
284
                        endcase
285
 
286 4 dgisselq
        end endgenerate
287
 
288 5 dgisselq
        assign  o_axi_wlast = 1'b1;
289 8 dgisselq
        initial o_axi_wvalid = 0;
290 2 dgisselq
        always @(posedge i_clk)
291 14 dgisselq
        if (i_reset)
292
                o_axi_wvalid <= 0;
293
        else
294 5 dgisselq
                o_axi_wvalid <= ((!o_wb_stall)&&(i_wb_stb)&&(i_wb_we))
295 8 dgisselq
                        ||(o_axi_wvalid)&&(!i_axi_wready);
296 2 dgisselq
 
297 8 dgisselq
        // Read data channel / response logic
298 5 dgisselq
        assign  o_axi_rready = 1'b1;
299
        assign  o_axi_bready = 1'b1;
300 2 dgisselq
 
301 8 dgisselq
        wire    [(LGFIFOLN-1):0] n_fifo_head, nn_fifo_head;
302
        assign  n_fifo_head = fifo_head+1'b1;
303
        assign  nn_fifo_head = { fifo_head[(LGFIFOLN-1):1]+1'b1, fifo_head[0] };
304
 
305
 
306 2 dgisselq
        wire    w_fifo_full;
307 8 dgisselq
        reg     [(LGFIFOLN-1):0] fifo_tail;
308
 
309 2 dgisselq
        generate
310 8 dgisselq
        if (C_AXI_DATA_WIDTH == DW)
311 2 dgisselq
        begin
312 8 dgisselq
                if (STRICT_ORDER == 0)
313
                begin
314
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data [0:(FIFOLN-1)];
315 3 dgisselq
 
316 8 dgisselq
                        always @(posedge i_clk)
317
                                if ((o_axi_rready)&&(i_axi_rvalid))
318
                                        reorder_fifo_data[i_axi_rid] <= i_axi_rdata;
319
                        always @(posedge i_clk)
320
                                o_wb_data <= reorder_fifo_data[fifo_tail];
321
                end else begin
322
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data;
323 6 dgisselq
 
324 8 dgisselq
                        always @(posedge i_clk)
325
                                reorder_fifo_data <= i_axi_rdata;
326
                        always @(posedge i_clk)
327
                                o_wb_data <= reorder_fifo_data;
328
                end
329
        end else if (C_AXI_DATA_WIDTH / DW == 2)
330
        begin
331
                reg             reorder_fifo_addr [0:(FIFOLN-1)];
332
 
333
                reg             low_addr;
334
                always @(posedge i_clk)
335
                        if ((i_wb_stb)&&(!o_wb_stall))
336
                                low_addr <= i_wb_addr[0];
337
                always @(posedge i_clk)
338
                        if ((o_axi_arvalid)&&(i_axi_arready))
339
                                reorder_fifo_addr[o_axi_arid] <= low_addr;
340
 
341
                if (STRICT_ORDER == 0)
342 4 dgisselq
                begin
343 8 dgisselq
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data [0:(FIFOLN-1)];
344 3 dgisselq
 
345 8 dgisselq
                        always @(posedge i_clk)
346
                                if ((o_axi_rready)&&(i_axi_rvalid))
347
                                        reorder_fifo_data[i_axi_rid] <= i_axi_rdata;
348
                        always @(posedge i_clk)
349
                                reorder_fifo_data[i_axi_rid] <= i_axi_rdata;
350
                        always @(posedge i_clk)
351
                        case(reorder_fifo_addr[fifo_tail])
352
                        1'b0: o_wb_data <=reorder_fifo_data[fifo_tail][(  DW-1):    0 ];
353
                        1'b1: o_wb_data <=reorder_fifo_data[fifo_tail][(2*DW-1):(  DW)];
354
                        endcase
355
                end else begin
356
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data;
357 3 dgisselq
 
358 4 dgisselq
                        always @(posedge i_clk)
359 8 dgisselq
                                reorder_fifo_data <= i_axi_rdata;
360 4 dgisselq
                        always @(posedge i_clk)
361 8 dgisselq
                        case(reorder_fifo_addr[fifo_tail])
362
                        1'b0: o_wb_data <=reorder_fifo_data[(  DW-1):    0 ];
363
                        1'b1: o_wb_data <=reorder_fifo_data[(2*DW-1):(  DW)];
364
                        endcase
365
                end
366
        end else if (C_AXI_DATA_WIDTH / DW == 4)
367
        begin
368
                reg     [1:0]    reorder_fifo_addr [0:(FIFOLN-1)];
369 3 dgisselq
 
370 8 dgisselq
 
371
                reg     [1:0]    low_addr;
372
                always @(posedge i_clk)
373
                        if ((i_wb_stb)&&(!o_wb_stall))
374
                                low_addr <= i_wb_addr[1:0];
375
                always @(posedge i_clk)
376
                        if ((o_axi_arvalid)&&(i_axi_arready))
377
                                reorder_fifo_addr[o_axi_arid] <= low_addr;
378
 
379
                if (STRICT_ORDER == 0)
380
                begin
381
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data [0:(FIFOLN-1)];
382
 
383 4 dgisselq
                        always @(posedge i_clk)
384 8 dgisselq
                                if ((o_axi_rready)&&(i_axi_rvalid))
385
                                        reorder_fifo_data[i_axi_rid] <= i_axi_rdata;
386
                        always @(posedge i_clk)
387 6 dgisselq
                        case(reorder_fifo_addr[fifo_tail][1:0])
388 8 dgisselq
                        2'b00: o_wb_data <=reorder_fifo_data[fifo_tail][(  DW-1):    0 ];
389
                        2'b01: o_wb_data <=reorder_fifo_data[fifo_tail][(2*DW-1):(  DW)];
390
                        2'b10: o_wb_data <=reorder_fifo_data[fifo_tail][(3*DW-1):(2*DW)];
391
                        2'b11: o_wb_data <=reorder_fifo_data[fifo_tail][(4*DW-1):(3*DW)];
392 4 dgisselq
                        endcase
393 8 dgisselq
                end else begin
394
                        reg     [(C_AXI_DATA_WIDTH-1):0] reorder_fifo_data;
395 4 dgisselq
 
396
                        always @(posedge i_clk)
397 8 dgisselq
                                reorder_fifo_data <= i_axi_rdata;
398
                        always @(posedge i_clk)
399
                        case(reorder_fifo_addr[fifo_tail][1:0])
400
                        2'b00: o_wb_data <=reorder_fifo_data[(  DW-1): 0];
401
                        2'b01: o_wb_data <=reorder_fifo_data[(2*DW-1):(  DW)];
402
                        2'b10: o_wb_data <=reorder_fifo_data[(3*DW-1):(2*DW)];
403
                        2'b11: o_wb_data <=reorder_fifo_data[(4*DW-1):(3*DW)];
404
                        endcase
405 4 dgisselq
                end
406 8 dgisselq
        end
407 4 dgisselq
 
408 8 dgisselq
        endgenerate
409 4 dgisselq
 
410 13 dgisselq
        // verilator lint_off UNUSED
411 8 dgisselq
        wire    axi_rd_ack, axi_wr_ack, axi_ard_req, axi_awr_req, axi_wr_req,
412
                axi_rd_err, axi_wr_err;
413 13 dgisselq
        // verilator lint_on  UNUSED
414 8 dgisselq
        //
415
        assign  axi_ard_req = (o_axi_arvalid)&&(i_axi_arready);
416
        assign  axi_awr_req = (o_axi_awvalid)&&(i_axi_awready);
417
        assign  axi_wr_req  = (o_axi_wvalid )&&(i_axi_wready);
418
        //
419
        assign  axi_rd_ack = (i_axi_rvalid)&&(o_axi_rready);
420
        assign  axi_wr_ack = (i_axi_bvalid)&&(o_axi_bready);
421
        assign  axi_rd_err = (axi_rd_ack)&&(i_axi_rresp[1]);
422
        assign  axi_wr_err = (axi_wr_ack)&&(i_axi_bresp[1]);
423 2 dgisselq
 
424 8 dgisselq
        //
425
        // We're going to need a FIFO on the return to make certain that we can
426
        // select the right bits from the return value, in the case where
427
        // DW != the axi data width.
428
        //
429
        // If we aren't using a strict order, this FIFO is can be used as a
430
        // reorder buffer as well, to place our out of order bus responses
431
        // back into order.  Responses on the wishbone, however, are *always*
432
        // done in order.
433 16 dgisselq
`ifdef  FORMAL
434
        reg     [31:0]   reorder_count;
435
`endif
436
        integer k;
437 8 dgisselq
        generate
438
        if (STRICT_ORDER == 0)
439
        begin
440
                // Reorder FIFO
441
                //
442
                // FIFO reorder buffer
443
                reg     [(FIFOLN-1):0]   reorder_fifo_valid;
444
                reg     [(FIFOLN-1):0]   reorder_fifo_err;
445 2 dgisselq
 
446 8 dgisselq
                initial reorder_fifo_valid = 0;
447
                initial reorder_fifo_err = 0;
448
 
449
 
450
                initial fifo_tail = 0;
451
                initial o_wb_ack  = 0;
452
                initial o_wb_err  = 0;
453 2 dgisselq
                always @(posedge i_clk)
454 14 dgisselq
                if (i_reset)
455 2 dgisselq
                begin
456 14 dgisselq
                        reorder_fifo_valid <= 0;
457
                        reorder_fifo_err <= 0;
458
                        o_wb_ack  <= 0;
459
                        o_wb_err  <= 0;
460
                        fifo_tail <= 0;
461
                end else begin
462 8 dgisselq
                        if (axi_rd_ack)
463 2 dgisselq
                        begin
464 5 dgisselq
                                reorder_fifo_valid[i_axi_rid] <= 1'b1;
465 8 dgisselq
                                reorder_fifo_err[i_axi_rid] <= axi_rd_err;
466 2 dgisselq
                        end
467 8 dgisselq
                        if (axi_wr_ack)
468 2 dgisselq
                        begin
469 5 dgisselq
                                reorder_fifo_valid[i_axi_bid] <= 1'b1;
470 8 dgisselq
                                reorder_fifo_err[i_axi_bid] <= axi_wr_err;
471 2 dgisselq
                        end
472
 
473
                        if (reorder_fifo_valid[fifo_tail])
474
                        begin
475 8 dgisselq
                                o_wb_ack <= (!wb_abort)&&(!reorder_fifo_err[fifo_tail]);
476
                                o_wb_err <= (!wb_abort)&&( reorder_fifo_err[fifo_tail]);
477
                                fifo_tail <= fifo_tail + 1'b1;
478 2 dgisselq
                                reorder_fifo_valid[fifo_tail] <= 1'b0;
479
                                reorder_fifo_err[fifo_tail]   <= 1'b0;
480
                        end else begin
481
                                o_wb_ack <= 1'b0;
482
                                o_wb_err <= 1'b0;
483
                        end
484
 
485
                        if (!i_wb_cyc)
486
                        begin
487 8 dgisselq
                                // reorder_fifo_valid <= 0;
488
                                // reorder_fifo_err   <= 0;
489 2 dgisselq
                                o_wb_err <= 1'b0;
490
                                o_wb_ack <= 1'b0;
491
                        end
492
                end
493
 
494 16 dgisselq
`ifdef  FORMAL
495
                always @(*)
496
                begin
497
                        reorder_count = 0;
498
                        for(k=0; k<FIFOLN; k=k+1)
499
                                if (reorder_fifo_valid[k])
500
                                        reorder_count = reorder_count + 1;
501
                end
502
 
503
                reg     [(FIFOLN-1):0]   f_reorder_fifo_valid_zerod,
504
                                        f_reorder_fifo_err_zerod;
505
                always @(*)
506
                        f_reorder_fifo_valid_zerod <=
507
                                ((reorder_fifo_valid >> fifo_tail)
508
                                | (reorder_fifo_valid << (FIFOLN-fifo_tail)));
509
                always @(*)
510
                        assert((f_reorder_fifo_valid_zerod & (~((1<<f_fifo_used)-1)))==0);
511
                //
512
                always @(*)
513
                        f_reorder_fifo_err_zerod <=
514
                                ((reorder_fifo_valid >> fifo_tail)
515
                                | (reorder_fifo_valid << (FIFOLN-fifo_tail)));
516
                always @(*)
517
                        assert((f_reorder_fifo_err_zerod & (~((1<<f_fifo_used)-1)))==0);
518
`endif
519
 
520 3 dgisselq
                reg     r_fifo_full;
521 8 dgisselq
                initial r_fifo_full = 0;
522 2 dgisselq
                always @(posedge i_clk)
523 14 dgisselq
                if (i_reset)
524
                        r_fifo_full <= 0;
525
                else begin
526 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall)
527 2 dgisselq
                                        &&(reorder_fifo_valid[fifo_tail]))
528
                                r_fifo_full <= (fifo_tail==n_fifo_head);
529 8 dgisselq
                        else if ((i_wb_stb)&&(!o_wb_stall))
530 2 dgisselq
                                r_fifo_full <= (fifo_tail==nn_fifo_head);
531
                        else if (reorder_fifo_valid[fifo_tail])
532
                                r_fifo_full <= 1'b0;
533
                        else
534
                                r_fifo_full <= (fifo_tail==n_fifo_head);
535
                end
536
                assign w_fifo_full = r_fifo_full;
537
        end else begin
538 6 dgisselq
                //
539 8 dgisselq
                // Strict ordering
540 6 dgisselq
                //
541 8 dgisselq
                reg     reorder_fifo_valid;
542
                reg     reorder_fifo_err;
543
 
544
                initial reorder_fifo_valid = 1'b0;
545
                initial reorder_fifo_err   = 1'b0;
546 2 dgisselq
                always @(posedge i_clk)
547 14 dgisselq
                if (i_reset)
548
                begin
549
                        reorder_fifo_valid <= 0;
550
                        reorder_fifo_err   <= 0;
551
                end else begin
552 8 dgisselq
                        if (axi_rd_ack)
553
                        begin
554
                                reorder_fifo_valid <= 1'b1;
555
                                reorder_fifo_err   <= axi_rd_err;
556
                        end else if (axi_wr_ack)
557
                        begin
558
                                reorder_fifo_valid <= 1'b1;
559
                                reorder_fifo_err   <= axi_wr_err;
560
                        end else begin
561
                                reorder_fifo_valid <= 1'b0;
562
                                reorder_fifo_err   <= 1'b0;
563
                        end
564 14 dgisselq
                end
565 8 dgisselq
 
566 16 dgisselq
`ifdef  FORMAL
567
                always @(*)
568
                        reorder_count = (reorder_fifo_valid) ? 1 : 0;
569
`endif
570
 
571 8 dgisselq
                initial fifo_tail = 0;
572 2 dgisselq
                always @(posedge i_clk)
573 14 dgisselq
                if (i_reset)
574
                        fifo_tail <= 0;
575
                else if (reorder_fifo_valid)
576
                        fifo_tail <= fifo_tail + 1'b1;
577 8 dgisselq
 
578
                initial o_wb_ack  = 0;
579 2 dgisselq
                always @(posedge i_clk)
580 14 dgisselq
                if (i_reset)
581
                        o_wb_ack <= 0;
582
                else
583 8 dgisselq
                        o_wb_ack <= (reorder_fifo_valid)&&(i_wb_cyc)&&(!wb_abort);
584
 
585
                initial o_wb_err  = 0;
586
                always @(posedge i_clk)
587 14 dgisselq
                if (i_reset)
588
                        o_wb_err <= 0;
589
                else
590 8 dgisselq
                        o_wb_err <= (reorder_fifo_err)&&(i_wb_cyc)&&(!wb_abort);
591
 
592
                reg     r_fifo_full;
593
                initial r_fifo_full = 0;
594
                always @(posedge i_clk)
595 14 dgisselq
                if (i_reset)
596
                        r_fifo_full <= 0;
597
                else begin
598 8 dgisselq
                        if ((i_wb_stb)&&(!o_wb_stall)
599
                                        &&(reorder_fifo_valid))
600
                                r_fifo_full <= (fifo_tail==n_fifo_head);
601
                        else if ((i_wb_stb)&&(!o_wb_stall))
602
                                r_fifo_full <= (fifo_tail==nn_fifo_head);
603 13 dgisselq
                        else if (reorder_fifo_valid)
604 8 dgisselq
                                r_fifo_full <= 1'b0;
605
                        else
606
                                r_fifo_full <= (fifo_tail==n_fifo_head);
607
                end
608
 
609
                assign w_fifo_full = r_fifo_full;
610 3 dgisselq
        end endgenerate
611 2 dgisselq
 
612 8 dgisselq
        //
613
        // Wishbone abort logic
614
        //
615
 
616 16 dgisselq
        // Did we just accept something?
617
        initial wb_cyc_stb = 1'b0;
618
        always @(posedge i_clk)
619
        if (i_reset)
620
                wb_cyc_stb <= 1'b0;
621
        else
622
                wb_cyc_stb <= (i_wb_cyc)&&(i_wb_stb)&&(!o_wb_stall);
623
 
624 14 dgisselq
        // Else, are we mid-cycle?
625 8 dgisselq
        initial wb_mid_cycle = 0;
626
        always @(posedge i_clk)
627 14 dgisselq
        if (i_reset)
628
                wb_mid_cycle <= 0;
629
        else if ((fifo_head != fifo_tail)
630
                        ||(o_axi_arvalid)||(o_axi_awvalid)
631
                        ||(o_axi_wvalid)
632
                        ||(i_wb_cyc)&&(i_wb_stb)&&(!o_wb_stall))
633
                wb_mid_cycle <= 1'b1;
634
        else
635
                wb_mid_cycle <= 1'b0;
636 8 dgisselq
 
637 14 dgisselq
        initial wb_mid_abort = 0;
638 8 dgisselq
        always @(posedge i_clk)
639 14 dgisselq
        if (i_reset)
640
                wb_mid_abort <= 0;
641
        else if (wb_mid_cycle)
642
                wb_mid_abort <= (wb_mid_abort)||(!i_wb_cyc);
643
        else
644
                wb_mid_abort <= 1'b0;
645 8 dgisselq
 
646
        assign  wb_abort = ((wb_mid_cycle)&&(!i_wb_cyc))||(wb_mid_abort);
647
 
648 2 dgisselq
        // Now, the difficult signal ... the stall signal
649
        // Let's build for a single cycle input ... and only stall if something
650
        // outgoing is valid and nothing is ready.
651
        assign  o_wb_stall = (i_wb_cyc)&&(
652 8 dgisselq
                                (w_fifo_full)||(wb_mid_abort)
653 5 dgisselq
                                ||((o_axi_awvalid)&&(!i_axi_awready))
654
                                ||((o_axi_wvalid )&&(!i_axi_wready ))
655
                                ||((o_axi_arvalid)&&(!i_axi_arready)));
656 8 dgisselq
 
657
 
658
/////////////////////////////////////////////////////////////////////////
659
//
660
//
661
//
662
// Formal methods section
663
//
664
// These are only relevant when *proving* that this translator works
665
//
666
//
667
//
668
/////////////////////////////////////////////////////////////////////////
669 16 dgisselq
`ifdef  FORMAL
670
        reg     f_err_state;
671 8 dgisselq
//
672 16 dgisselq
`ifdef  WBM2AXISP
673
// If we are the top-level of the design ...
674
`define ASSUME  assume
675
`define FORMAL_CLOCK    assume(i_clk == !f_last_clk); f_last_clk <= i_clk;
676
`else
677
`define ASSUME  assert
678
`define FORMAL_CLOCK    f_last_clk <= i_clk; // Clock will be given to us valid already
679
`endif
680
 
681
        reg     [4:0]    f_reset_counter;
682
        initial f_reset_counter = 1'b0;
683
        always @(posedge i_clk)
684
        if ((i_reset)&&(f_reset_counter < 5'h1f))
685
                f_reset_counter <= f_reset_counter + 1'b1;
686
        else if (!i_reset)
687
                f_reset_counter <= 0;
688
 
689
        always @(posedge i_clk)
690
        if ((f_past_valid)&&($past(i_reset))&&($past(f_reset_counter < 5'h10)))
691
                assume(i_reset);
692
 
693
        // Parameters
694
        initial assert(   (C_AXI_DATA_WIDTH / DW == 4)
695
                        ||(C_AXI_DATA_WIDTH / DW == 2)
696
                        ||(C_AXI_DATA_WIDTH      == DW));
697
        //
698
        initial assert( C_AXI_ADDR_WIDTH - LG_AXI_DW + LG_WB_DW == AW);
699
 
700
        //
701
        // Setup
702
        //
703
 
704
        reg     f_past_valid, f_last_clk;
705
 
706
        always @($global_clock)
707
        begin
708
                `FORMAL_CLOCK
709
 
710
                // Assume our inputs will only change on the positive edge
711
                // of the clock
712
                if (!$rose(i_clk))
713
                begin
714
                        // AXI inputs
715
                        `ASSUME($stable(i_axi_awready));
716
                        `ASSUME($stable(i_axi_wready));
717
                        `ASSUME($stable(i_axi_bid));
718
                        `ASSUME($stable(i_axi_bresp));
719
                        `ASSUME($stable(i_axi_bvalid));
720
                        `ASSUME($stable(i_axi_arready));
721
                        `ASSUME($stable(i_axi_rid));
722
                        `ASSUME($stable(i_axi_rresp));
723
                        `ASSUME($stable(i_axi_rvalid));
724
                        `ASSUME($stable(i_axi_rdata));
725
                        `ASSUME($stable(i_axi_rlast));
726
                        // Wishbone inputs
727
                        `ASSUME((i_reset)||($stable(i_reset)));
728
                        `ASSUME($stable(i_wb_cyc));
729
                        `ASSUME($stable(i_wb_stb));
730
                        `ASSUME($stable(i_wb_we));
731
                        `ASSUME($stable(i_wb_addr));
732
                        `ASSUME($stable(i_wb_data));
733
                        `ASSUME($stable(i_wb_sel));
734
                end
735
        end
736
 
737
        initial f_past_valid = 1'b0;
738
        always @(posedge i_clk)
739
                f_past_valid <= 1'b1;
740
 
741
        //////////////////////////////////////////////
742
        //
743
        //
744
        // Assumptions about the WISHBONE inputs
745
        //
746
        //
747
        //////////////////////////////////////////////
748
        assume property(f_past_valid || i_reset);
749
 
750
        wire    [(C_AXI_ID_WIDTH-1):0]   f_wb_nreqs, f_wb_nacks,f_wb_outstanding;
751
        fwb_slave #(.DW(DW),.AW(AW),
752
                        .F_MAX_STALL(0),
753
                        .F_MAX_ACK_DELAY(0),
754
                        .F_LGDEPTH(C_AXI_ID_WIDTH),
755
                        .F_MAX_REQUESTS((1<<(C_AXI_ID_WIDTH))-2))
756
                f_wb(i_clk, i_reset, i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr,
757
                                        i_wb_data, i_wb_sel,
758
                                o_wb_ack, o_wb_stall, o_wb_data, o_wb_err,
759
                        f_wb_nreqs, f_wb_nacks, f_wb_outstanding);
760
 
761
        wire    [(C_AXI_ID_WIDTH-1):0]   f_axi_rd_outstanding,
762
                                        f_axi_wr_outstanding,
763
                                        f_axi_awr_outstanding;
764
 
765
        wire    [((1<<C_AXI_ID_WIDTH)-1):0]      f_axi_rd_id_outstanding,
766
                                                f_axi_wr_id_outstanding,
767
                                                f_axi_awr_id_outstanding;
768
 
769
        faxi_master #(
770
                .C_AXI_ID_WIDTH(C_AXI_ID_WIDTH),
771
                .C_AXI_DATA_WIDTH(C_AXI_DATA_WIDTH),
772
                .C_AXI_ADDR_WIDTH(C_AXI_ADDR_WIDTH),
773
                .F_AXI_MAXSTALL(3),
774
                .F_AXI_MAXDELAY(3),
775
                .F_STRICT_ORDER(STRICT_ORDER),
776
                .F_CONSECUTIVE_IDS(1'b1),
777
                .F_OPT_BURSTS(1'b0),
778
                .F_CHECK_IDS(1'b1))
779
                f_axi(.i_clk(i_clk), .i_axi_reset_n(!i_reset),
780
                        // Write address channel
781
                        .i_axi_awready(i_axi_awready),
782
                        .i_axi_awid(   o_axi_awid),
783
                        .i_axi_awaddr( o_axi_awaddr),
784
                        .i_axi_awlen(  o_axi_awlen),
785
                        .i_axi_awsize( o_axi_awsize),
786
                        .i_axi_awburst(o_axi_awburst),
787
                        .i_axi_awlock( o_axi_awlock),
788
                        .i_axi_awcache(o_axi_awcache),
789
                        .i_axi_awprot( o_axi_awprot),
790
                        .i_axi_awqos(  o_axi_awqos),
791
                        .i_axi_awvalid(o_axi_awvalid),
792
                        // Write data channel
793
                        .i_axi_wready( i_axi_wready),
794
                        .i_axi_wdata(  o_axi_wdata),
795
                        .i_axi_wstrb(  o_axi_wstrb),
796
                        .i_axi_wlast(  o_axi_wlast),
797
                        .i_axi_wvalid( o_axi_wvalid),
798
                        // Write response channel
799
                        .i_axi_bid(    i_axi_bid),
800
                        .i_axi_bresp(  i_axi_bresp),
801
                        .i_axi_bvalid( i_axi_bvalid),
802
                        .i_axi_bready( o_axi_bready),
803
                        // Read address channel
804
                        .i_axi_arready(i_axi_arready),
805
                        .i_axi_arid(   o_axi_arid),
806
                        .i_axi_araddr( o_axi_araddr),
807
                        .i_axi_arlen(  o_axi_arlen),
808
                        .i_axi_arsize( o_axi_arsize),
809
                        .i_axi_arburst(o_axi_arburst),
810
                        .i_axi_arlock( o_axi_arlock),
811
                        .i_axi_arcache(o_axi_arcache),
812
                        .i_axi_arprot( o_axi_arprot),
813
                        .i_axi_arqos(  o_axi_arqos),
814
                        .i_axi_arvalid(o_axi_arvalid),
815
                        // Read data channel
816
                        .i_axi_rid(    i_axi_rid),
817
                        .i_axi_rresp(  i_axi_rresp),
818
                        .i_axi_rvalid( i_axi_rvalid),
819
                        .i_axi_rdata(  i_axi_rdata),
820
                        .i_axi_rlast(  i_axi_rlast),
821
                        .i_axi_rready( o_axi_rready),
822
                        // Counts
823
                        .f_axi_rd_outstanding( f_axi_rd_outstanding),
824
                        .f_axi_wr_outstanding( f_axi_wr_outstanding),
825
                        .f_axi_awr_outstanding( f_axi_awr_outstanding),
826
                        // Outstanding ID's
827
                        .f_axi_rd_id_outstanding( f_axi_rd_id_outstanding),
828
                        .f_axi_wr_id_outstanding( f_axi_wr_id_outstanding),
829
                        .f_axi_awr_id_outstanding(f_axi_awr_id_outstanding)
830
                );
831
 
832
 
833
 
834
        //////////////////////////////////////////////
835
        //
836
        //
837
        // Assumptions about the AXI inputs
838
        //
839
        //
840
        //////////////////////////////////////////////
841
 
842
 
843
        //////////////////////////////////////////////
844
        //
845
        //
846
        // Assertions about the AXI4 ouputs
847
        //
848
        //
849
        //////////////////////////////////////////////
850
 
851
        wire    [(LGFIFOLN-1):0] f_last_transaction_id;
852
        assign  f_last_transaction_id = transaction_id- 1;
853
        always @(posedge i_clk)
854
        if ((f_past_valid)&&(!$past(i_reset)))
855
        begin
856
                assert(o_axi_awid == f_last_transaction_id);
857
                if ($past(o_wb_stall))
858
                        assert($stable(o_axi_awid));
859
        end
860
 
861
        // Write response channel
862
        always @(posedge i_clk)
863
                // We keep bready high, so the other condition doesn't
864
                // need to be checked
865
                assert(o_axi_bready);
866
 
867
        // AXI read data channel signals
868
        always @(posedge i_clk)
869
                // We keep o_axi_rready high, so the other condition's
870
                // don't need to be checked here
871
                assert(o_axi_rready);
872
 
873
        //
874
        // Let's look into write requests
875
        //
876
        initial assert(!o_axi_awvalid);
877
        initial assert(!o_axi_wvalid);
878
        always @(posedge i_clk)
879
        if ((f_past_valid)&&($past(i_wb_stb))&&($past(i_wb_we))&&(!$past(o_wb_stall)))
880
        begin
881
                if ($past(i_reset))
882
                begin
883
                        assert(!o_axi_awvalid);
884
                        assert(!o_axi_wvalid);
885
                end else begin
886
                        // Following any write request that we accept, awvalid
887
                        // and wvalid should both be true
888
                        assert(o_axi_awvalid);
889
                        assert(o_axi_wvalid);
890
                end
891
        end
892
 
893
        // Let's assume all responses will come within 120 clock ticks
894
        parameter       [(C_AXI_ID_WIDTH-1):0]   F_AXI_MAXDELAY = 3,
895
                                                F_AXI_MAXSTALL = 3; // 7'd120;
896
        localparam      [(C_AXI_ID_WIDTH):0]     F_WB_MAXDELAY = F_AXI_MAXDELAY + 4;
897
 
898
        //
899
        // AXI write address channel
900
        //
901
        always @(posedge i_clk)
902
        if ((f_past_valid)&&($past(i_wb_cyc))&&(!$past(o_wb_stall)))
903
        begin
904
                if (($past(i_reset))||(!$past(i_wb_stb)))
905
                        assert(!o_axi_awvalid);
906
                else
907
                        assert(o_axi_awvalid == $past(i_wb_we));
908
        end
909
        //
910
        generate
911
        if (C_AXI_DATA_WIDTH      == DW)
912
        begin
913
                always @(posedge i_clk)
914
                if ((f_past_valid)&&($past(i_wb_cyc))&&($past(i_wb_stb))&&($past(i_wb_we))
915
                        &&(!$past(o_wb_stall)))
916
                        assert(o_axi_awaddr == { $past(i_wb_addr[AW-1:0]), axi_bottom_addr });
917
 
918
        end else if (C_AXI_DATA_WIDTH / DW == 2)
919
        begin
920
 
921
                always @(posedge i_clk)
922
                if ((f_past_valid)&&($past(i_wb_cyc))&&($past(i_wb_stb))&&($past(i_wb_we))
923
                        &&(!$past(o_wb_stall)))
924
                        assert(o_axi_awaddr == { $past(i_wb_addr[AW-1:1]), axi_bottom_addr });
925
 
926
        end else if (C_AXI_DATA_WIDTH / DW == 4)
927
        begin
928
 
929
                always @(posedge i_clk)
930
                if ((f_past_valid)&&($past(i_wb_cyc))&&($past(i_wb_stb))&&($past(i_wb_we))
931
                        &&(!$past(o_wb_stall)))
932
                        assert(o_axi_awaddr == { $past(i_wb_addr[AW-1:2]), axi_bottom_addr });
933
 
934
        end endgenerate
935
 
936
        //
937
        // AXI write data channel
938
        //
939
        always @(posedge i_clk)
940
        if ((f_past_valid)&&($past(i_wb_cyc))&&(!$past(o_wb_stall)))
941
        begin
942
                if (($past(i_reset))||(!$past(i_wb_stb)))
943
                        assert(!o_axi_wvalid);
944
                else
945
                        assert(o_axi_wvalid == $past(i_wb_we));
946
        end
947
        //
948
        generate
949
        if (C_AXI_DATA_WIDTH == DW)
950
        begin
951
 
952
                always @(posedge i_clk)
953
                if ((f_past_valid)&&($past(i_wb_stb))&&($past(i_wb_we)))
954
                begin
955
                        assert(o_axi_wdata == $past(i_wb_data));
956
                        assert(o_axi_wstrb == $past(i_wb_sel));
957
                end
958
 
959
        end else if (C_AXI_DATA_WIDTH / DW == 2)
960
        begin
961
 
962
                always @(posedge i_clk)
963
                if ((f_past_valid)&&($past(i_wb_stb))&&($past(i_wb_we)))
964
                begin
965
                        case($past(i_wb_addr[0]))
966
                        1'b0: assert(o_axi_wdata[(  DW-1): 0] == $past(i_wb_data));
967
                        1'b1: assert(o_axi_wdata[(2*DW-1):DW] == $past(i_wb_data));
968
                        endcase
969
 
970
                        case($past(i_wb_addr[0]))
971
                        1'b0: assert(o_axi_wstrb == {  no_sel,$past(i_wb_sel)});
972
                        1'b1: assert(o_axi_wstrb == {  $past(i_wb_sel),no_sel});
973
                        endcase
974
                end
975
 
976
        end else if (C_AXI_DATA_WIDTH / DW == 4)
977
        begin
978
 
979
                always @(posedge i_clk)
980
                if ((f_past_valid)&&($past(i_wb_stb))&&(!$past(o_wb_stall))&&($past(i_wb_we)))
981
                begin
982
                        case($past(i_wb_addr[1:0]))
983
                        2'b00: assert(o_axi_wdata[  (DW-1):    0 ] == $past(i_wb_data));
984
                        2'b00: assert(o_axi_wdata[(2*DW-1):(  DW)] == $past(i_wb_data));
985
                        2'b00: assert(o_axi_wdata[(3*DW-1):(2*DW)] == $past(i_wb_data));
986
                        2'b11: assert(o_axi_wdata[(4*DW-1):(3*DW)] == $past(i_wb_data));
987
                        endcase
988
 
989
                        case($past(i_wb_addr[1:0]))
990
                        2'b00: assert(o_axi_wstrb == { {(3){no_sel}},$past(i_wb_sel)});
991
                        2'b01: assert(o_axi_wstrb == { {(2){no_sel}},$past(i_wb_sel), {(1){no_sel}}});
992
                        2'b10: assert(o_axi_wstrb == { {(1){no_sel}},$past(i_wb_sel), {(2){no_sel}}});
993
                        2'b11: assert(o_axi_wstrb == {       $past(i_wb_sel),{(3){no_sel}}});
994
                        endcase
995
                end
996
        end endgenerate
997
 
998
        //
999
        // AXI read address channel
1000
        //
1001
        initial assert(!o_axi_arvalid);
1002
        always @(posedge i_clk)
1003
        if ((f_past_valid)&&($past(i_wb_cyc))&&(!$past(o_wb_stall)))
1004
        begin
1005
                if (($past(i_reset))||(!$past(i_wb_stb)))
1006
                        assert(!o_axi_arvalid);
1007
                else
1008
                        assert(o_axi_arvalid == !$past(i_wb_we));
1009
        end
1010
        //
1011
        generate
1012
        if (C_AXI_DATA_WIDTH == DW)
1013
        begin
1014
                always @(posedge i_clk)
1015
                        if ((f_past_valid)&&($past(i_wb_stb))&&($past(!i_wb_we))
1016
                                &&(!$past(o_wb_stall)))
1017
                                assert(o_axi_araddr == $past({ i_wb_addr[AW-1:0], axi_bottom_addr }));
1018
 
1019
        end else if (C_AXI_DATA_WIDTH / DW == 2)
1020
        begin
1021
 
1022
                always @(posedge i_clk)
1023
                        if ((f_past_valid)&&($past(i_wb_stb))&&($past(!i_wb_we))
1024
                                &&(!$past(o_wb_stall)))
1025
                                assert(o_axi_araddr == $past({ i_wb_addr[AW-1:1], axi_bottom_addr }));
1026
 
1027
        end else if (C_AXI_DATA_WIDTH / DW == 4)
1028
        begin
1029
                always @(posedge i_clk)
1030
                        if ((f_past_valid)&&($past(i_wb_stb))&&($past(!i_wb_we))
1031
                                &&(!$past(o_wb_stall)))
1032
                                assert(o_axi_araddr == $past({ i_wb_addr[AW-1:2], axi_bottom_addr }));
1033
 
1034
        end endgenerate
1035
 
1036
        //
1037
        // AXI write response channel
1038
        //
1039
 
1040
 
1041
        //
1042
        // AXI read data channel signals
1043
        //
1044
        always @(posedge i_clk)
1045
                `ASSUME(f_axi_rd_outstanding <= f_wb_outstanding);
1046
        //
1047
        always @(posedge i_clk)
1048
                `ASSUME(f_axi_rd_outstanding + f_axi_wr_outstanding  <= f_wb_outstanding);
1049
        always @(posedge i_clk)
1050
                `ASSUME(f_axi_rd_outstanding + f_axi_awr_outstanding <= f_wb_outstanding);
1051
        //
1052
        always @(posedge i_clk)
1053
                `ASSUME(f_axi_rd_outstanding + f_axi_wr_outstanding +2 > f_wb_outstanding);
1054
        always @(posedge i_clk)
1055
                `ASSUME(f_axi_rd_outstanding + f_axi_awr_outstanding +2 > f_wb_outstanding);
1056
 
1057
        // Make sure we only create one request at a time
1058
        always @(posedge i_clk)
1059
                assert((!o_axi_arvalid)||(!o_axi_wvalid));
1060
        always @(posedge i_clk)
1061
                assert((!o_axi_arvalid)||(!o_axi_awvalid));
1062
 
1063
        // Now, let's look into that FIFO.  Without it, we know nothing about the ID's
1064
 
1065
        // Error handling
1066
        always @(posedge i_clk)
1067
                if (!i_wb_cyc)
1068
                        f_err_state <= 0;
1069
                else if (o_wb_err)
1070
                        f_err_state <= 1;
1071
        always @(posedge i_clk)
1072
                if ((f_past_valid)&&($past(f_err_state))&&(
1073
                                (!$past(o_wb_stall))||(!$past(i_wb_stb))))
1074
                        `ASSUME(!i_wb_stb);
1075
 
1076
        // Head and tail pointers
1077
 
1078
        // The head should only increment when something goes through
1079
        always @(posedge i_clk)
1080
                if ((f_past_valid)&&(!$past(i_reset))
1081
                                &&((!$past(i_wb_stb))||($past(o_wb_stall))))
1082
                        assert($stable(fifo_head));
1083
 
1084
        // Can't overrun the FIFO
1085
        wire    [(LGFIFOLN-1):0] f_fifo_tail_minus_one;
1086
        assign  f_fifo_tail_minus_one = fifo_tail - 1'b1;
1087
        always @(posedge i_clk)
1088
        if ((!f_past_valid)||($past(i_reset)))
1089
                assert(fifo_head == fifo_tail);
1090
        else if ((f_past_valid)&&($past(fifo_head == f_fifo_tail_minus_one)))
1091
                assert(fifo_head != fifo_tail);
1092
 
1093
        reg                     f_pre_ack;
1094
 
1095
        wire    [(LGFIFOLN-1):0] f_fifo_used;
1096
        assign  f_fifo_used = fifo_head - fifo_tail;
1097
 
1098
        initial assert(fifo_tail == 0);
1099
        initial assert(reorder_fifo_valid        == 0);
1100
        initial assert(reorder_fifo_err          == 0);
1101
        initial f_pre_ack = 1'b0;
1102
        always @(posedge i_clk)
1103
        begin
1104
                f_pre_ack <= (!wb_abort)&&((axi_rd_ack)||(axi_wr_ack));
1105
                if (STRICT_ORDER)
1106
                begin
1107
                        `ASSUME((!axi_rd_ack)||(!axi_wr_ack));
1108
 
1109
                        if ((f_past_valid)&&(!$past(i_reset)))
1110
                                assert((!$past(i_wb_cyc))
1111
                                        ||(o_wb_ack == $past(f_pre_ack)));
1112
                end
1113
        end
1114
 
1115
        //
1116
        // Verify that there are no outstanding requests outside of the FIFO
1117
        // window.  This should never happen, but the formal tools need to know
1118
        // that.
1119
        //
1120
        always @(*)
1121
        begin
1122
                assert((f_axi_rd_id_outstanding&f_axi_wr_id_outstanding)==0);
1123
                assert((f_axi_rd_id_outstanding&f_axi_awr_id_outstanding)==0);
1124
 
1125
                if (fifo_head == fifo_tail)
1126
                begin
1127
                        assert(f_axi_rd_id_outstanding  == 0);
1128
                        assert(f_axi_wr_id_outstanding  == 0);
1129
                        assert(f_axi_awr_id_outstanding == 0);
1130
                end
1131
 
1132
                for(k=0; k<(1<<LGFIFOLN); k=k+1)
1133
                begin
1134
                        if (      ((fifo_tail < fifo_head)&&(k <  fifo_tail))
1135
                                ||((fifo_tail < fifo_head)&&(k >= fifo_head))
1136
                                ||((fifo_head < fifo_tail)&&(k >= fifo_head)&&(k < fifo_tail))
1137
                                //||((fifo_head < fifo_tail)&&(k >=fifo_tail))
1138
                                )
1139
                        begin
1140
                                assert(f_axi_rd_id_outstanding[k]==0);
1141
                                assert(f_axi_wr_id_outstanding[k]==0);
1142
                                assert(f_axi_awr_id_outstanding[k]==0);
1143
                        end
1144
                end
1145
        end
1146
 
1147
        generate
1148
        if (STRICT_ORDER)
1149
        begin : STRICTREQ
1150
 
1151
                reg     [C_AXI_ID_WIDTH-1:0]     f_last_axi_id;
1152
                wire    [C_AXI_ID_WIDTH-1:0]     f_next_axi_id,
1153
                                                f_expected_last_id;
1154
                assign  f_next_axi_id = f_last_axi_id + 1'b1;
1155
                assign  f_expected_last_id = fifo_head - 1'b1 - f_fifo_used;
1156
 
1157
                initial f_last_axi_id = -1;
1158
                always @(posedge i_clk)
1159
                        if (i_reset)
1160
                                f_last_axi_id = -1;
1161
                        else if ((axi_rd_ack)||(axi_wr_ack))
1162
                                f_last_axi_id <= f_next_axi_id;
1163
                        else if (f_fifo_used == 0)
1164
                                assert(f_last_axi_id == fifo_head-1'b1);
1165
 
1166
                always @(posedge i_clk)
1167
                        if (axi_rd_ack)
1168
                                `ASSUME(i_axi_rid == f_next_axi_id);
1169
                        else if (axi_wr_ack)
1170
                                `ASSUME(i_axi_bid == f_next_axi_id);
1171
        end endgenerate
1172
 
1173
        reg     f_pending, f_returning;
1174
        initial f_pending = 1'b0;
1175
        always @(*)
1176
                f_pending <= (o_axi_arvalid)||(o_axi_awvalid);
1177
        always @(*)
1178
                f_returning <= (axi_rd_ack)||(axi_wr_ack);
1179
 
1180
        reg     [(LGFIFOLN):0]   f_pre_count;
1181
 
1182
        always @(*)
1183
                f_pre_count <= f_axi_awr_outstanding
1184
                        + f_axi_rd_outstanding
1185
                        + reorder_count
1186
                        + { {(LGFIFOLN){1'b0}}, (o_wb_ack) }
1187
                        + { {(LGFIFOLN){1'b0}}, (f_pending) };
1188
        always @(posedge i_clk)
1189
                assert((wb_abort)||(o_wb_err)||(f_pre_count == f_wb_outstanding));
1190
 
1191
        always @(posedge i_clk)
1192
                assert((wb_abort)||(o_wb_err)||(f_fifo_used == f_wb_outstanding
1193
                                        // + {{(LGFIFOLN){1'b0}},f_past_valid)(i_wb_stb)&&(!o_wb_ack)}
1194
                                        - {{(LGFIFOLN){1'b0}},(o_wb_ack)}));
1195
 
1196
        always @(posedge i_clk)
1197
                if (o_axi_wvalid)
1198
                        assert(f_fifo_used != 0);
1199
        always @(posedge i_clk)
1200
                if (o_axi_arvalid)
1201
                        assert(f_fifo_used != 0);
1202
        always @(posedge i_clk)
1203
                if (o_axi_awvalid)
1204
                        assert(f_fifo_used != 0);
1205
 
1206
`endif
1207 2 dgisselq
endmodule

powered by: WebSVN 2.1.0

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