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 88

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

powered by: WebSVN 2.1.0

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