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

Subversion Repositories pci

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

powered by: WebSVN 2.1.0

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