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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_10/] [rtl/] [verilog/] [pci_pciw_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 "pciw_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
45
//
46
 
47
/* FIFO_CONTROL module provides read/write address and status generation for
48
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
49
`include "pci_constants.v"
50
// synopsys translate_off
51
`include "timescale.v"
52
// synopsys translate_on
53
 
54
module pci_pciw_fifo_control
55
(
56
    rclock_in,
57
    wclock_in,
58
    renable_in,
59
    wenable_in,
60
    reset_in,
61
//    flush_in,         // not used
62
    almost_full_out,
63
    full_out,
64
    almost_empty_out,
65
    empty_out,
66
    waddr_out,
67
    raddr_out,
68
    rallow_out,
69
    wallow_out,
70
    two_left_out
71
);
72
 
73
parameter ADDR_LENGTH = 7 ;
74
 
75
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
76
input  rclock_in, wclock_in;
77
 
78
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
79
//                 write address changes on rising edge of wclock_in when writes are allowed
80
input  renable_in, wenable_in;
81
 
82
// reset input
83
input  reset_in;
84
 
85
// flush input
86
//input flush_in ;      // not used
87
 
88
// almost full and empy status outputs
89
output almost_full_out, almost_empty_out;
90
 
91
// full and empty status outputs
92
output full_out, empty_out;
93
 
94
// read and write addresses outputs
95
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
96
 
97
// read and write allow outputs
98
output rallow_out, wallow_out ;
99
 
100
// two locations left output indicator
101
output two_left_out ;
102
 
103
// read address register
104
reg [(ADDR_LENGTH - 1):0] raddr ;
105
 
106
// write address register
107
reg [(ADDR_LENGTH - 1):0] waddr;
108
assign waddr_out = waddr ;
109
 
110
// grey code registers
111
// grey code pipeline for write address
112
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
113
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
114
 
115
// next write gray address calculation - bitwise xor between address and shifted address
116
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
117
 
118
// grey code pipeline for read address
119
reg [(ADDR_LENGTH - 1):0] rgrey_minus2 ; // two before current
120
reg [(ADDR_LENGTH - 1):0] rgrey_minus1 ; // one before current
121
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
122
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
123
 
124
// next read gray address calculation - bitwise xor between address and shifted address
125
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
126
 
127
// FFs for registered empty and full flags
128
wire empty ;
129
wire full ;
130
 
131
// registered almost_empty and almost_full flags
132
wire almost_empty ;
133
wire almost_full ;
134
 
135
// write allow wire - writes are allowed when fifo is not full
136
wire wallow = wenable_in && !full ;
137
 
138
// write allow output assignment
139
assign wallow_out = wallow ;
140
 
141
// read allow wire
142
wire rallow ;
143
 
144
// full output assignment
145
assign full_out  = full ;
146
 
147
// almost full output assignment
148
assign almost_full_out  = almost_full && !full ;
149
 
150
// clear generation for FFs and registers
151
wire clear = reset_in /*|| flush_in*/ ;     // flush not used for write fifo
152
 
153
assign empty_out = empty ;
154
 
155
//rallow generation
156
assign rallow = renable_in && !empty ; // reads allowed if read enable is high and FIFO is not empty
157
 
158
// rallow output assignment
159
assign rallow_out = rallow ;
160
 
161
// almost empty output assignment
162
assign almost_empty_out = almost_empty && !empty ;
163
 
164
// at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
165
// when FIFO is empty, this register provides actual read address, so first location can be read
166
reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
167
 
168
 
169
// read address mux - when read is performed, next address is driven, so next data is available immediately after read
170
// this is convenient for zero wait stait bursts
171
assign raddr_out = rallow ? raddr_plus_one : raddr ;
172
 
173
always@(posedge rclock_in or posedge clear)
174
begin
175
    if (clear)
176
    begin
177
        // initial values seem a bit odd - they are this way to allow easier grey pipeline implementation and to allow min fifo size of 8
178
        raddr_plus_one <= #`FF_DELAY 5 ;
179
        raddr          <= #`FF_DELAY 4 ;
180
    end
181
    else if (rallow)
182
    begin
183
        raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
184
        raddr          <= #`FF_DELAY raddr_plus_one ;
185
    end
186
end
187
 
188
/*-----------------------------------------------------------------------------------------------
189
Read address control consists of Read address counter and Grey Address pipeline
190
There are 4 Grey addresses:
191
    - rgrey_minus2 is Grey Code of address two before current address
192
    - rgrey_minus1 is Grey Code of address one before current address
193
    - rgrey_addr is Grey Code of current read address
194
    - rgrey_next is Grey Code of next read address
195
--------------------------------------------------------------------------------------------------*/
196
// grey coded address pipeline for status generation in read clock domain
197
always@(posedge rclock_in or posedge clear)
198
begin
199
    if (clear)
200
    begin
201
        rgrey_minus2 <= #`FF_DELAY 0 ;
202
        rgrey_minus1 <= #`FF_DELAY 1 ;
203
        rgrey_addr   <= #`FF_DELAY 3 ;
204
        rgrey_next   <= #`FF_DELAY 2 ;
205
    end
206
    else
207
    if (rallow)
208
    begin
209
        rgrey_minus2 <= #`FF_DELAY rgrey_minus1 ;
210
        rgrey_minus1 <= #`FF_DELAY rgrey_addr ;
211
        rgrey_addr   <= #`FF_DELAY rgrey_next ;
212
        rgrey_next   <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
213
    end
214
end
215
 
216
/*--------------------------------------------------------------------------------------------
217
Write address control consists of write address counter and 2 Grey Code Registers:
218
    - wgrey_addr represents current Grey Coded write address
219
    - wgrey_next represents Grey Coded next write address
220
----------------------------------------------------------------------------------------------*/
221
// grey coded address pipeline for status generation in write clock domain
222
always@(posedge wclock_in or posedge clear)
223
begin
224
    if (clear)
225
    begin
226
        wgrey_addr   <= #`FF_DELAY 3 ;
227
        wgrey_next   <= #`FF_DELAY 2 ;
228
    end
229
    else
230
    if (wallow)
231
    begin
232
        wgrey_addr   <= #`FF_DELAY wgrey_next ;
233
        wgrey_next   <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
234
    end
235
end
236
 
237
// write address counter - nothing special except initial value
238
always@(posedge wclock_in or posedge clear)
239
begin
240
    if (clear)
241
        // initial value 5
242
        waddr <= #`FF_DELAY 4 ;
243
    else
244
    if (wallow)
245
        waddr <= #`FF_DELAY waddr + 1'b1 ;
246
end
247
 
248
/*------------------------------------------------------------------------------------------------------------------------------
249
Full control:
250
Gray coded read address pointer is synchronized to write clock domain and compared to Gray coded next write address.
251
If they are equal, fifo is full.
252
 
253
Almost full control:
254
Gray coded address of read address decremented by two is synchronized to write clock domain and compared to Gray coded write
255
address. If they are equal, fifo is almost full.
256
 
257
Two left control:
258
If Gray coded next write address is equal to Gray coded address of read address decremented by two, the fifo has two free
259
locations left.
260
--------------------------------------------------------------------------------------------------------------------------------*/
261
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_addr ;
262
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_addr ;
263
wire [(ADDR_LENGTH - 1):0] wclk_sync_rgrey_minus2 ;
264
reg  [(ADDR_LENGTH - 1):0] wclk_rgrey_minus2 ;
265
 
266
synchronizer_flop #(2 * ADDR_LENGTH) i_synchronizer_reg_rgrey_addr
267
(
268
    .data_in        ({rgrey_addr, rgrey_minus2}),
269
    .clk_out        (wclock_in),
270
    .sync_data_out  ({wclk_sync_rgrey_addr, wclk_sync_rgrey_minus2}),
271
    .async_reset    (1'b0)
272
) ;
273
 
274
always@(posedge wclock_in)
275
begin
276
    wclk_rgrey_addr   <= #`FF_DELAY wclk_sync_rgrey_addr ;
277
    wclk_rgrey_minus2 <= #`FF_DELAY wclk_sync_rgrey_minus2 ;
278
end
279
 
280
assign full         = (wgrey_next == wclk_rgrey_addr) ;
281
assign almost_full  = (wgrey_addr == wclk_rgrey_minus2) ;
282
assign two_left_out = (wgrey_next == wclk_rgrey_minus2) ;
283
 
284
/*------------------------------------------------------------------------------------------------------------------------------
285
Empty control:
286
Gray coded write address pointer is synchronized to read clock domain and compared to Gray coded read address pointer.
287
If they are equal, fifo is empty.
288
 
289
Almost empty control:
290
Synchronized write pointer is also compared to Gray coded next read address. If these two are
291
equal, fifo is almost empty.
292
--------------------------------------------------------------------------------------------------------------------------------*/
293
wire [(ADDR_LENGTH - 1):0] rclk_sync_wgrey_addr ;
294
reg  [(ADDR_LENGTH - 1):0] rclk_wgrey_addr ;
295
synchronizer_flop #(ADDR_LENGTH) i_synchronizer_reg_wgrey_addr
296
(
297
    .data_in        (wgrey_addr),
298
    .clk_out        (rclock_in),
299
    .sync_data_out  (rclk_sync_wgrey_addr),
300
    .async_reset    (1'b0)
301
) ;
302
 
303
always@(posedge rclock_in)
304
begin
305
    rclk_wgrey_addr <= #`FF_DELAY rclk_sync_wgrey_addr ;
306
end
307
 
308
assign almost_empty = (rgrey_next == rclk_wgrey_addr) ;
309
assign empty        = (rgrey_addr == rclk_wgrey_addr) ;
310
endmodule

powered by: WebSVN 2.1.0

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