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

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [core/] [ds_dma64/] [pcie_src/] [pcie_core64_m1/] [source/] [sync_fifo.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
 
2
//-----------------------------------------------------------------------------
3
//
4
// (c) Copyright 2009-2010 Xilinx, Inc. All rights reserved.
5
//
6
// This file contains confidential and proprietary information
7
// of Xilinx, Inc. and is protected under U.S. and
8
// international copyright and other intellectual property
9
// laws.
10
//
11
// DISCLAIMER
12
// This disclaimer is not a license and does not grant any
13
// rights to the materials distributed herewith. Except as
14
// otherwise provided in a valid license issued to you by
15
// Xilinx, and to the maximum extent permitted by applicable
16
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
17
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
18
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
19
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
20
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
21
// (2) Xilinx shall not be liable (whether in contract or tort,
22
// including negligence, or under any other theory of
23
// liability) for any loss or damage of any kind or nature
24
// related to, arising under or in connection with these
25
// materials, including for any direct, or any indirect,
26
// special, incidental, or consequential loss or damage
27
// (including loss of data, profits, goodwill, or any type of
28
// loss or damage suffered as a result of any action brought
29
// by a third party) even if such damage or loss was
30
// reasonably foreseeable or Xilinx had been advised of the
31
// possibility of the same.
32
//
33
// CRITICAL APPLICATIONS
34
// Xilinx products are not designed or intended to be fail-
35
// safe, or for use in any application requiring fail-safe
36
// performance, such as life-support or safety devices or
37
// systems, Class III medical devices, nuclear facilities,
38
// applications related to the deployment of airbags, or any
39
// other applications that could lead to death, personal
40
// injury, or severe property or environmental damage
41
// (individually and collectively, "Critical
42
// Applications"). Customer assumes the sole risk and
43
// liability of any use of Xilinx products in Critical
44
// Applications, subject only to applicable laws and
45
// regulations governing limitations on product liability.
46
//
47
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
48
// PART OF THIS FILE AT ALL TIMES.
49
//
50
//-----------------------------------------------------------------------------
51
// Project    : V5-Block Plus for PCI Express
52
// File       : sync_fifo.v
53
//--------------------------------------------------------------------------------
54
//--------------------------------------------------------------------------------
55
/******************************************************************************
56
 
57
    Description:    This module is functions as a FIFO
58
 
59
******************************************************************************/
60
 
61
`timescale 1ns/1ps
62
 
63
module sync_fifo
64
  #(
65
    parameter WIDTH    = 32,
66
    parameter DEPTH    = 16,
67
    parameter STYLE    = "SRL",  //Choices: SRL, REG, BRAM
68
    parameter AFASSERT = DEPTH-1,
69
    parameter AEASSERT = 1,
70
    parameter FWFT     = 0,
71
    parameter SUP_REWIND = 0,
72
    parameter INIT_OUTREG = 0,
73
    parameter ADDRW = (DEPTH<=2)    ? 1:
74
                      (DEPTH<=4)    ? 2:
75
                      (DEPTH<=8)    ? 3:
76
                      (DEPTH<=16)   ? 4:
77
                      (DEPTH<=32)   ? 5:
78
                      (DEPTH<=64)   ? 6:
79
                      (DEPTH<=128)  ? 7:
80
                      (DEPTH<=256)  ? 8:
81
                      (DEPTH<=512)  ? 9:
82
                      (DEPTH<=1024) ?10:
83
                      (DEPTH<=2048) ?11:
84
                      (DEPTH<=4096) ?12:
85
                      (DEPTH<=8192) ?13:
86
                      (DEPTH<=16384)?14: -1
87
   )
88
   (
89
   input  wire             clk,
90
   input  wire             rst_n,
91
   input  wire [WIDTH-1:0] din,
92
   output wire [WIDTH-1:0] dout,
93
   input  wire             wr_en,
94
   input  wire             rd_en,
95
   output reg              full,
96
   output reg              afull,
97
   output wire             empty,
98
   output wire             aempty,
99
   output wire [ADDRW:0]   data_count,
100
   //rewind stuff
101
   input  wire             mark_addr,
102
   input  wire             clear_addr,
103
   input  wire             rewind
104
   );
105
 
106
 
107
   parameter TCQ = 1;
108
   reg    [WIDTH-1:0] regBank         [DEPTH-1:0];
109
   wire   [WIDTH-1:0] dout_int;
110
   reg    [ADDRW:0]   data_count_int;
111
   wire   [ADDRW-1:0] data_count_int_trunc;
112
   reg    [ADDRW:0]   data_count_m1;
113
   wire   [ADDRW-1:0] data_count_m1_trunc;
114
   wire   [ADDRW:0]   data_count_pkt;
115
   reg    [ADDRW:0]   data_count_pkt_up;
116
   reg    [ADDRW:0]   data_count_pkt_down;
117
   reg    [ADDRW-1:0] bram_waddr;
118
   reg    [ADDRW-1:0] bram_raddr;
119
   reg    [ADDRW-1:0] rewind_addr;
120
   reg    [ADDRW-1:0] packet_size_int;
121
   reg                clear_addr_d;
122
   reg                empty_int;
123
   reg                aempty_int;
124
   reg    [WIDTH-1:0] output_stage;
125
   reg                output_stage_empty;
126
   wire               wr_en_int;
127
   wire               rd_en_fwft;
128
   reg                internal_fifo_newdata = 0;
129
   wire               internal_fifo_newdata_take;
130
   integer            i,ii;
131
 
132
 
133
//{{{ Choose external IO drivers based on mode
134
// Read Enable must be qualified with Empty; for FWFT, internal logic drives
135
assign rd_en_int = FWFT ? rd_en_fwft : (rd_en && !empty_int);
136
// Write Enable must be qualified with Full
137
assign wr_en_int = wr_en && !full && !(SUP_REWIND && rewind);
138
// Dout is the output register stage in FWFT mode
139
assign dout   = FWFT ? output_stage : dout_int;
140
//Empty indicates that the output stage is not valid in FWFT mode
141
assign empty  = FWFT ? output_stage_empty : empty_int;
142
//Aempty may be assert 1 cycle soon for FWFT
143
assign aempty = FWFT ? (aempty_int || output_stage_empty) : aempty_int;
144
assign data_count = data_count_int;
145
//}}}
146
 
147
assign data_count_int_trunc = data_count_int[ADDRW-1:0];
148
assign data_count_m1_trunc  = data_count_m1[ADDRW-1:0];
149
 
150
//{{{ Infer Memory 
151
//{{{ SRL 16 should be inferred
152
generate if (STYLE=="SRL")  begin: srl_style_fifo
153
   always @(posedge clk) begin
154
      if (wr_en_int) begin
155
         for (i=(DEPTH-1); i>0; i=i-1)
156
            regBank[i] <= #TCQ regBank[i-1];
157
         regBank[0]    <= #TCQ din;
158
      end
159
   end
160
 
161
   assign dout_int = FWFT ? regBank[data_count_m1_trunc] : regBank[data_count_int_trunc];
162
 
163
   initial begin
164
      for (ii=(DEPTH-1); ii>=0; ii=ii-1) regBank[ii] = INIT_OUTREG;
165
   end
166
//}}}
167
//{{{ SRL 16 w/Registered output should be inferred
168
end else if (STYLE=="SRLREG")  begin: srlreg_style_fifo
169
   reg    [WIDTH-1:0] dout_reg = INIT_OUTREG;
170
 
171
   always @(posedge clk) begin
172
      if (wr_en_int) begin
173
         for (i=(DEPTH-1); i>0; i=i-1)
174
            regBank[i] <= #TCQ regBank[i-1];
175
         regBank[0]    <= #TCQ din;
176
      end
177
   end
178
 
179
   always @(posedge clk or negedge rst_n) begin
180
      if (!rst_n)
181
        dout_reg <= #TCQ INIT_OUTREG;
182
      else if (rd_en_int) begin
183
         dout_reg    <= #TCQ regBank[data_count_m1_trunc]; //"m1" points to latest data
184
      end
185
   end
186
 
187
   assign dout_int = dout_reg;
188
 
189
   initial begin
190
      for (ii=(DEPTH-1); ii>=0; ii=ii-1) regBank[ii] = INIT_OUTREG;
191
   end
192
//}}}
193
//{{{ BRAM(s) should be inferred
194
end else if (STYLE=="BRAM") begin: bram_style_fifo
195
   reg    [WIDTH-1:0] dout_reg;
196
 
197
   always @(posedge clk) begin
198
      if (wr_en_int) begin
199
         regBank[bram_waddr]    <= #TCQ din;
200
      end
201
   end
202
 
203
   always @(posedge clk) begin
204
      if (rd_en_int) begin
205
         dout_reg    <= #TCQ regBank[bram_raddr];
206
      end
207
   end
208
 
209
   assign dout_int = dout_reg;
210
 
211
//}}}
212
//{{{ REGISTERs should be inferred
213
end else begin: reg_style_fifo //STYLE==REG
214
   reg    [WIDTH-1:0] dout_reg = INIT_OUTREG;
215
 
216
   always @(posedge clk or negedge rst_n) begin
217
      if (!rst_n)
218
         for (i=(DEPTH-1); i>=0; i=i-1) regBank[i] <= #TCQ INIT_OUTREG;
219
      else if (wr_en_int) begin
220
         for (i=(DEPTH-1); i>0; i=i-1)  regBank[i] <= #TCQ regBank[i-1];
221
         regBank[0]    <= #TCQ din;
222
      end
223
   end
224
 
225
   always @(posedge clk or negedge rst_n) begin
226
      if (!rst_n)
227
        dout_reg <= #TCQ INIT_OUTREG;
228
      else if (rd_en_int)
229
        dout_reg <= #TCQ regBank[data_count_m1_trunc];
230
   end
231
 
232
   assign dout_int = dout_reg;
233
 
234
end
235
endgenerate
236
//}}}
237
//}}}
238
 
239
//{{{ SRL/Reg Address Logic; SRL/Reg/BRAM flag logic
240
always @(posedge clk or negedge rst_n) begin
241
    if (!rst_n) begin
242
       data_count_int  <= #TCQ 'h0;
243
       data_count_m1   <= #TCQ {(ADDRW+1){1'b1}};
244
       full            <= #TCQ 1'b0;
245
       afull           <= #TCQ 1'b0;
246
    // read from non-empty FIFO, not writing to FIFO
247
    end else if (rd_en_int && !wr_en_int) begin
248
       data_count_int  <= #TCQ data_count_int - 1;
249
       data_count_m1   <= #TCQ data_count_m1  - 1;
250
       full            <= #TCQ 1'b0;
251
       if (data_count_int == AFASSERT)
252
         afull           <= #TCQ 1'b0;
253
    // write into non-full FIFO, not reading from FIFO
254
    end else if (!rd_en_int && wr_en_int) begin
255
       data_count_int  <= #TCQ data_count_int + 1;
256
       data_count_m1   <= #TCQ data_count_m1  + 1;
257
       if (data_count_int == (DEPTH-1))
258
         full            <= #TCQ 1'b1;
259
       if (data_count_int == (AFASSERT-1))
260
         afull           <= #TCQ 1'b1;
261
    end
262
end
263
 
264
`ifdef SV
265
  //synthesis translate_off
266
  ASSERT_FIFO_OVERFLOW:      assert property (@(posedge clk)
267
    !(data_count_int > DEPTH))                else $fatal;
268
  ASSERT_FIFO_UNDERFLOW:     assert property (@(posedge clk)
269
     (data_count_int=='h0) |-> ##1 !(&data_count_int)) else $fatal;
270
  ASSERT_FIFO_AFULLCHECK1:   assert property (@(posedge clk)
271
    afull  |-> (data_count_int >= AFASSERT)) else $fatal;
272
  ASSERT_FIFO_AFULLCHECK2:   assert property (@(posedge clk)
273
    !afull |-> (data_count_int <  AFASSERT)) else $fatal;
274
  ASSERT_FIFO_AEMPTYCHECK1R: assert property (@(posedge clk)
275
    aempty &&  SUP_REWIND && !FWFT |-> (data_count_pkt <= AEASSERT)) else $fatal;
276
  ASSERT_FIFO_AEMPTYCHECK1 : assert property (@(posedge clk)
277
    aempty && !SUP_REWIND && !FWFT |-> (data_count_int <= AEASSERT)) else $fatal;
278
  ASSERT_FIFO_AEMPTYCHECK2R: assert property (@(posedge clk)
279
   !aempty &&  SUP_REWIND && !FWFT |-> (data_count_pkt >  AEASSERT)) else $fatal;
280
  ASSERT_FIFO_AEMPTYCHECK2 : assert property (@(posedge clk)
281
   !aempty && !SUP_REWIND && !FWFT |-> (data_count_int >  AEASSERT)) else $fatal;
282
  //synthesis translate_on
283
`endif
284
 
285
//}}}
286
 
287
//{{{ BRAM-Style FIFO Address logic
288
generate if (STYLE=="BRAM") begin: gen_bram_address_logic
289
   always @(posedge clk or negedge rst_n) begin
290
     if (!rst_n) begin
291
        bram_waddr  <= #TCQ 'h0;
292
     // Rewind to the stored address
293
     end else if (SUP_REWIND && rewind) begin
294
        bram_waddr  <= #TCQ rewind_addr;
295
     end else if (wr_en_int) begin
296
        bram_waddr  <= #TCQ bram_waddr + 1;
297
     end
298
   end
299
 
300
   always @(posedge clk or negedge rst_n) begin
301
     if (!rst_n) begin
302
        bram_raddr      <= #TCQ 'h0;
303
     end else if (rd_en_int) begin
304
        bram_raddr      <= #TCQ bram_raddr + 1;
305
     end
306
   end
307
end
308
 
309
`ifdef SV
310
  //synthesis translate_off
311
  ASSERT_FIFO_NOTWRITTEN_WHEN_FULL:  assert property (@(posedge clk)
312
    full      && rst_n |-> ##1 $stable(bram_waddr)) else $fatal;
313
  ASSERT_FIFO_NOTWRITTEN_WHEN_EMPTY: assert property (@(posedge clk)
314
    empty_int && rst_n |-> ##1 $stable(bram_raddr)) else $fatal;
315
  ASSERT_FIFO_REWINDNOWRAP:   assert property (@(posedge clk)
316
    SUP_REWIND && rewind && (bram_waddr>=bram_raddr) |-> ##1 (bram_waddr>=bram_raddr)) else $fatal;
317
  ASSERT_FIFO_REWINDWRAP:     assert property (@(posedge clk)
318
    SUP_REWIND && rewind && (bram_waddr< bram_raddr) |-> ##1 (bram_waddr<$past(bram_waddr))||(bram_waddr>=bram_raddr)) else $fatal;
319
  //synthesis translate_on
320
`endif
321
 
322
endgenerate
323
//}}}
324
 
325
 
326
 
327
 
328
 
329
 
330
//{{{ Rewind Capture logic
331
generate if (SUP_REWIND) begin: gen_rewind
332
 
333
   //REWIND Logic: Running count of packet size; location of SOF
334
   always @(posedge clk or negedge rst_n) begin
335
     if (!rst_n) begin
336
        rewind_addr      <= #TCQ 'h0;
337
        packet_size_int  <= #TCQ 'h1;
338
     end else if (wr_en_int) begin
339
        if (mark_addr) begin
340
           rewind_addr     <= #TCQ bram_waddr;
341
           packet_size_int <= #TCQ 'h1;
342
        end else begin
343
           packet_size_int <= #TCQ packet_size_int + 1;
344
        end
345
     end
346
   end
347
 
348
   assign data_count_pkt = data_count_pkt_up + data_count_pkt_down;
349
 
350
   //REWIND Logic: Compute number words in good packets, calculate empty flags
351
   always @(posedge clk or negedge rst_n) begin
352
       if (!rst_n) begin
353
          data_count_pkt_down <= #TCQ 'h0;
354
          data_count_pkt_up  <= #TCQ 'h0;
355
          empty_int       <= #TCQ 1'b1;
356
          aempty_int      <= #TCQ 1'b1;
357
       // read from non-empty FIFO, not writing a packet count
358
       end else if (rd_en_int && !clear_addr_d) begin
359
          data_count_pkt_down <= #TCQ data_count_pkt_down - 1;
360
          data_count_pkt_up   <= #TCQ data_count_pkt_up;
361
          empty_int           <= #TCQ (data_count_pkt <= 1);
362
          aempty_int          <= #TCQ (data_count_pkt <= (AEASSERT+1));
363
       // write packet count, not reading from FIFO
364
       end else if (!rd_en_int && clear_addr_d) begin
365
          data_count_pkt_down <= #TCQ data_count_pkt_down;
366
          data_count_pkt_up   <= #TCQ data_count_pkt_up + packet_size_int;
367
          empty_int           <= #TCQ 1'b0;
368
          aempty_int          <= #TCQ (data_count_pkt + packet_size_int) <= AEASSERT;
369
       // read from non-empty FIFO and writing a packet count
370
       end else if (rd_en_int &&  clear_addr_d) begin
371
          data_count_pkt_down <= #TCQ data_count_pkt_down - 1;
372
          data_count_pkt_up   <= #TCQ data_count_pkt_up + packet_size_int;
373
          empty_int           <= #TCQ 1'b0;
374
          aempty_int          <= #TCQ (data_count_pkt + packet_size_int - 1) <= AEASSERT;
375
       end
376
   end
377
 
378
   //Pipeline
379
   always @(posedge clk or negedge rst_n) begin
380
     if (!rst_n) begin
381
        clear_addr_d        <= #TCQ 1'b0;
382
     end else begin
383
        clear_addr_d        <= #TCQ clear_addr && !rewind;
384
     end
385
   end
386
 
387
 
388
end else begin: gen_norewind
389
 
390
   always @(posedge clk or negedge rst_n) begin
391
       if (!rst_n) begin
392
          empty_int       <= #TCQ 1'b1;
393
          aempty_int      <= #TCQ 1'b1;
394
       // read from non-empty FIFO, not writing to FIFO
395
       end else if (rd_en_int && !wr_en_int) begin
396
          if (data_count_int == 1)
397
            empty_int       <= #TCQ 1'b1;
398
          if (data_count_int == (AEASSERT+1))
399
            aempty_int      <= #TCQ 1'b1;
400
       // write into non-full FIFO, not reading from FIFO
401
       end else if (!rd_en_int && wr_en_int) begin
402
          empty_int       <= #TCQ 1'b0;
403
          if (data_count_int == AEASSERT)
404
            aempty_int      <= #TCQ 1'b0;
405
       end
406
   end
407
 
408
end
409
endgenerate
410
//}}}
411
 
412
 
413
 
414
 
415
 
416
 
417
//{{{ FWFT logic
418
generate if (FWFT) begin: gen_fwft_common
419
   always @(posedge clk or negedge rst_n) begin
420
     if (!rst_n) begin
421
        output_stage       <= #TCQ INIT_OUTREG;
422
        output_stage_empty <= #TCQ 1'b1;
423
     end else if (internal_fifo_newdata_take) begin
424
        output_stage       <= #TCQ dout_int;
425
        output_stage_empty <= #TCQ 1'b0;
426
     end else if (rd_en) begin
427
        output_stage_empty <= #TCQ 1'b1;
428
     end
429
   end
430
end
431
endgenerate
432
 
433
 
434
 
435
 
436
generate if ((FWFT) && (STYLE=="SRL")) begin: gen_fwft_srl
437
 
438
   always @*    internal_fifo_newdata = !empty_int;
439
   assign internal_fifo_newdata_take  = internal_fifo_newdata &&  (output_stage_empty || rd_en);
440
   assign rd_en_fwft = (rd_en || internal_fifo_newdata_take) && !empty_int;
441
 
442
end else if (FWFT) begin: gen_fwft
443
 
444
   always @(posedge clk or negedge rst_n) begin
445
     if (!rst_n) begin
446
        internal_fifo_newdata <= #TCQ 1'b0;
447
     end else if (rd_en_fwft) begin
448
        internal_fifo_newdata <= #TCQ 1'b1;
449
     end else if (internal_fifo_newdata_take) begin
450
        internal_fifo_newdata <= #TCQ 1'b0;
451
     end
452
   end
453
 
454
   assign internal_fifo_newdata_take  = internal_fifo_newdata &&  (output_stage_empty || rd_en);
455
   assign rd_en_fwft = (rd_en || internal_fifo_newdata_take) && !empty_int;
456
 
457
`ifdef SV
458
  //synthesis translate_off
459
  ASSERT_FIFO_FWFTEMPTYCHECK1: assert property (@(posedge clk)
460
    internal_fifo_newdata                     |-> ##1 !empty) else $fatal;
461
  ASSERT_FIFO_FWFTEMPTYCHECK2: assert property (@(posedge clk)
462
    !internal_fifo_newdata && !empty && rd_en |-> ##1  empty) else $fatal;
463
  //synthesis translate_on
464
`endif
465
 
466
end
467
endgenerate
468
//}}}
469
 
470
endmodule

powered by: WebSVN 2.1.0

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