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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_7/] [rtl/] [verilog/] [pci_pcir_fifo_control.v] - Blame information for rev 154

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

powered by: WebSVN 2.1.0

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