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

Subversion Repositories pci

[/] [pci/] [tags/] [rel_3/] [rtl/] [verilog/] [wbr_fifo_control.v] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 mihad
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////  File name "wbr_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 6 mihad
// Revision 1.1.1.1  2001/10/02 15:33:47  mihad
46
// New project directory structure
47 2 mihad
//
48 6 mihad
//
49 2 mihad
 
50
/* FIFO_CONTROL module provides read/write address and status generation for
51
   FIFOs implemented with standard dual port SRAM cells in ASIC or FPGA designs */
52
`include "constants.v"
53 6 mihad
`include "timescale.v"
54 2 mihad
`ifdef FPGA
55
    // fifo design in FPGA will be synchronous
56
    `ifdef SYNCHRONOUS
57
    `else
58
        `define SYNCHRONOUS
59
    `endif
60
`endif
61
 
62
module WBR_FIFO_CONTROL
63
(
64
    rclock_in,
65
    wclock_in,
66
    renable_in,
67
    wenable_in,
68
    reset_in,
69
    flush_in,
70
    empty_out,
71
    waddr_out,
72
    raddr_out,
73
    rallow_out,
74
    wallow_out
75
) ;
76
 
77
parameter ADDR_LENGTH = 7 ;
78
 
79
// independent clock inputs - rclock_in = read clock, wclock_in = write clock
80
input  rclock_in, wclock_in;
81
 
82
// enable inputs - read address changes on rising edge of rclock_in when reads are allowed
83
//                 write address changes on rising edge of wclock_in when writes are allowed
84
input  renable_in, wenable_in;
85
 
86
// reset input
87
input  reset_in;
88
 
89
// flush input
90
input flush_in ;
91
 
92
// empty status output
93
output empty_out;
94
 
95
// read and write addresses outputs
96
output [(ADDR_LENGTH - 1):0] waddr_out, raddr_out;
97
 
98
// read and write allow outputs
99
output rallow_out, wallow_out ;
100
 
101
// read address register
102
reg [(ADDR_LENGTH - 1):0] raddr ;
103
 
104
// write address register
105
reg [(ADDR_LENGTH - 1):0] waddr;
106
assign waddr_out = waddr ;
107
 
108
// grey code registers
109
// grey code pipeline for write address
110
reg [(ADDR_LENGTH - 1):0] wgrey_addr ; // current
111
reg [(ADDR_LENGTH - 1):0] wgrey_next ; // next
112
 
113
// next write gray address calculation - bitwise xor between address and shifted address
114
wire [(ADDR_LENGTH - 2):0] calc_wgrey_next  = waddr[(ADDR_LENGTH - 1):1] ^ waddr[(ADDR_LENGTH - 2):0] ;
115
 
116
// grey code pipeline for read address
117
reg [(ADDR_LENGTH - 1):0] rgrey_addr ; // current
118
reg [(ADDR_LENGTH - 1):0] rgrey_next ; // next
119
 
120
// next read gray address calculation - bitwise xor between address and shifted address
121
wire [(ADDR_LENGTH - 2):0] calc_rgrey_next  = raddr[(ADDR_LENGTH - 1):1] ^ raddr[(ADDR_LENGTH - 2):0] ;
122
 
123
// FF for registered empty flag
124
reg empty ;
125
 
126
// write allow wire
127
wire wallow = wenable_in ;
128
 
129
// write allow output assignment
130
assign wallow_out = wallow ;
131
 
132
// read allow wire
133
wire rallow ;
134
 
135
// clear generation for FFs and registers
136
wire clear = reset_in || flush_in ;
137
 
138
`ifdef SYNCHRONOUS
139
 
140
    reg wclock_nempty_detect ;
141
    always@(posedge reset_in or posedge wclock_in)
142
    begin
143
        if (reset_in)
144
            wclock_nempty_detect <= #`FF_DELAY 1'b0 ;
145
        else
146
            wclock_nempty_detect <= #`FF_DELAY (rgrey_addr != wgrey_addr) ;
147
    end
148
 
149
    // special synchronizing mechanism for different implementations - in synchronous imp., empty is prolonged for 1 clock edge if no write clock comes after initial write
150
    reg stretched_empty ;
151
    always@(posedge rclock_in or posedge clear)
152
    begin
153
        if(clear)
154
            stretched_empty <= #`FF_DELAY 1'b1 ;
155
        else
156
            stretched_empty <= #`FF_DELAY empty && ~wclock_nempty_detect ;
157
    end
158
 
159
    // empty output is actual empty + 1 read clock cycle ( stretched empty )
160
    assign empty_out = empty  || stretched_empty ;
161
 
162
    //rallow generation    
163
    assign rallow = renable_in && ~empty && ~stretched_empty ; // reads allowed if read enable is high and FIFO is not empty
164
 
165
    // rallow output assignment
166
    assign rallow_out = renable_in ;
167
 
168
    // at any clock edge that rallow is high, this register provides next read address, so wait cycles are not necessary
169
    // when FIFO is empty, this register provides actual read address, so first location can be read
170
    reg [(ADDR_LENGTH - 1):0] raddr_plus_one ;
171
 
172
    // address output mux - when FIFO is empty, current actual address is driven out, when it is non - empty next address is driven out
173
    // done for zero wait state burst
174
    assign raddr_out = rallow ? raddr_plus_one : raddr ;
175
 
176
    // enable for this register
177
    wire raddr_plus_one_en = rallow ;
178
    always@(posedge rclock_in or posedge clear)
179
    begin
180
        if (clear)
181
        begin
182
            raddr_plus_one[(ADDR_LENGTH - 1):1] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0}} ;
183
            raddr_plus_one[0] <= #`FF_DELAY 1'b1 ;
184
        end
185
        else if (raddr_plus_one_en)
186
            raddr_plus_one <= #`FF_DELAY raddr_plus_one + 1'b1 ;
187
    end
188
 
189
    // raddr is filled with raddr_plus_one on rising read clock edge when rallow is high
190
    always@(posedge rclock_in or posedge clear)
191
    begin
192
            if (clear)
193
            // initial value is 000......00
194
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
195
            else if (rallow)
196
                raddr <= #`FF_DELAY raddr_plus_one ;
197
    end
198
 
199
`else
200
    // asynchronous RAM storage for FIFOs - somewhat simpler control logic
201
    //rallow generation    
202
    assign rallow = renable_in && ~empty ;
203
 
204
    assign rallow_out = rallow ;
205
 
206
    // read address counter - normal counter, nothing to it
207
    // for asynchronous implementation, there is no need for pointing to next address.
208
    // On clock edge that read is performed, read address will change and on the next clock edge
209
    // asynchronous memory will provide next data
210
    always@(posedge rclock_in or posedge clear)
211
    begin
212
            if (clear)
213
            // initial value is 000......00
214
                    raddr <= #`FF_DELAY { ADDR_LENGTH{1'b0}} ;
215
            else if (rallow)
216
                    raddr <= #`FF_DELAY raddr + 1'b1 ;
217
    end
218
 
219
    assign empty_out = empty ;
220
    assign raddr_out = raddr ;
221
`endif
222
 
223
/*-----------------------------------------------------------------------------------------------
224
Read address control consists of Read address counter and Grey Address pipeline
225
There are 3 Grey addresses:
226
    - rgrey_addr is Grey Code of current read address
227
    - rgrey_next is Grey Code of next read address
228
--------------------------------------------------------------------------------------------------*/
229
 
230
// grey code register for read address - represents current Read Address
231
always@(posedge rclock_in or posedge clear)
232
begin
233
        if (clear)
234
    begin
235
        // initial value is 100.......01
236
                rgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
237
        rgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
238
        rgrey_addr[0] <= #`FF_DELAY 1'b1 ;
239
    end
240
        else
241
                if (rallow)
242
                        rgrey_addr <= #`FF_DELAY rgrey_next ;
243
end
244
 
245
// grey code register for next read address - represents Grey Code of next read address    
246
always@(posedge rclock_in or posedge clear)
247
begin
248
        if (clear)
249
    begin
250
        // initial value is 100......00
251
                rgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
252
        rgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
253
    end
254
        else
255
                if (rallow)
256
            rgrey_next <= #`FF_DELAY {raddr[ADDR_LENGTH - 1], calc_rgrey_next} ;
257
end
258
 
259
/*--------------------------------------------------------------------------------------------
260
Write address control consists of write address counter and two Grey Code Registers:
261
    - wgrey_addr represents current Grey Coded write address
262
    - wgrey_next represents Grey Coded next write address
263
----------------------------------------------------------------------------------------------*/
264
// grey code register for write address
265
always@(posedge wclock_in or posedge clear)
266
begin
267
        if (clear)
268
    begin
269
        // initial value is 100.....001
270
        wgrey_addr[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
271
        wgrey_addr[(ADDR_LENGTH - 2):1] <= #`FF_DELAY { (ADDR_LENGTH - 2){1'b0} } ;
272
        wgrey_addr[0] <= #`FF_DELAY 1'b1 ;
273
    end
274
        else
275
                if (wallow)
276
                        wgrey_addr <= #`FF_DELAY wgrey_next ;
277
end
278
 
279
// grey code register for next write address
280
always@(posedge wclock_in or posedge clear)
281
begin
282
        if (clear)
283
    begin
284
        // initial value is 100......00
285
                wgrey_next[(ADDR_LENGTH - 1)] <= #`FF_DELAY 1'b1 ;
286
        wgrey_next[(ADDR_LENGTH - 2):0] <= #`FF_DELAY { (ADDR_LENGTH - 1){1'b0} } ;
287
    end
288
        else
289
        if (wallow)
290
            wgrey_next <= #`FF_DELAY {waddr[(ADDR_LENGTH - 1)], calc_wgrey_next} ;
291
end
292
 
293
// write address counter - nothing special
294
always@(posedge wclock_in or posedge clear)
295
begin
296
        if (clear)
297
        // initial value 00.........00
298
                waddr <= #`FF_DELAY { (ADDR_LENGTH){1'b0} } ;
299
        else
300
                if (wallow)
301
                        waddr <= #`FF_DELAY waddr + 1'b1 ;
302
end
303
 
304
 
305
/*------------------------------------------------------------------------------------------------------------------------------
306
Registered empty control:
307
registered empty is set on rising edge of rclock_in,
308
when only one location is used and read in/from fifo. It's kept high until something is written to FIFO, which is registered on
309
the next read clock.
310
--------------------------------------------------------------------------------------------------------------------------------*/
311
// combinatorial input for registered emty FlipFlop
312
wire reg_empty = (rallow && (rgrey_next == wgrey_addr)) || (rgrey_addr == wgrey_addr) ;
313
 
314
always@(posedge rclock_in or posedge clear)
315
begin
316
    if (clear)
317
        empty <= #`FF_DELAY 1'b1 ;
318
        else
319
        empty <= #`FF_DELAY reg_empty ;
320
end
321
 
322
endmodule

powered by: WebSVN 2.1.0

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