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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_3/] [rtl/] [verilog/] [fifo_control.v] - Blame information for rev 154

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mihad
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "fifo_control.v"                                  ////
4
////                                                              ////
5
////  This file is part of the "PCI bridge" project               ////
6
////  http://www.opencores.org/cores/pci/                         ////
7
////                                                              ////
8
////  Author(s):                                                  ////
9
////      - Miha Dolenc (mihad@opencores.org)                     ////
10
////                                                              ////
11
////  All additional information is avaliable in the README       ////
12
////  file.                                                       ////
13
////                                                              ////
14
////                                                              ////
15
//////////////////////////////////////////////////////////////////////
16
////                                                              ////
17
//// Copyright (C) 2001 Miha Dolenc, mihad@opencores.org          ////
18
////                                                              ////
19
//// This source file may be used and distributed without         ////
20
//// restriction provided that this copyright statement is not    ////
21
//// removed from the file and that any derivative work contains  ////
22
//// the original copyright notice and the associated disclaimer. ////
23
////                                                              ////
24
//// This source file is free software; you can redistribute it   ////
25
//// and/or modify it under the terms of the GNU Lesser General   ////
26
//// Public License as published by the Free Software Foundation; ////
27
//// either version 2.1 of the License, or (at your option) any   ////
28
//// later version.                                               ////
29
////                                                              ////
30
//// This source is distributed in the hope that it will be       ////
31
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
32
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
33
//// PURPOSE.  See the GNU Lesser General Public License for more ////
34
//// details.                                                     ////
35
////                                                              ////
36
//// You should have received a copy of the GNU Lesser General    ////
37
//// Public License along with this source; if not, download it   ////
38
//// from http://www.opencores.org/lgpl.shtml                     ////
39
////                                                              ////
40
//////////////////////////////////////////////////////////////////////
41
//
42
// CVS Revision History
43
//
44
// $Log: not supported by cvs2svn $
45 71 mihad
// Revision 1.6  2002/09/30 16:03:04  mihad
46
// Added meta flop module for easier meta stable FF identification during synthesis
47
//
48 59 mihad
// Revision 1.5  2002/09/25 15:53:52  mihad
49
// Removed all logic from asynchronous reset network
50
//
51 58 mihad
// Revision 1.4  2002/03/05 11:53:47  mihad
52
// Added some testcases, removed un-needed fifo signals
53
//
54 33 mihad
// Revision 1.3  2002/02/01 15:25:12  mihad
55
// Repaired a few bugs, updated specification, added test bench files and design document
56
//
57 21 mihad
// Revision 1.2  2001/10/05 08:14:28  mihad
58
// Updated all files with inclusion of timescale file for simulation purposes.
59
//
60 6 mihad
// Revision 1.1.1.1  2001/10/02 15:33:46  mihad
61
// New project directory structure
62 2 mihad
//
63 6 mihad
//
64 2 mihad
 
65
/* FIFO_CONTROL module provides read/write address and status generation for
66
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
67
 
68 21 mihad
`include "pci_constants.v"
69 6 mihad
 
70 21 mihad
// synopsys translate_off
71 6 mihad
`include "timescale.v"
72 21 mihad
// synopsys translate_on
73 6 mihad
 
74 2 mihad
module FIFO_CONTROL
75
(
76 21 mihad
    rclock_in,
77
    wclock_in,
78
    renable_in,
79
    wenable_in,
80
    reset_in,
81
    flush_in,
82
    full_out,
83
    almost_empty_out,
84
    empty_out,
85
    waddr_out,
86
    raddr_out,
87
    rallow_out,
88 2 mihad
    wallow_out
89
);
90
 
91
// address length parameter - depends on fifo depth
92
parameter ADDR_LENGTH = 7 ;
93
 
94
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
95
input  rclock_in, wclock_in;
96
 
97
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
98
//                 write address changes on rising edge of wclock_in when writes are allowed
99
input  renable_in, wenable_in;
100
 
101
// reset input
102
input  reset_in;
103
 
104
// flush input
105
input flush_in ;
106
 
107 33 mihad
// almost empy status output
108
output almost_empty_out;
109 2 mihad
 
110
// full and empty status outputs
111
output full_out, empty_out;
112
 
113
// read and write addresses outputs
114
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
115
 
116
// read and write allow outputs
117
output rallow_out, wallow_out ;
118
 
119
// read address register
120
reg [(ADDR_LENGTH - 1):0] raddr ;
121
 
122
// write address register
123
reg [(ADDR_LENGTH - 1):0] waddr;
124
assign waddr_out = waddr ;
125
 
126
// grey code registers
127
// grey code pipeline for write address
128
reg [(ADDR_LENGTH - 1):0] wgrey_minus1 ; // one before current grey coded write address
129
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
130
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
131
 
132
// next write gray address calculation - bitwise xor between address and shifted address
133
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
134
 
135
// grey code pipeline for read address
136
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
137
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
138
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
139
 
140
// next read gray address calculation - bitwise xor between address and shifted address
141
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
142
 
143
// FFs for registered empty and full flags
144 59 mihad
wire empty ;
145
wire full ;
146 2 mihad
 
147 33 mihad
// almost_empty tag
148 59 mihad
wire almost_empty ;
149 2 mihad
 
150
// write allow wire - writes are allowed when fifo is not full
151 59 mihad
wire wallow = wenable_in && !full ;
152 2 mihad
 
153
// write allow output assignment
154
assign wallow_out = wallow ;
155
 
156
// read allow wire
157
wire rallow ;
158
 
159
// full output assignment
160
assign full_out  = full ;
161
 
162
// clear generation for FFs and registers
163 58 mihad
wire clear = reset_in /*|| flush_in*/ ; // flush changed to synchronous operation
164 2 mihad
 
165 21 mihad
reg wclock_nempty_detect ;
166 58 mihad
always@(posedge clear or posedge wclock_in)
167 21 mihad
begin
168 58 mihad
    if (clear)
169 21 mihad
        wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
170
    else
171
        wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
172
end
173 2 mihad
 
174 59 mihad
wire stretched_empty ;
175 2 mihad
 
176 59 mihad
wire stretched_empty_flop_i = empty && !wclock_nempty_detect ;
177
 
178
meta_flop #(1) i_meta_flop_stretched_empty
179
(
180
    .rst_i      (clear),
181
    .clk_i      (rclock_in),
182
    .ld_i       (1'b0),
183
    .ld_val_i   (1'b0),
184
    .en_i       (1'b1),
185
    .d_i        (stretched_empty_flop_i),
186
    .meta_q_o   (stretched_empty)
187
) ;
188
 
189 21 mihad
// empty output is actual empty + 1 read clock cycle ( stretched empty )
190
assign empty_out = empty || stretched_empty ;
191 2 mihad
 
192 21 mihad
//rallow generation
193 59 mihad
assign rallow = renable_in && !empty && !stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
194 2 mihad
 
195 21 mihad
// rallow output assignment
196
assign rallow_out = rallow ;
197 2 mihad
 
198 21 mihad
// almost empty output assignment
199 59 mihad
assign almost_empty_out = almost_empty && !empty && !stretched_empty ;
200 2 mihad
 
201 21 mihad
// at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
202
// when FIFO is empty, this register provides actual read address, so first location can be read
203
reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
204 2 mihad
 
205 21 mihad
// address output mux - when FIFO is not read, current actual address is driven out, when it is read, next address is driven out to provide
206
// next data immediately
207
// done for zero wait state burst operation
208
assign raddr_out = rallow ? raddr_plus_one : raddr ;
209 2 mihad
 
210 21 mihad
always@(posedge rclock_in or posedge clear)
211
begin
212
    if (clear)
213 71 mihad
    begin
214
        // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
215 33 mihad
        raddr_plus_one <= #`FF_DELAY 4 ;
216 71 mihad
        raddr          <= #`FF_DELAY 3 ;
217
    end
218 58 mihad
    else if (flush_in)
219 71 mihad
    begin
220 58 mihad
        raddr_plus_one <= #`FF_DELAY waddr + 1'b1 ;
221 71 mihad
        raddr          <= #`FF_DELAY waddr ;
222
    end
223 21 mihad
    else if (rallow)
224 71 mihad
    begin
225 21 mihad
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
226 71 mihad
        raddr          <= #`FF_DELAY raddr_plus_one ;
227
    end
228 21 mihad
end
229 2 mihad
 
230
/*-----------------------------------------------------------------------------------------------
231
Read address control consists of Read address counter and Grey Address pipeline
232 21 mihad
There are 4 Grey addresses:
233 2 mihad
    - rgrey_minus1 is Grey Code of address one before current address
234
    - rgrey_addr is Grey Code of current read address
235
    - rgrey_next is Grey Code of next read address
236
--------------------------------------------------------------------------------------------------*/
237 71 mihad
// grey coded address pipeline for status generation in read clock domain
238 2 mihad
always@(posedge rclock_in or posedge clear)
239
begin
240 21 mihad
    if (clear)
241 71 mihad
    begin
242 33 mihad
        rgrey_minus1 <= #`FF_DELAY 0 ;
243 71 mihad
        rgrey_addr   <= #`FF_DELAY 1 ;
244
        rgrey_next   <= #`FF_DELAY 3 ; // this grey code is calculated from the current binary address and loaded any time data is read from fifo
245
    end
246 58 mihad
    else if (flush_in)
247 71 mihad
    begin
248
        // when fifo is flushed, load the register values from the write clock domain.
249
        // must be no problem, because write pointers are stable for at least 3 clock cycles before flush can occur.
250 58 mihad
        rgrey_minus1 <= #`FF_DELAY wgrey_minus1 ;
251 71 mihad
        rgrey_addr   <= #`FF_DELAY wgrey_addr ;
252
        rgrey_next   <= #`FF_DELAY wgrey_next ;
253
    end
254 58 mihad
    else if (rallow)
255 71 mihad
    begin
256
        // move the pipeline when data is read from fifo and calculate new value for first stage of pipeline from current binary fifo address
257 21 mihad
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
258 71 mihad
        rgrey_addr   <= #`FF_DELAY rgrey_next ;
259
        rgrey_next   <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
260
    end
261 2 mihad
end
262
 
263
/*--------------------------------------------------------------------------------------------
264
Write address control consists of write address counter and three Grey Code Registers:
265
    - wgrey_minus1 represents Grey Coded address of location one before current write address
266
    - wgrey_addr represents current Grey Coded write address
267
    - wgrey_next represents Grey Coded next write address
268
----------------------------------------------------------------------------------------------*/
269 71 mihad
// grey coded address pipeline for status generation in write clock domain
270 2 mihad
always@(posedge wclock_in or posedge clear)
271
begin
272 21 mihad
    if (clear)
273 2 mihad
    begin
274 33 mihad
        // initial value is 0
275
        wgrey_minus1 <= #`FF_DELAY 0 ;
276 71 mihad
        wgrey_addr   <= #`FF_DELAY 1 ;
277
        wgrey_next   <= #`FF_DELAY 3 ;
278 2 mihad
    end
279 21 mihad
    else
280 2 mihad
    if (wallow)
281 71 mihad
    begin
282 21 mihad
        wgrey_minus1 <= #`FF_DELAY wgrey_addr ;
283 71 mihad
        wgrey_addr   <= #`FF_DELAY wgrey_next ;
284
        wgrey_next   <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
285 2 mihad
    end
286
end
287
 
288 71 mihad
// write address binary counter - nothing special except initial value
289 2 mihad
always@(posedge wclock_in or posedge clear)
290
begin
291 21 mihad
    if (clear)
292 33 mihad
        // initial value 3
293
        waddr <= #`FF_DELAY 3 ;
294 21 mihad
    else
295
    if (wallow)
296
        waddr <= #`FF_DELAY waddr + 1'b1 ;
297 2 mihad
end
298
 
299
/*------------------------------------------------------------------------------------------------------------------------------
300
Registered full control:
301 21 mihad
registered full is set on rising edge of wclock_in, when fifo is almost full and something gets written to it.
302 2 mihad
It's kept high until something is read from FIFO, which is registered on next rising write clock edge.
303
 
304
Registered almost full control:
305
Almost full flag is set on rising write clock edge whenever two free locations are left in fifo and another entry is written to it.
306
It remains set if nothing is read/written from/to fifo. All operations are synchronized on write clock.
307
--------------------------------------------------------------------------------------------------------------------------------*/
308
wire comb_full          = wgrey_next == rgrey_addr ;
309 33 mihad
wire comb_almost_full   = wgrey_next == rgrey_minus1 ;
310 2 mihad
 
311
//combinatorial input to Registered full FlipFlop
312
wire reg_full = (wallow && comb_almost_full) || (comb_full) ;
313
 
314 59 mihad
meta_flop #(0) i_meta_flop_full
315
(
316
    .rst_i      (clear),
317
    .clk_i      (wclock_in),
318
    .ld_i       (1'b0),
319
    .ld_val_i   (1'b0),
320
    .en_i       (1'b1),
321
    .d_i        (reg_full),
322
    .meta_q_o   (full)
323
) ;
324 2 mihad
 
325
/*------------------------------------------------------------------------------------------------------------------------------
326
Registered empty control:
327
registered empty is set on rising edge of rclock_in when one location is occupied and read from it. It remains set until
328
something is written to fifo which is detected on next read clock edge.
329
 
330
Registered almost empty control:
331
Almost empty is set on rising clock edge of read clock when two locations are used in fifo and one of them is read from it.
332
It remains set until something is read/written from/to fifo. All operations are detected on rising edge of read clock.
333
--------------------------------------------------------------------------------------------------------------------------------*/
334
wire comb_almost_empty  = rgrey_next == wgrey_addr ;
335
wire comb_empty         = rgrey_addr == wgrey_addr ;
336
wire comb_two_used      = rgrey_next == wgrey_minus1 ;
337
 
338
// combinatorial input for registered emty FlipFlop
339
wire reg_empty = (rallow && comb_almost_empty) || comb_empty ;
340
 
341 59 mihad
// meta flop for empty signal instantiation - reset value 1, load value (flush) 1 etc..
342
meta_flop #(1) i_meta_flop_empty
343
(
344
    .rst_i      (clear),
345
    .clk_i      (rclock_in),
346
    .ld_i       (flush_in),
347
    .ld_val_i   (1'b1),
348
    .en_i       (1'b1),
349
    .d_i        (reg_empty),
350
    .meta_q_o   (empty)
351
) ;
352 2 mihad
 
353
// input for almost empty flip flop
354
wire reg_almost_empty = rallow && comb_two_used || comb_almost_empty ;
355
 
356 59 mihad
meta_flop #(0) i_meta_flop_almost_empty
357
(
358
    .rst_i      (clear),
359
    .clk_i      (rclock_in),
360
    .ld_i       (flush_in),
361
    .ld_val_i   (1'b0),
362
    .en_i       (1'b1),
363
    .d_i        (reg_almost_empty),
364
    .meta_q_o   (almost_empty)
365
) ;
366
 
367 2 mihad
endmodule

powered by: WebSVN 2.1.0

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