-
Notifications
You must be signed in to change notification settings - Fork 1
/
fifo_tb.v
209 lines (174 loc) · 4.02 KB
/
fifo_tb.v
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
`define width 8
`define depth 8
module fifo_tb();
reg clk,rst,wr_en,rd_en;
reg [`width-1:0] wr_data;
wire [`width-1:0] rd_data;
wire full,empty,almost_full,almost_empty,half;
fifo dut(clk,rst,wr_en,rd_en,wr_data,rd_data,full,empty,almost_full,almost_empty,half);
//////////// reference model ////////
reg [`width-1:0] ram [0:`depth-1];
reg exp_full,exp_empty,exp_half,exp_al_half,exp_al_full,exp_al_empty;
reg [`width-1:0] exp_rd_data;
reg [3:0] r_pt=0;
reg [3:0] w_pt=0;
integer j;
//////////// initialise counter for self check ////
integer data_out_count=0;
integer empty_count=1;
integer full_count=1;
integer almost_full_count=1;
integer almost_empty_count=1;
integer half_count=1;
integer count=1;
/////////// reset task //////////////
task reset();
begin
@(negedge clk);
rst=1'b1;
@(negedge clk);
rst=1'b0;
end
endtask
//////////// write task //////////////
task write(input [`width-1:0] data);
begin
@(negedge clk)
wr_en=1'b1;
wr_data=data;
end
endtask
//////////// read task /////////
task read();
begin
@(negedge clk)
rd_en=1'b1;
end
endtask
//////////// reset check ///////
task reset_check();
begin : rst_chk
reg [7:0] exp_rd_data;
write({$random});
reset();
exp_rd_data<=0;
@(negedge clk)
if(rd_data== exp_rd_data)
$display("Reset check passed");
else
$display("Reset check failed");
end
endtask
///////////////////// refernce model logic //////////
initial
begin
forever@(posedge clk)
begin
if(rst)
begin
exp_rd_data<=0;
r_pt<=0;
w_pt<=0;
for (j=0;j<`width;j=j+1)
begin
ram[j]<=0;
end
end
else
begin
if(wr_en && !exp_full)
begin
ram[w_pt[2:0]]<=wr_data;
w_pt<=w_pt+1;
end
if(rd_en && !exp_empty)
begin
exp_rd_data<=ram[r_pt[2:0]];
ram[r_pt]<='bz;
r_pt<=r_pt+1;
end
end
end
end
always@(posedge clk)
begin
fork
begin
if (rd_data!==0 && rd_data!==8'dx)
begin
if(exp_rd_data==rd_data)
//data_out_count<=data_out_count+1; // expected data out value
$display("DATA OUT is good");
else
$display("DATA OUT IS FAULTY");
end
//$display("DATA OUT count=%d time=%t",data_out_count,$time);
end
//$display("DATA OUT CORRECT COUNT=%d",data_out_count);
begin
if(exp_empty===empty)
//empty_count<=empty_count+1; // expected empty flag
$display("EMPTY is good");
else
$display("EMPTY FAILED");
end
begin
if(exp_full===full)
//full_count<=full_count+1; // expected full flag
$display("Full is good");
else
$display("FULL FAILED");
end
begin
if(exp_al_full===almost_full)
//almost_full_count<=almost_full_count+1; // expected almost full flag
$display("ALMOST FULL is good");
else
$display("ALMOST FULL FAILED");
end
begin
if(exp_al_empty===almost_empty)
//almost_empty_count<=almost_empty_count+1; // expected almost empty flag
$display("ALMOST EMPTY is good");
else
$display("ALMOST EMPTY FAILED");
end
begin
if(exp_half===half)
//half_count<=half_count+1; // expected half flag
$display("HALF is good");
else
$display("HALF FAILED");
end
join
end
//////////////////////////// flag logic /////////////
always@(posedge clk)
begin
assign exp_full=(w_pt-r_pt==`width )?1:0;
assign exp_empty=(w_pt==r_pt)?1:0;
assign exp_al_full=(w_pt-r_pt>=`depth-`gap && !full)?1:0;
assign exp_al_empty=(w_pt-r_pt<=`gap && !empty)?1:0;
assign exp_half=(w_pt-r_pt==`depth/2)?1:0;
end
/////////// clock /////////////////
initial begin
clk=1'b1;
forever #5 clk=~clk;
end
///////////// stimulus ////////////
initial begin
reset();
repeat(8)
write({$random});
repeat(8)
read();
reset();
fork
begin repeat(4) write({$random}); end
begin repeat(4) read(); end
join
reset_check();
@(negedge clk) $finish;
end
endmodule