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

Subversion Repositories pci

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

powered by: WebSVN 2.1.0

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