vusb_fifo.v
7.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*******************************************************************************
-- File Type: Verilog HDL
-- Tool Version: VHDL2verilog v4.4 Tue Sep 19 10:06:32 EDT 2000 SunOS 5.5.1
-- Input file was: vusb_fifo
-- Date Created: Tue Jul 16 14:00:42 2002
*******************************************************************************/
`timescale 1 ns / 1 ns // timescale for following modules
// ----------------------------------------------------------------------------
// Copyright 2001 VAutomation Inc. Nashua NH USA. All rights reserved.
// This software is provided under license and contains proprietary
// and confidential material which is the property of VAutomation Inc.
// HTTP://www.vautomation.com
// ----------------------------------------------------------------------------
// File Name: $Workfile: vusb_fifo.vhdl$
// Revision: $Revision: 1.1.1.1 $
// Description:
//
// Description:
// This is a FIFO core. The depth of the fifo is passed into this file as
// a generic.
// The constant DEPTH should be set to 2-16 and must be even. DEPTH could be
// more than 16 but you'd be better off using a DPRAM. Currently only a
// depth of 16 has been verified in simulation.
//
// Since it is so small, it is
// built out of clock enabled DFFs. This results in more gates than using
// a Dual Port RAM architecture, but it is much easier to synthesize.
// The FIFO has a latency of DEPTH clocks where DEPTH is the depth of the
// FIFO.
//
// Note that there is a seperate EMPTY and OUT_VALID flags. The FIFO can be
// not EMPTY but OUT_VALID is low indicating that a byte has been loaded into
// the FIFO but it's still rippling down the pipeline.
//
// Taking this fifo and re-naming the port signals to something more
// meaningful. Also removing the out_valid outputs and generating a half
// full flag.
//
// -----------------------------------------------------------------------------
// This product is licensed to:
// John Princen of RouteFree
// for use at site(s):
// broadon
// -----------Revision History--------------------------------------------------
// $Log:
// 7 VUSB 1.6 4/11/02 2:49:15 PM Patrick Koran all
// checked in from pats pc, week of Starteam upgrade 4.6 to 5.1
// 6 VUSB 1.5 2/11/02 3:04:02 PM Tom Frechette Moving
// fifo flush into fifo module.
// 5 VUSB 1.4 8/15/01 2:57:51 PM Tom Frechette Changed
// full flag.
// 4 VUSB 1.3 7/18/01 4:45:01 PM Tom Frechette Changed
// full and empty flags.
// 3 VUSB 1.2 7/18/01 12:00:55 PM Tom Frechette Fixed
// full and empty signals.
// 2 VUSB 1.1 6/27/01 3:12:22 PM Tom Frechette Removed
// generate loop
// 1 VUSB 1.0 6/21/01 9:25:20 AM Tom Frechette
// $
// $NoKeywords$
// -----------------------------------------------------------------------------
// ---------------------------ENTITY ---------------------
module vusb_fifo (clk,
rst,
rst_a,
flush,
wr,
rd,
full,
half_full,
empty,
out_valid,
data_in,
data_out);
parameter DEPTH = 16;
parameter ADDR_SIZE = 3;
input clk; // everything clocks on rising edge
input rst; // reset active high
input rst_a; // reset active high
input flush; // flush fifo pointers
input wr; // write a byte
input rd; // read a byte
output full; // 1=FIFO is full
output half_full; // 1=FIFO is half full
output empty; // 1=FIFO is empty
output out_valid; //
input [7:0] data_in; // data bus in
output [7:0] data_out;
wire full;
wire half_full;
wire empty;
reg out_valid;
wire [7:0] data_out;
parameter THRESHOLD = DEPTH / 2;
reg [7:0] fifo_regs [0:DEPTH - 1];
// address pointers
reg [ADDR_SIZE:0] wr_addr_rg; // write address pointer
reg [ADDR_SIZE:0] rd_addr_rg; // read address pointer
wire [ADDR_SIZE:0] next_wr_addr; // write address increment
wire [ADDR_SIZE:0] next_rd_addr; // read address increment
wire [ADDR_SIZE:0] prev_rd_addr; // Previous address increment
wire [ADDR_SIZE:0] distance; // distance between write & read pointers
wire reached_threshold;
reg fifo_full; // Fifo full signal design
wire full_sig; // Fifo full signal
wire empty_sig; // internal copy of empty output
always @(posedge clk)
begin : regs
if (wr == 1'b 1)
begin
fifo_regs[wr_addr_rg] <= data_in;
end
end
// Data out read mux for simulation, lets read zeros instead of x's when its empty
assign data_out = empty_sig == 1'b 0 ? fifo_regs[rd_addr_rg] :
{8{1'b 0}};
assign next_wr_addr = wr_addr_rg + 1;
assign next_rd_addr = rd_addr_rg + 1;
assign prev_rd_addr = rd_addr_rg - 1;
// FIFO full
assign full = fifo_full | full_sig;
// 1=FIFO is full
assign full_sig = wr_addr_rg == prev_rd_addr & wr == 1'b 1 ? 1'b 1 :
1'b 0;
// Compute FIFO empty detect
assign empty = empty_sig;
assign empty_sig = wr_addr_rg == rd_addr_rg & fifo_full == 1'b 0 ? 1'b 1 :
1'b 0;
// Must compute the distance between the write address pointer
// and the read address pointer. This is used to detect when
// we must then begin refilling the FIFO.
assign distance = wr_addr_rg - rd_addr_rg;
// When ever the distance between the read address pointer and
// write address pointer reaches the THRESHOLD value we must
// stop reading data from the FIFO.
assign half_full = distance >= THRESHOLD ? 1'b 1 :
1'b 0; // When ever the distance between the read address pointer and
// write address pointer reaches the THRESHOLD value we must
// stop reading data from the FIFO.
assign reached_threshold = distance >= THRESHOLD ? 1'b 1 :
1'b 0;
always @(posedge clk or posedge rst_a)
begin : addr_cnt
if (rst_a == 1'b 1)
begin
wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
fifo_full <= 1'b 0;
out_valid <= 1'b 0;
end
else
begin
if (rst == 1'b 1)
begin
wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
fifo_full <= 1'b 0;
out_valid <= 1'b 0;
end
else
begin
if (full_sig == 1'b 1)
begin
fifo_full <= 1'b 1;
end
else if (rd == 1'b 1 | flush == 1'b 1 )
begin
fifo_full <= 1'b 0;
// FIFO output valid control with hysterisis
end
if (reached_threshold == 1'b 1)
begin
out_valid <= 1'b 1;
end
else if (empty_sig == 1'b 1 | flush == 1'b 1 )
begin
out_valid <= 1'b 0;
end
if (flush == 1'b 1)
begin
wr_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
end
else if (wr == 1'b 1 )
begin
wr_addr_rg <= next_wr_addr;
end
else
begin
wr_addr_rg <= wr_addr_rg;
end
if (flush == 1'b 1)
begin
rd_addr_rg <= {(ADDR_SIZE - 0 + 1){1'b 0}};
end
else if (rd == 1'b 1 & empty_sig == 1'b 0 )
begin
rd_addr_rg <= next_rd_addr;
end
else
begin
rd_addr_rg <= rd_addr_rg;
end
end
end
end
// Set the threshold to be 1/2 the depth
endmodule // module vusb_fifo