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

Subversion Repositories pci

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

powered by: WebSVN 2.1.0

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