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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_00/] [rtl/] [verilog/] [wbw_fifo_control.v] - Blame information for rev 41

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mihad
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "wbw_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 21 mihad
// Revision 1.2  2001/10/05 08:14:30  mihad
46
// Updated all files with inclusion of timescale file for simulation purposes.
47
//
48 6 mihad
// Revision 1.1.1.1  2001/10/02 15:33:47  mihad
49
// New project directory structure
50 2 mihad
//
51 6 mihad
//
52 2 mihad
 
53
/* FIFO_CONTROL module provides read/write address and status generation for
54
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
55 21 mihad
`include "pci_constants.v"
56
// synopsys translate_off
57 6 mihad
`include "timescale.v"
58 21 mihad
// synopsys translate_on
59
 
60 2 mihad
module WBW_FIFO_CONTROL
61
(
62 21 mihad
    rclock_in,
63
    wclock_in,
64
    renable_in,
65
    wenable_in,
66
    reset_in,
67
    flush_in,
68
    almost_full_out,
69
    full_out,
70
    empty_out,
71
    waddr_out,
72
    raddr_out,
73
    rallow_out,
74 2 mihad
    wallow_out
75
);
76
 
77
parameter ADDR_LENGTH = 7 ;
78
 
79
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
80
input  rclock_in, wclock_in;
81
 
82
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
83
//                 write address changes on rising edge of wclock_in when writes are allowed
84
input  renable_in, wenable_in ;
85
 
86
// reset input
87
input  reset_in;
88
 
89
// flush input
90
input flush_in ;
91
 
92
// almost full and empy status outputs
93
output almost_full_out ;
94
 
95
// full and empty status outputs
96
output full_out, empty_out;
97
 
98
// read and write addresses outputs
99
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
100
 
101
// read and write allow outputs
102
output rallow_out, wallow_out ;
103
 
104
// read address register
105
reg [(ADDR_LENGTH - 1):0] raddr ;
106
 
107
// write address register
108
reg [(ADDR_LENGTH - 1):0] waddr;
109
assign waddr_out = waddr ;
110
 
111
// grey code registers
112
// grey code pipeline for write address
113
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
114
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
115
 
116
// next write gray address calculation - bitwise xor between address and shifted address
117
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
118
 
119
// grey code pipeline for read address
120
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
121
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
122
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
123
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
124
 
125
// next read gray address calculation - bitwise xor between address and shifted address
126
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
127
 
128
// FFs for registered empty and full flags
129
reg empty ;
130
reg full ;
131
 
132
// almost_full tag
133
reg almost_full ;
134
 
135
// write allow wire - writes are allowed when fifo is not full
136
wire wallow = wenable_in && ~full ;
137
 
138
// write allow output assignment
139
assign wallow_out = wallow && ~full ;
140
 
141
// read allow wire
142
wire rallow ;
143
 
144
// full output assignment
145
assign full_out  = full ;
146
 
147
// almost full output assignment
148
assign almost_full_out  = almost_full && ~full ;
149
 
150
// clear generation for FFs and registers
151
wire clear = reset_in || flush_in ;
152
 
153 21 mihad
reg wclock_nempty_detect ;
154
always@(posedge reset_in or posedge wclock_in)
155
begin
156
    if (reset_in)
157
        wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
158
    else
159
        wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
160
end
161 2 mihad
 
162 21 mihad
// special synchronizing mechanism for different implementations - in synchronous imp., empty is prolonged for 1 clock edge if no write clock comes after initial write
163
reg stretched_empty ;
164
always@(posedge rclock_in or posedge clear)
165
begin
166
    if(clear)
167
        stretched_empty <= #`FF_DELAY 1'b1 ;
168
    else
169
        stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
170
end
171 2 mihad
 
172 21 mihad
// empty output is actual empty + 1 read clock cycle ( stretched empty )
173
assign empty_out = empty || stretched_empty ;
174 2 mihad
 
175 21 mihad
//rallow generation
176
assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
177 2 mihad
 
178 21 mihad
// rallow output assignment
179
assign rallow_out = rallow ;
180 2 mihad
 
181 21 mihad
// at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
182
// when FIFO is empty, this register provides actual read address, so first location can be read
183
reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
184 2 mihad
 
185 21 mihad
// address output mux - when FIFO is empty, current actual address is driven out, when it is non - empty next address is driven out
186
// done for zero wait state burst
187
assign raddr_out = rallow ? raddr_plus_one : raddr ;
188 2 mihad
 
189 21 mihad
always@(posedge rclock_in or posedge clear)
190
begin
191
    if (clear)
192 2 mihad
    begin
193 21 mihad
        // initial value is important - raddr initial value is 4, so this one is 5
194
        raddr_plus_one <= #`FF_DELAY 5 ;
195 2 mihad
    end
196 21 mihad
    else if (rallow)
197
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
198
end
199 2 mihad
 
200 21 mihad
// raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
201
always@(posedge rclock_in or posedge clear)
202
begin
203
    if (clear)
204
        // initial value is 4
205
    raddr <= #`FF_DELAY 4 ;
206
    else if (rallow)
207
        raddr <= #`FF_DELAY raddr_plus_one ;
208
end
209 2 mihad
 
210
/*-----------------------------------------------------------------------------------------------
211
Read address control consists of Read address counter and Grey Address pipeline
212 21 mihad
There are 4 Grey addresses:
213 2 mihad
    - rgrey_minus2 is Grey Code of address two before current address
214
    - rgrey_minus1 is Grey Code of address one before current address
215
    - rgrey_addr is Grey Code of current read address
216
    - rgrey_next is Grey Code of next read address
217
--------------------------------------------------------------------------------------------------*/
218
 
219
// grey code register for two before read address
220
always@(posedge rclock_in or posedge clear)
221
begin
222
        if (clear)
223
    begin
224 21 mihad
        // initial value is 0
225
        rgrey_minus2 <= #`FF_DELAY 0 ;
226 2 mihad
    end
227 21 mihad
    else
228
    if (rallow)
229
        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
230 2 mihad
end
231
 
232
// grey code register for one before read address
233
always@(posedge rclock_in or posedge clear)
234
begin
235 21 mihad
    if (clear)
236 2 mihad
    begin
237 21 mihad
        // initial value is 1
238
        rgrey_minus1 <= #`FF_DELAY 1 ;
239 2 mihad
    end
240 21 mihad
    else
241
    if (rallow)
242
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
243 2 mihad
end
244
 
245
// grey code register for read address - represents current Read Address
246
always@(posedge rclock_in or posedge clear)
247
begin
248 21 mihad
    if (clear)
249 2 mihad
    begin
250 21 mihad
        // initial value is 3 = ...00011
251
        rgrey_addr <= #`FF_DELAY 3 ;
252 2 mihad
    end
253 21 mihad
    else
254
    if (rallow)
255
        rgrey_addr <= #`FF_DELAY rgrey_next ;
256 2 mihad
end
257
 
258 21 mihad
// grey code register for next read address - represents Grey Code of next read address
259 2 mihad
always@(posedge rclock_in or posedge clear)
260
begin
261 21 mihad
    if (clear)
262 2 mihad
    begin
263 21 mihad
        // initial value is 2 = ...00010
264
        rgrey_next <= #`FF_DELAY 2 ;
265 2 mihad
    end
266 21 mihad
    else
267
    if (rallow)
268
        rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
269 2 mihad
end
270
 
271
/*--------------------------------------------------------------------------------------------
272
Write address control consists of write address counter and two Grey Code Registers:
273
    - wgrey_addr represents current Grey Coded write address
274
    - wgrey_next represents Grey Coded next write address
275
----------------------------------------------------------------------------------------------*/
276
// grey code register for write address
277
always@(posedge wclock_in or posedge clear)
278
begin
279 21 mihad
    if (clear)
280 2 mihad
    begin
281 21 mihad
        // initial value is 3 = ....011
282
        wgrey_addr <= #`FF_DELAY 3 ;
283 2 mihad
    end
284 21 mihad
    else
285
    if (wallow)
286
        wgrey_addr <= #`FF_DELAY wgrey_next ;
287 2 mihad
end
288
 
289
// grey code register for next write address
290
always@(posedge wclock_in or posedge clear)
291
begin
292 21 mihad
    if (clear)
293 2 mihad
    begin
294 21 mihad
        // initial value is 2 = ...010
295
        wgrey_next <= #`FF_DELAY 2 ;
296 2 mihad
    end
297 21 mihad
    else
298
    if (wallow)
299
        wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
300 2 mihad
end
301
 
302 21 mihad
// write address counter - nothing special - initial value is important though
303 2 mihad
always@(posedge wclock_in or posedge clear)
304
begin
305 21 mihad
    if (clear)
306
        // initial value 4
307
        waddr <= #`FF_DELAY 4 ;
308
    else
309
    if (wallow)
310
        waddr <= #`FF_DELAY waddr + 1'b1 ;
311 2 mihad
end
312
 
313
/*------------------------------------------------------------------------------------------------------------------------------
314
Registered full control:
315
registered full is set on rising edge of wclock_in when there is one free location in and another written to fifo
316
It's kept high until something is read from FIFO, which is registered on
317
next rising write clock edge.
318
 
319
Registered almost full control:
320
Almost full flag is set on rising wclock_in edge when there are two unused locations left in and another written to fifo.
321
It is set until something is read/written from/to fifo
322
--------------------------------------------------------------------------------------------------------------------------------*/
323
//combinatorial input to Registered full FlipFlop
324
wire reg_full = wallow && (wgrey_next == rgrey_minus1) || (wgrey_next == rgrey_addr) ;
325
 
326
always@(posedge wclock_in or posedge clear)
327
begin
328
        if (clear)
329
                full <= #`FF_DELAY 1'b0 ;
330
        else
331
                full <= #`FF_DELAY reg_full ;
332
end
333
 
334
// input for almost full latch
335
wire reg_almost_full_in = wallow && (wgrey_next == rgrey_minus2) || (wgrey_next == rgrey_minus1) ;
336
 
337
always@(posedge clear or posedge wclock_in)
338
begin
339
    if (clear)
340
        almost_full <= #`FF_DELAY 1'b0 ;
341
    else
342
        almost_full <= #`FF_DELAY reg_almost_full_in ;
343
end
344
 
345
/*------------------------------------------------------------------------------------------------------------------------------
346
Registered empty control:
347
registered empty is set on rising edge of rclock_in when one location is used and read from fifo. It's kept high
348
until something is written to the fifo, which is registered on the next clock edge.
349
 
350
Registered almost empty control:
351
Almost empty is set on rising edge of rclock_in when two locations are used and one read. It's kept set until something
352
is read/written from/to fifo.
353
--------------------------------------------------------------------------------------------------------------------------------*/
354
// combinatorial input for registered emty FlipFlop
355
wire comb_almost_empty = (rgrey_next == wgrey_addr) ;
356
wire comb_empty        = (rgrey_addr == wgrey_addr) ;
357
wire reg_empty         = renable_in && comb_almost_empty  || comb_empty ;
358
 
359
always@(posedge rclock_in or posedge clear)
360
begin
361
    if (clear)
362
        empty <= #`FF_DELAY 1'b1 ;
363
        else
364
        empty <= #`FF_DELAY reg_empty ;
365
end
366
 
367
endmodule

powered by: WebSVN 2.1.0

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