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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_9/] [rtl/] [verilog/] [pci_pcir_fifo_control.v] - Blame information for rev 104

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

Line No. Rev Author Line
1 77 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 104 mihad
// Revision 1.2  2003/03/26 13:16:18  mihad
46
// Added the reset value parameter to the synchronizer flop module.
47
// Added resets to all synchronizer flop instances.
48
// Repaired initial sync value in fifos.
49
//
50 88 mihad
// Revision 1.1  2003/01/27 16:49:31  mihad
51
// Changed module and file names. Updated scripts accordingly. FIFO synchronizations changed.
52
//
53 77 mihad
// Revision 1.7  2002/11/27 20:36:10  mihad
54
// Changed the code a bit to make it more readable.
55
// Functionality not changed in any way.
56
// More robust synchronization in fifos is still pending.
57
//
58
// Revision 1.6  2002/09/30 16:03:04  mihad
59
// Added meta flop module for easier meta stable FF identification during synthesis
60
//
61
// Revision 1.5  2002/09/25 15:53:52  mihad
62
// Removed all logic from asynchronous reset network
63
//
64
// Revision 1.4  2002/03/05 11:53:47  mihad
65
// Added some testcases, removed un-needed fifo signals
66
//
67
// Revision 1.3  2002/02/01 15:25:12  mihad
68
// Repaired a few bugs, updated specification, added test bench files and design document
69
//
70
// Revision 1.2  2001/10/05 08:14:28  mihad
71
// Updated all files with inclusion of timescale file for simulation purposes.
72
//
73
// Revision 1.1.1.1  2001/10/02 15:33:46  mihad
74
// New project directory structure
75
//
76
//
77
 
78
/* FIFO_CONTROL module provides read/write address and status generation for
79
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
80
 
81
`include "pci_constants.v"
82
 
83
// synopsys translate_off
84
`include "timescale.v"
85
// synopsys translate_on
86
 
87
module pci_pcir_fifo_control
88
(
89
    rclock_in,
90
    wclock_in,
91
    renable_in,
92
    wenable_in,
93
    reset_in,
94
    flush_in,
95
    full_out,
96
    almost_empty_out,
97
    empty_out,
98
    waddr_out,
99
    raddr_out,
100
    rallow_out,
101
    wallow_out
102
);
103
 
104
// address length parameter - depends on fifo depth
105
parameter ADDR_LENGTH = 7 ;
106
 
107
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
108
input  rclock_in, wclock_in;
109
 
110
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
111
//                 write address changes on rising edge of wclock_in when writes are allowed
112
input  renable_in, wenable_in;
113
 
114
// reset input
115
input  reset_in;
116
 
117
// flush input
118
input flush_in ;
119
 
120
// almost empy status output
121
output almost_empty_out;
122
 
123
// full and empty status outputs
124
output full_out, empty_out;
125
 
126
// read and write addresses outputs
127
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
128
 
129
// read and write allow outputs
130
output rallow_out, wallow_out ;
131
 
132
// read address register
133
reg [(ADDR_LENGTH - 1):0] raddr ;
134
 
135
// write address register
136
reg [(ADDR_LENGTH - 1):0] waddr;
137
assign waddr_out = waddr ;
138
 
139
// grey code registers
140
// grey code pipeline for write address
141
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current grey coded write address
142
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next grey coded write address
143
 
144
// next write gray address calculation - bitwise xor between address and shifted address
145
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
146
 
147
// grey code pipeline for read address
148
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
149
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
150
 
151
// next read gray address calculation - bitwise xor between address and shifted address
152
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
153
 
154
// FFs for registered empty and full flags
155
wire empty ;
156
wire full ;
157
 
158
// almost_empty tag
159
wire almost_empty ;
160
 
161
// write allow wire - writes are allowed when fifo is not full
162
wire wallow = wenable_in && !full ;
163
 
164
// write allow output assignment
165
assign wallow_out = wallow ;
166
 
167
// read allow wire
168
wire rallow ;
169
 
170
// full output assignment
171
assign full_out  = full ;
172
 
173
// clear generation for FFs and registers
174
wire clear = reset_in /*|| flush_in*/ ; // flush changed to synchronous operation
175
 
176
assign empty_out = empty ;
177
 
178
//rallow generation
179
assign rallow = renable_in && !empty ; // reads allowed if read enable is high and FIFO is not empty
180
 
181
// rallow output assignment
182
assign rallow_out = rallow ;
183
 
184
// almost empty output assignment
185
assign almost_empty_out = almost_empty ;
186
 
187
// at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
188
// when FIFO is empty, this register provides actual read address, so first location can be read
189
reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
190
 
191
// 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
192
// next data immediately
193
// done for zero wait state burst operation
194
assign raddr_out = rallow ? raddr_plus_one : raddr ;
195
 
196
always@(posedge rclock_in or posedge clear)
197
begin
198
    if (clear)
199
    begin
200
        // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
201
        raddr_plus_one <= #`FF_DELAY 3 ;
202
        raddr          <= #`FF_DELAY 2 ;
203
    end
204
    else if (flush_in)
205
    begin
206
        raddr_plus_one <= #`FF_DELAY waddr + 1'b1 ;
207
        raddr          <= #`FF_DELAY waddr ;
208
    end
209
    else if (rallow)
210
    begin
211
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
212
        raddr          <= #`FF_DELAY raddr_plus_one ;
213
    end
214
end
215
 
216
/*-----------------------------------------------------------------------------------------------
217
Read address control consists of Read address counter and Grey Address pipeline
218
There are 2 Grey addresses:
219
    - rgrey_addr is Grey Code of current read address
220
    - rgrey_next is Grey Code of next read address
221
--------------------------------------------------------------------------------------------------*/
222
// grey coded address pipeline for status generation in read clock domain
223
always@(posedge rclock_in or posedge clear)
224
begin
225
    if (clear)
226
    begin
227 104 mihad
        rgrey_addr   <= #1 0 ;
228 77 mihad
        rgrey_next   <= #`FF_DELAY 1 ; // this grey code is calculated from the current binary address and loaded any time data is read from fifo
229
    end
230
    else if (flush_in)
231
    begin
232
        // when fifo is flushed, load the register values from the write clock domain.
233
        // must be no problem, because write pointers are stable for at least 3 clock cycles before flush can occur.
234 104 mihad
        rgrey_addr   <= #1 wgrey_addr ;
235 77 mihad
        rgrey_next   <= #`FF_DELAY wgrey_next ;
236
    end
237
    else if (rallow)
238
    begin
239
        // move the pipeline when data is read from fifo and calculate new value for first stage of pipeline from current binary fifo address
240 104 mihad
        rgrey_addr   <= #1 rgrey_next ;
241 77 mihad
        rgrey_next   <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
242
    end
243
end
244
 
245
/*--------------------------------------------------------------------------------------------
246
Write address control consists of write address counter and 2 Grey Code Registers:
247
    - wgrey_addr represents current Grey Coded write address
248
    - wgrey_next represents Grey Coded next write address
249
----------------------------------------------------------------------------------------------*/
250
// grey coded address pipeline for status generation in write clock domain
251
always@(posedge wclock_in or posedge clear)
252
begin
253
    if (clear)
254
    begin
255 104 mihad
        wgrey_addr   <= #1 0 ;
256 77 mihad
        wgrey_next   <= #`FF_DELAY 1 ;
257
    end
258
    else
259
    if (wallow)
260
    begin
261 104 mihad
        wgrey_addr   <= #1 wgrey_next ;
262 77 mihad
        wgrey_next   <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
263
    end
264
end
265
 
266
// write address binary counter - nothing special except initial value
267
always@(posedge wclock_in or posedge clear)
268
begin
269
    if (clear)
270
        // initial value 2
271
        waddr <= #`FF_DELAY 2 ;
272
    else
273
    if (wallow)
274
        waddr <= #`FF_DELAY waddr + 1'b1 ;
275
end
276
 
277
/*------------------------------------------------------------------------------------------------------------------------------
278
Full control:
279
Gray coded read address pointer is synchronized to write clock domain and compared to Gray coded next write address.
280
If they are equal, fifo is full.
281
--------------------------------------------------------------------------------------------------------------------------------*/
282
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_addr ;
283
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_addr ;
284 88 mihad
synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_rgrey_addr
285 77 mihad
(
286
    .data_in        (rgrey_addr),
287
    .clk_out        (wclock_in),
288
    .sync_data_out  (wclk_sync_rgrey_addr),
289 88 mihad
    .async_reset    (clear)
290 77 mihad
) ;
291
 
292 88 mihad
always@(posedge wclock_in or posedge clear)
293 77 mihad
begin
294 88 mihad
    if (clear)
295
        wclk_rgrey_addr <= #`FF_DELAY 0 ;
296
    else
297
        wclk_rgrey_addr <= #`FF_DELAY wclk_sync_rgrey_addr ;
298 77 mihad
end
299
 
300
assign full = (wgrey_next == wclk_rgrey_addr) ;
301
 
302
/*------------------------------------------------------------------------------------------------------------------------------
303
Empty control:
304
Gray coded write address pointer is synchronized to read clock domain and compared to Gray coded read address pointer.
305
If they are equal, fifo is empty. Synchronized write pointer is also compared to Gray coded next read address. If these two are
306
equal, fifo is almost empty.
307
--------------------------------------------------------------------------------------------------------------------------------*/
308
wire [(ADDR_LENGTH - 1):0] rclk_sync_wgrey_addr ;
309
reg  [(ADDR_LENGTH - 1):0] rclk_wgrey_addr ;
310 88 mihad
synchronizer_flop #(ADDR_LENGTH, 0) i_synchronizer_reg_wgrey_addr
311 77 mihad
(
312
    .data_in        (wgrey_addr),
313
    .clk_out        (rclock_in),
314
    .sync_data_out  (rclk_sync_wgrey_addr),
315 88 mihad
    .async_reset    (clear)
316 77 mihad
) ;
317
 
318 88 mihad
always@(posedge rclock_in or posedge clear)
319 77 mihad
begin
320 88 mihad
    if (clear)
321
        rclk_wgrey_addr <= #`FF_DELAY 0 ;
322
    else
323
        rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
324 77 mihad
end
325
 
326
assign almost_empty = (rgrey_next == rclk_wgrey_addr) ;
327
assign empty        = (rgrey_addr == rclk_wgrey_addr) ;
328
 
329
endmodule

powered by: WebSVN 2.1.0

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