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

Subversion Repositories wb2axip

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 dgisselq
`error This full featured AXI to WB converter does not (yet) work
2 8 dgisselq
////////////////////////////////////////////////////////////////////////////////
3
//
4
// Filename:    aximwr2wbsp.v
5
//
6
// Project:     Pipelined Wishbone to AXI converter
7
//
8
// Purpose:     Convert the three AXI4 write channels to a single wishbone
9
//              channel to write the results.
10
//
11
//      Still need to implement the lock feature.
12
//
13 16 dgisselq
        // We're going to need to keep track of transaction bursts in progress,
14
        // since the wishbone doesn't.  For this, we'll use a FIFO, but with
15
        // multiple pointers:
16
        //
17
        //      fifo_ahead      - pointer to where to write the next incoming
18
        //                              bus request .. adjusted when
19
        //                              (o_axi_awready)&&(i_axi_awvalid)
20
        //      fifo_neck       - pointer to where to read from the FIFO in
21
        //                              order to issue another request.  Used
22
        //                              when (o_wb_stb)&&(!i_wb_stall)
23
        //      fifo_torso      - pointer to where to write a wishbone
24
        //                              transaction upon return.
25
        //                              when (i_ack)
26
        //      fifo_tail       - pointer to where the last transaction is to
27
        //                              be retired when
28
        //                                      (i_axi_rvalid)&&(i_axi_rready)
29
        //
30
        // All of these are to be set to zero upon a reset signal.
31
        //
32
//
33 8 dgisselq
// Creator:     Dan Gisselquist, Ph.D.
34
//              Gisselquist Technology, LLC
35
//
36
////////////////////////////////////////////////////////////////////////////////
37
//
38 16 dgisselq
// Copyright (C) 2015-2019, Gisselquist Technology, LLC
39 8 dgisselq
//
40 16 dgisselq
// This file is part of the pipelined Wishbone to AXI converter project, a
41
// project that contains multiple bus bridging designs and formal bus property
42
// sets.
43 8 dgisselq
//
44 16 dgisselq
// The bus bridge designs and property sets are free RTL designs: you can
45
// redistribute them and/or modify any of them under the terms of the GNU
46
// Lesser General Public License as published by the Free Software Foundation,
47
// either version 3 of the License, or (at your option) any later version.
48 8 dgisselq
//
49 16 dgisselq
// The bus bridge designs and property sets are distributed in the hope that
50
// they will be useful, but WITHOUT ANY WARRANTY; without even the implied
51
// warranty of MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
52
// GNU Lesser General Public License for more details.
53
//
54
// You should have received a copy of the GNU Lesser General Public License
55
// along with these designs.  (It's in the $(ROOT)/doc directory.  Run make
56
// with no target there if the PDF file isn't present.)  If not, see
57 8 dgisselq
// <http://www.gnu.org/licenses/> for a copy.
58
//
59 16 dgisselq
// License:     LGPL, v3, as defined and found on www.gnu.org,
60
//              http://www.gnu.org/licenses/lgpl.html
61 8 dgisselq
//
62
////////////////////////////////////////////////////////////////////////////////
63
//
64
//
65
`default_nettype        none
66
//
67
//
68
module aximwr2wbsp #(
69
        parameter C_AXI_ID_WIDTH        = 6, // The AXI id width used for R&W
70
                                             // This is an int between 1-16
71
        parameter C_AXI_DATA_WIDTH      = 32,// Width of the AXI R&W data
72
        parameter C_AXI_ADDR_WIDTH      = 28,   // AXI Address width
73
        parameter AW                    = 26,
74
        parameter LGFIFO                =  4
75
        ) (
76
        input   wire                    i_axi_clk,      // System clock
77
        input   wire                    i_axi_reset_n,
78
 
79
// AXI write address channel signals
80
        output  wire                    o_axi_awready, // Slave is ready to accept
81
        input   wire    [C_AXI_ID_WIDTH-1:0]     i_axi_awid,     // Write ID
82
        input   wire    [C_AXI_ADDR_WIDTH-1:0]   i_axi_awaddr,   // Write address
83
        input   wire    [7:0]            i_axi_awlen,    // Write Burst Length
84
        input   wire    [2:0]            i_axi_awsize,   // Write Burst size
85
        input   wire    [1:0]            i_axi_awburst,  // Write Burst type
86
        input   wire    [0:0]             i_axi_awlock,   // Write lock type
87
        input   wire    [3:0]            i_axi_awcache,  // Write Cache type
88
        input   wire    [2:0]            i_axi_awprot,   // Write Protection type
89
        input   wire    [3:0]            i_axi_awqos,    // Write Quality of Svc
90
        input   wire                    i_axi_awvalid,  // Write address valid
91
 
92
// AXI write data channel signals
93
        output  wire                    o_axi_wready,  // Write data ready
94
        input   wire    [C_AXI_DATA_WIDTH-1:0]   i_axi_wdata,    // Write data
95
        input   wire    [C_AXI_DATA_WIDTH/8-1:0] i_axi_wstrb,    // Write strobes
96
        input   wire                    i_axi_wlast,    // Last write transaction   
97
        input   wire                    i_axi_wvalid,   // Write valid
98
 
99
// AXI write response channel signals
100
        output  wire [C_AXI_ID_WIDTH-1:0] o_axi_bid,     // Response ID
101
        output  wire [1:0]               o_axi_bresp,    // Write response
102
        output  wire                    o_axi_bvalid,  // Write reponse valid
103
        input   wire                    i_axi_bready,  // Response ready
104
 
105
        // We'll share the clock and the reset
106
        output  reg                     o_wb_cyc,
107
        output  reg                     o_wb_stb,
108
        output  wire [(AW-1):0]          o_wb_addr,
109
        output  wire [(C_AXI_DATA_WIDTH-1):0]    o_wb_data,
110
        output  wire [(C_AXI_DATA_WIDTH/8-1):0]  o_wb_sel,
111
        input   wire                    i_wb_ack,
112
        input   wire                    i_wb_stall,
113
        // input        [(C_AXI_DATA_WIDTH-1):0]        i_wb_data,
114
        input   wire                    i_wb_err
115 16 dgisselq
`ifdef  FORMAL
116
        ,
117
        output  wire    [LGFIFO-1:0]     f_fifo_ahead,
118
        output  wire    [LGFIFO-1:0]     f_fifo_dhead,
119
        output  wire    [LGFIFO-1:0]     f_fifo_neck,
120
        output  wire    [LGFIFO-1:0]     f_fifo_torso,
121
        output  wire    [LGFIFO-1:0]     f_fifo_tail
122
`endif
123 8 dgisselq
);
124
 
125
        localparam      DW = C_AXI_DATA_WIDTH;
126
 
127
        wire    w_reset;
128
        assign  w_reset = (i_axi_reset_n == 1'b0);
129
 
130
        //
131
        //
132
        //
133
        reg     [LGFIFO-1:0]     fifo_ahead, fifo_dhead, fifo_neck, fifo_torso,
134
                                fifo_tail;
135
        wire    [LGFIFO-1:0]     next_ahead, next_dhead, next_neck, next_torso,
136
                                next_tail;
137
        assign  next_ahead = fifo_ahead + 1;
138
        assign  next_dhead = fifo_dhead + 1;
139
        assign  next_neck  = fifo_neck  + 1;
140
        assign  next_torso = fifo_torso + 1;
141
        assign  next_tail  = fifo_tail  + 1;
142
 
143
        reg     [(C_AXI_ID_WIDTH+AW)-1:0]        afifo   [0:((1<<(LGFIFO))-1)];
144
        reg     [(DW + DW/8)-1:0]                dfifo   [0:((1<<(LGFIFO))-1)];
145
        reg     [((1<<(LGFIFO))-1):0]            efifo;
146
 
147
        reg     [(C_AXI_ID_WIDTH+AW)-1:0]        afifo_at_neck, afifo_at_tail;
148
        reg     [(DW + DW/8)-1:0]                dfifo_at_neck;
149
        reg                                     efifo_at_tail;
150
 
151
        reg     filling_fifo, incr;
152
        reg     [7:0]    len;
153
        reg     [(AW-1):0]       wr_fifo_addr;
154
        reg     [(C_AXI_ID_WIDTH-1):0]   wr_fifo_id;
155
 
156 16 dgisselq
        wire    axi_aw_req, axi_wr_req, axi_wr_ack;
157 8 dgisselq
        assign  axi_aw_req = (o_axi_awready)&&(i_axi_awvalid);
158
        assign  axi_wr_req = (o_axi_wready)&&(i_axi_wvalid);
159 16 dgisselq
        assign  axi_wr_ack = (o_axi_bvalid)&&(i_axi_bready);
160 8 dgisselq
 
161
        wire    fifo_full;
162
        assign  fifo_full = (next_ahead == fifo_tail)||(next_dhead ==fifo_tail);
163
 
164
        initial fifo_ahead = 0;
165
        initial fifo_dhead = 0;
166
        always @(posedge i_axi_clk)
167
        begin
168
                if (filling_fifo)
169
                begin
170
                        if (!fifo_full)
171
                        begin
172
                                len <= len - 1;
173
                                if (len == 1)
174
                                        filling_fifo <= 1'b0;
175
                                fifo_ahead <= next_ahead;
176
                                wr_fifo_addr <= wr_fifo_addr
177
                                        + {{(AW-1){1'b0}},incr};
178
                        end
179
                end else begin
180
                        wr_fifo_addr <= i_axi_awaddr[(C_AXI_ADDR_WIDTH-1):(C_AXI_ADDR_WIDTH-AW)];
181
                        wr_fifo_id   <= i_axi_awid;
182
                        incr         <= i_axi_awburst[0];
183
                        if (axi_aw_req)
184
                        begin
185
                                fifo_ahead <= next_ahead;
186
                                len <= i_axi_awlen;
187
                                filling_fifo <= (i_axi_awlen != 0);
188
                        end
189
                end
190
 
191
                if (w_reset)
192
                begin
193
                        fifo_ahead <= 0;
194
                        len <= 0;
195
                        filling_fifo <= 0;
196
                end
197
        end
198
 
199
        always @(posedge i_axi_clk)
200
                afifo[fifo_ahead] <= { wr_fifo_id, wr_fifo_addr };
201
 
202
        initial fifo_dhead = 0;
203
        always @(posedge i_axi_clk)
204
                if (w_reset)
205
                        fifo_dhead <= 0;
206
                else if (axi_wr_req)
207
                        fifo_dhead <= next_dhead;
208
 
209
        always @(posedge i_axi_clk)
210
                dfifo[fifo_dhead] <= { i_axi_wstrb, i_axi_wdata };
211
 
212
 
213
        reg     err_state;
214
 
215
        initial o_wb_cyc   = 0;
216
        initial o_wb_stb   = 0;
217
        initial fifo_neck  = 0;
218
        initial fifo_torso = 0;
219
        initial err_state  = 0;
220
        always @(posedge i_axi_clk)
221
        begin
222
                if (w_reset)
223
                begin
224
                        o_wb_cyc <= 0;
225
                        o_wb_stb <= 0;
226
 
227
                        fifo_neck <= 0;
228
                        fifo_torso <= 0;
229
 
230
                        err_state <= 0;
231
                end else if (o_wb_stb)
232
                begin
233
                        if (i_wb_err)
234
                        begin
235 16 dgisselq
                                o_wb_cyc <= 1'b0;
236 8 dgisselq
                                o_wb_stb <= 1'b0;
237 16 dgisselq
                                err_state <= 1'b1;
238
                        end else if (!i_wb_stall)
239 8 dgisselq
                                o_wb_stb <= (fifo_ahead != next_neck)
240
                                        &&(fifo_dhead != next_neck);
241
 
242
                        if ((!i_wb_stall)&&(fifo_neck != fifo_ahead)&&(fifo_neck != fifo_dhead))
243
                                fifo_neck <= next_neck;
244
 
245
                        if (i_wb_ack)
246
                                fifo_torso <= next_torso;
247
 
248
                        if (fifo_neck == next_torso)
249
                                o_wb_cyc <= 1'b0;
250 16 dgisselq
                end else if ((err_state)||(i_wb_err))
251 8 dgisselq
                begin
252
                        o_wb_cyc <= 1'b0;
253 16 dgisselq
                        o_wb_stb <= 1'b0;
254
                        err_state <= (err_state)||(i_wb_err);
255
                        if ((o_wb_cyc)&&(fifo_torso != fifo_neck))
256 8 dgisselq
                                fifo_torso <= next_torso;
257
                        if (fifo_neck == next_torso)
258
                                err_state <= 1'b0;
259
                end else if (o_wb_cyc)
260
                begin
261
                        if (i_wb_ack)
262
                                fifo_torso <= next_torso;
263
                        if (fifo_neck == next_torso)
264
                                o_wb_cyc <= 1'b0;
265 16 dgisselq
                end else if((fifo_ahead!= fifo_neck)
266
                                &&(fifo_dhead != fifo_neck))
267 8 dgisselq
                begin
268
                        o_wb_cyc <= 1;
269
                        o_wb_stb <= 1;
270
                end
271
        end
272
 
273
        initial efifo = 0;
274
        always @(posedge i_axi_clk)
275
                if(w_reset)
276
                        efifo <= 0;
277
                else
278
                        efifo[fifo_torso] <= (i_wb_err)||(err_state);
279
 
280
        always @(posedge i_axi_clk)
281
                afifo_at_neck <= afifo[fifo_neck];
282
        assign  o_wb_addr = afifo_at_neck[(AW-1):0];
283
 
284
        always @(posedge i_axi_clk)
285
                dfifo_at_neck <= dfifo[fifo_neck];
286
        assign  o_wb_data = dfifo_at_neck[DW-1:0];
287
        assign  o_wb_sel  = dfifo_at_neck[(DW+(DW/8))-1:DW];
288
 
289
        initial fifo_tail = 0;
290
        always @(posedge i_axi_clk)
291
                if (w_reset)
292
                        fifo_tail <= 0;
293 16 dgisselq
                else if (axi_wr_ack)
294 8 dgisselq
                        fifo_tail <= next_tail;
295
 
296
        always @(posedge i_axi_clk)
297
                afifo_at_tail <= afifo[fifo_tail];
298
        always @(posedge i_axi_clk)
299
                efifo_at_tail <= efifo[fifo_tail];
300
 
301
        assign  o_axi_bid   = afifo_at_tail[(C_AXI_ID_WIDTH+AW)-1:AW];
302
        assign  o_axi_bresp = {(2){efifo_at_tail}};
303
 
304
        assign  o_axi_bvalid  = (fifo_tail  != fifo_torso);
305
        assign  o_axi_awready = (next_ahead != fifo_tail);
306
        assign  o_axi_wready  = (next_dhead != fifo_tail);
307
 
308
        // Make Verilator happy
309
        // verilator lint_on  UNUSED
310
        wire    [(C_AXI_ID_WIDTH+AW+C_AXI_ADDR_WIDTH-AW)
311
                +(1)+1+3+1+4+3+4-1:0]    unused;
312
        assign  unused = { i_axi_awburst[1], i_axi_awsize,
313
                        i_axi_awlock, i_axi_awcache, i_axi_awprot,
314
                        i_axi_awqos, i_axi_wlast,
315
                        afifo_at_neck[(C_AXI_ID_WIDTH+AW-1):AW],
316
                        afifo_at_tail[(AW-1):0],
317
                        i_axi_awaddr[(C_AXI_ADDR_WIDTH-AW)-1:0] };
318
        // verilator lint_off UNUSED
319
 
320
`ifdef  FORMAL
321
        always @(*)
322
                assume(!i_axi_awburst[1]);
323
 
324
        reg     f_past_valid;
325
        initial f_past_valid = 1'b0;
326
        always @(posedge i_axi_clk)
327
                f_past_valid <= 1'b1;
328
 
329
        wire    [LGFIFO-1:0]     f_afifo_used, f_dfifo_used,
330
                                f_fifo_neck_used, f_fifo_torso_used;
331
 
332
        assign  f_afifo_used      = fifo_ahead - fifo_tail;
333
        assign  f_dfifo_used      = fifo_dhead - fifo_tail;
334
        assign  f_fifo_neck_used  = fifo_dhead - fifo_neck;
335
        assign  f_fifo_torso_used = fifo_dhead - fifo_torso;
336
 
337
        always @(*)
338
                assert((f_afifo_used < {(LGFIFO){1'b1}})||(!o_axi_awready));
339
        always @(*)
340
                assert((f_dfifo_used < {(LGFIFO){1'b1}})||(!o_axi_wready));
341
        always @(*)
342
                assert(f_fifo_neck_used  <= f_dfifo_used);
343
        always @(*)
344
                assert(f_fifo_torso_used <= f_dfifo_used);
345
        always @(*)
346
                assert((!o_wb_stb)||
347
                        ((fifo_neck != fifo_ahead)
348
                                &&(fifo_neck != fifo_dhead)));
349 16 dgisselq
 
350
        assign  f_fifo_ahead = fifo_ahead;
351
        assign  f_fifo_dhead = fifo_dhead;
352
        assign  f_fifo_neck  = fifo_neck;
353
        assign  f_fifo_torso = fifo_torso;
354
        assign  f_fifo_tail  = fifo_tail;
355
 
356
        always @(*)
357
                if (i_axi_awvalid)
358
                        assert(!i_axi_awburst[1]);
359 8 dgisselq
`endif
360
endmodule
361
 

powered by: WebSVN 2.1.0

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