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

Subversion Repositories pci

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

powered by: WebSVN 2.1.0

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