Skip to content

Commit f05ba14

Browse files
committed
Start to correct FIFO behavior
1 parent 3c1c804 commit f05ba14

File tree

2 files changed

+87
-51
lines changed

2 files changed

+87
-51
lines changed

sim/test/async_fifo_unit_test.sv

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
`timescale 1 ns / 1 ps
21
`include "svut_h.sv"
32
`include "../../src/vlog/async_fifo.v"
3+
`timescale 1 ns / 1 ps
44

55
module async_fifo_unit_test;
66

@@ -10,45 +10,53 @@ module async_fifo_unit_test;
1010
parameter POINTER = 4;
1111

1212
reg wr_clk;
13-
reg awresetn;
14-
reg wren;
15-
reg [WIDTH-1:0] data_in;
13+
reg wr_arstn;
14+
reg wr_en;
15+
reg [WIDTH-1:0] wr_data;
1616
wire wr_full;
1717
reg rd_clk;
18-
reg arresetn;
19-
reg rden;
20-
wire [WIDTH-1:0] data_out;
18+
reg rd_arstn;
19+
reg rd_en;
20+
wire [WIDTH-1:0] rd_data;
2121
wire rd_empty;
2222

2323
async_fifo
2424
#(
25-
,
26-
POINTER
25+
.WIDTH (WIDTH),
26+
.POINTER (POINTER)
2727
)
2828
dut
2929
(
3030
wr_clk,
31-
awresetn,
32-
wren,
33-
data_in,
31+
wr_arstn,
32+
wr_en,
33+
wr_data,
3434
wr_full,
3535
rd_clk,
36-
arresetn,
37-
rden,
38-
data_out,
36+
rd_arstn,
37+
rd_en,
38+
rd_data,
3939
rd_empty
4040
);
4141

4242
// An example to create a clock
43-
// initial aclk = 0;
44-
// always #2 aclk <= ~aclk;
43+
initial wr_clk = 0;
44+
initial rd_clk = 0;
45+
always #2 wr_clk = ~wr_clk;
46+
always #2 rd_clk = ~rd_clk;
4547

4648
// An example to dump data for visualization
47-
// initial $dumpvars(0,async_fifo_unit_test);
49+
initial $dumpvars(0,async_fifo_unit_test);
4850

4951
task setup();
5052
begin
51-
// setup() runs when a test begins
53+
wr_arstn = 1;
54+
rd_arstn = 1;
55+
init_write();
56+
init_read();
57+
#50;
58+
wr_arstn = 1;
59+
rd_arstn = 1;
5260
end
5361
endtask
5462

@@ -58,10 +66,26 @@ module async_fifo_unit_test;
5866
end
5967
endtask
6068

69+
task init_write();
70+
begin
71+
wr_arstn = 0;
72+
wr_en = 1'b0;
73+
wr_data = 0;
74+
end
75+
endtask
76+
77+
task init_read();
78+
begin
79+
rd_arstn = 0;
80+
rd_en = 1'b0;
81+
end
82+
endtask
83+
6184
`UNIT_TESTS
6285

63-
`UNIT_TEST(TESTNAME)
64-
// Describe here your testcase
86+
`UNIT_TEST(INIT_FIFO)
87+
wait (wr_full == 1'b0);
88+
wait (rd_empty == 1'b0);
6589
`UNIT_TEST_END
6690

6791
`UNIT_TESTS_END

src/vlog/async_fifo.v

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,52 @@ module async_fifo
2525
)(
2626
// Write side of the FIFO
2727
input wire wr_clk,
28-
input wire awresetn,
29-
input wire wren,
30-
input wire [WIDTH-1:0] data_in,
28+
input wire wr_arstn,
29+
input wire wr_en,
30+
input wire [WIDTH-1:0] wr_data,
3131
output wire wr_full,
3232
// Read side of the FIFO
3333
input wire rd_clk,
34-
input wire arresetn,
35-
input wire rden,
36-
output wire [WIDTH-1:0] data_out,
34+
input wire rd_arstn,
35+
input wire rd_en,
36+
output wire [WIDTH-1:0] rd_data,
3737
output wire rd_empty
3838
);
3939

4040
localparam DEPTH = 1 << POINTER;
4141

42-
reg [POINTER-1 : 0] rd_pointer, rd_sync_1, rd_sync_2;
43-
reg [POINTER-1 : 0] wr_pointer, wr_sync_1, wr_sync_2;
44-
wire [POINTER-1 : 0] rd_pointer_g;
45-
wire [POINTER-1 : 0] wr_pointer_g;
42+
// Read pointer managed by rd_clk
43+
reg [POINTER:0] rd_pointer;
44+
// Write pointer managed by wr_clk
45+
reg [POINTER:0] wr_pointer;
4646

47-
reg [WIDTH-1 : 0] mem [DEPTH-1 : 0];
47+
// Pointers used to pass between the domains
48+
reg [POINTER:0] rd_sync_1;
49+
reg [POINTER:0] wr_sync_1;
50+
reg [POINTER:0] rd_sync_2;
51+
reg [POINTER:0] wr_sync_2;
52+
wire [POINTER:0] rd_pointer_g;
53+
wire [POINTER:0] wr_pointer_g;
4854

49-
wire [POINTER-1 : 0] rd_pointer_sync;
50-
wire [POINTER-1 : 0] wr_pointer_sync;
55+
// Pointers used across the domains:
56+
57+
// Used in write domain
58+
wire [POINTER:0] rd_pointer_sync;
59+
// Used in read domain
60+
wire [POINTER:0] wr_pointer_sync;
61+
62+
// The memory block RAM used to store and
63+
// pass the information
64+
reg [WIDTH-1:0] mem [DEPTH-1 : 0];
5165

5266
// Write logic management
53-
always @(posedge wr_clk or posedge awresetn) begin
54-
if (awresetn == 1'b0) begin
67+
always @(posedge wr_clk or negedge wr_arstn) begin
68+
if (wr_arstn == 1'b0) begin
5569
wr_pointer <= 0;
5670
end
57-
else if (wr_full == 1'b0 && wren == 1'b1) begin
71+
else if (wr_full == 1'b0 && wr_en == 1'b1) begin
5872
wr_pointer <= wr_pointer + 1;
59-
mem[wr_pointer[POINTER-1 : 0]] <= data_in;
73+
mem[wr_pointer[POINTER-1 : 0]] <= wr_data;
6074
end
6175
end
6276

@@ -67,16 +81,16 @@ module async_fifo
6781
end
6882

6983
// Read logic management
70-
always @(posedge rd_clk or posedge arresetn) begin
71-
if (arresetn == 1'b0) begin
84+
always @(posedge rd_clk or negedge rd_arstn) begin
85+
if (rd_arstn == 1'b0) begin
7286
rd_pointer <= 0;
7387
end
74-
else if (rd_empty == 1'b0 && rden == 1'b1) begin
88+
else if (rd_empty == 1'b0 && rd_en == 1'b1) begin
7589
rd_pointer <= rd_pointer + 1;
7690
end
7791
end
7892

79-
assign data_out = mem[rd_pointer[POINTER-1 : 0]];
93+
assign rd_data = mem[rd_pointer[POINTER-1 : 0]];
8094

8195
// Write pointer synchronization with read clock
8296
always @(posedge rd_clk) begin
@@ -85,13 +99,13 @@ module async_fifo
8599
end
86100

87101
// Binary pointer comparaison
88-
assign wr_full = ((wr_pointer[POINTER-1 : 0] == rd_pointer_sync[POINTER-1 : 0]) &&
89-
(wr_pointer[POINTER] != rd_pointer_sync[POINTER] ));
102+
//assign wr_full = ((wr_pointer[POINTER-1 : 0] == rd_pointer_sync[POINTER-1 : 0]) &&
103+
// (wr_pointer[POINTER] != rd_pointer_sync[POINTER] )) ? 1'b1 : 1'b0;
90104

91105
// Gray counter comparaison
92-
//assign wr_full = ((wr_pointer[POINTER-2 : 0] == rd_pointer_sync[POINTER-2 : 0]) &&
93-
// (wr_pointer[POINTER-1] != rd_pointer_sync[POINTER-1]) &&
94-
// (wr_pointer[POINTER] != rd_pointer_sync[POINTER]));
106+
assign wr_full = ((wr_pointer[POINTER-2 : 0] == rd_pointer_sync[POINTER-2 : 0]) &&
107+
(wr_pointer[POINTER-1] != rd_pointer_sync[POINTER-1]) &&
108+
(wr_pointer[POINTER] != rd_pointer_sync[POINTER])) ? 1'b1 : 1'b0;
95109

96110
// The FIFO is considered as empty when pointer match the same address
97111
// No more data remains to read
@@ -106,11 +120,9 @@ module async_fifo
106120

107121
// Convert back to binary after the synchronization from
108122
// the source domain
109-
assign wr_pointer_sync = wr_sync_2 ^ (wr_sync_2 >> 1) ^
110-
(wr_sync_2 >> 2) ^ (wr_sync_2 >> 3);
123+
assign wr_pointer_sync = wr_sync_2 ^ (wr_sync_2 >> 1) ^ (wr_sync_2 >> 2) ^ (wr_sync_2 >> 3);
111124

112-
assign rd_pointer_sync = rd_sync_2 ^ (rd_sync_2 >> 1) ^
113-
(rd_sync_2 >> 2) ^ (rd_sync_2 >> 3);
125+
assign rd_pointer_sync = rd_sync_2 ^ (rd_sync_2 >> 1) ^ (rd_sync_2 >> 2) ^ (rd_sync_2 >> 3);
114126

115127
endmodule
116128

0 commit comments

Comments
 (0)