-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsimpleFIFO.v
More file actions
192 lines (166 loc) · 5.54 KB
/
simpleFIFO.v
File metadata and controls
192 lines (166 loc) · 5.54 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
`timescale 1ns/1ps
/*
************************************************************
* Engineer: Brothers, Timothy
* Module: simpleFIFO
* Functionality:
* this is a simple RAM based fifo.
* Version History:
* 0.1 2017.03.03 T. Brothers
File Create
************************************************************
*/
module simpleFIFO (
clk , // Clock input
reset , // Active high reset
data_in , // Data input
rd_en_in , // Read enable
wr_en_in , // Write Enable
data_out , // Data Output
empty_out , // FIFO empty
full_out , // FIFO full
overflow_out // The fifo was written when full
);
//------------------------------------------------
// FIFO constants
//------------------------------------------------
parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 8;
parameter RAM_DEPTH = (1 << ADDR_WIDTH);
//------------------------------------------------
// Port Declarations
//------------------------------------------------
input wire clk;
input wire reset;
input wire rd_en_in;
input wire wr_en_in;
input wire [DATA_WIDTH-1:0] data_in;
output wire full_out;
output wire empty_out;
output wire [DATA_WIDTH-1:0] data_out;
output wire overflow_out;
//------------------------------------------------
// Internal variables
//------------------------------------------------
//the RAM pointer and the counter for the number of samples in the FIFO
reg [ADDR_WIDTH-1:0] wr_pointer = 0;
reg [ADDR_WIDTH-1:0] rd_pointer = 0;
wire [ADDR_WIDTH-1:0] sample_count;
//control signals for moving the pointers
wire inc_rd_sig;
wire inc_wr_sig;
wire clr_rd_sig;
wire clr_wr_sig;
//flags
reg full_reg = 1'b0;
reg full_sig;
reg empty_reg = 1'b1; //the fifo starts out empty
reg empty_sig;
reg overflow_sig;
reg overflow_reg = 1'b0;
// variable to infer the RAM
reg [DATA_WIDTH-1:0] ram [RAM_DEPTH-1:0];
//------------------------------------------------
// Assign the flags
//------------------------------------------------
assign full_out = full_reg;
assign empty_out = empty_reg;
assign overflow_out = overflow_reg;
//------------------------------------------------
// Address Pointers
// There are two counters. One for the read
// and one for the write pointer in the RAM
//------------------------------------------------
always @ (posedge clk or posedge reset)
begin : WRITE_POINTER
if (reset || clr_wr_sig)
wr_pointer <= 0;
else if (inc_wr_sig)
wr_pointer <= wr_pointer + 1;
else
wr_pointer <= wr_pointer;
end
always @ (posedge clk or posedge reset)
begin : READ_POINTER
if (reset || clr_rd_sig)
rd_pointer <= 0;
else if (inc_rd_sig)
rd_pointer <= rd_pointer + 1;
else
rd_pointer <= rd_pointer;
end
//------------------------------------------------
// Combinational Logic
//------------------------------------------------
// Calculate the number of samples in the fifo.
assign sample_count = wr_pointer - rd_pointer;
// Determine the signal for the full register
always @ (*)
begin
//default conditions
overflow_sig = 1'b0;
full_sig = full_reg;
// Write but no read and the fifo is almost full.
if (wr_en_in && !rd_en_in && (sample_count == (RAM_DEPTH-1)))
full_sig = 1'b1; //at the next clock the fifo will be full.
// Write but no read and the fifo is full.
else if (wr_en_in && !rd_en_in && full_reg) begin //the fifo is full and it is doing a write. Overflow!
overflow_sig = 1'b1;
full_sig = 1'b0; //reset the full signal.
end
//it is not writing but it is reading with the fifo full
else if (!wr_en_in && rd_en_in && full_reg)
full_sig = 1'b0; //the fifo will no longer be full.
else begin //default conditions just for fun.
overflow_sig = 1'b0;
full_sig = full_reg;
end
end
// Determine the signal for the empty register
always @ (*)
begin
//default conditions
empty_sig = empty_reg;
// Read but no write and there is data in the fifo.
if (overflow_sig)
empty_sig = 1'b1; //when we overflow we are going to reset the fifo.
else if (rd_en_in && !wr_en_in && (sample_count == 1)) //reading out the last sample of the fifo.
empty_sig = 1'b1; //at the next clock the fifo will be empty.
// Write but no read and the FIFO is empty
else if (wr_en_in && !rd_en_in && empty_reg)
empty_sig = 1'b0; //the fifo will no longer be empty
else //default condition just for fun
empty_sig = empty_reg;
end
// Determine the signal to increment and clear the read and write pointers
assign inc_rd_sig = (rd_en_in && !empty_reg); //there is a read and the fifo is not empty.
assign inc_wr_sig = wr_en_in; //always increment the write whenever there is data on the input line.
assign clr_rd_sig = overflow_sig; //whenever there is an overflow we are going to reset the machine.
assign clr_wr_sig = overflow_sig; //whenever there is an overflow we are going to reset the machine.
//------------------------------------------------
// Register blocks for output flags.
//------------------------------------------------
always @ (posedge clk or posedge reset)
begin
if(reset) begin
full_reg <= 1'b0;
empty_reg <= 1'b1; //when reset it is empty
overflow_reg <= 1'b0;
end
else begin
full_reg <= full_sig;
empty_reg <= empty_sig;
overflow_reg <= overflow_sig;
end
end
//Assign output
assign full_out = full_reg;
assign empty_out = empty_reg;
assign overflow_out = overflow_reg;
//Infer a two port RAM
always @(posedge clk) begin
if (wr_en_in)
ram[wr_pointer] <= data_in;
end
assign data_out = ram[rd_pointer];
endmodule