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 77

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

powered by: WebSVN 2.1.0

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