naajap
Newbie

I'm working on a 4-depth, 8-bit wide FIFO in SystemVerilog. I’ve written both the FIFO module and the testbench, but I’m encountering unexpected behavior in data read operations and flag updates.
Code:
module fifo #(
parameter DEPTH = 4, // Depth of the FIFO
parameter WIDTH = 8 // Width of each entry
)(
input logic clk,
input logic rst,
input logic [WIDTH-1:0] data_in,
input logic wr_en,
input logic rd_en,
output logic [WIDTH-1:0] data_out,
output logic full,
output logic empty
);
logic [WIDTH-1:0] mem [0 : DEPTH-1]; // FIFO memory
logic [1:0] wr_ptr; // Write pointer (2-bit for DEPTH=4)
logic [1:0] rd_ptr; // Read pointer (2-bit for DEPTH=4)
logic [2:0] count; // Counter to track elements (needs 3 bits for DEPTH=4)
always_ff @(posedge clk or posedge rst) begin
if (rst) begin
wr_ptr <= 0;
rd_ptr <= 0;
count <= 0;
full <= 0;
empty <= 1;
end else begin
// Handle simultaneous read and write
if (wr_en && !full && rd_en && !empty) begin
mem[wr_ptr] <= data_in; // Write new data
wr_ptr <= (wr_ptr + 1) % DEPTH;
rd_ptr <= (rd_ptr + 1) % DEPTH; // Read from FIFO
end
// Only write
else if (wr_en && !full) begin
mem[wr_ptr] <= data_in;
wr_ptr <= (wr_ptr + 1) % DEPTH;
count <= count + 1;
end
// Only read
else if (rd_en && !empty) begin
data_out <= mem[rd_ptr];
rd_ptr <= (rd_ptr + 1) % DEPTH;
count <= count - 1;
end
// Correctly update full and empty flags
full <= (count == DEPTH - 1);
empty <= (count == 0);
end
end
endmodule
Code:
module test_fifo;
// Declare signals
logic clk;
logic rst;
logic [7:0] data_in;
logic wr_en;
logic rd_en;
logic [7:0] data_out;
logic full;
logic empty;
// Instantiate FIFO DUT
fifo #(4, 8) dut (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_out(data_out),
.wr_en(wr_en),
.rd_en(rd_en),
.full(full),
.empty(empty)
);
// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Reset generation
initial begin
rst = 1;
#20 rst = 0;
end
// Test sequence
initial begin
// Initialize signals
data_in = 0;
wr_en = 0;
rd_en = 0;
// Wait for reset to complete
@(negedge rst);
// Test 1: Write data to FIFO
$display("Test 1: Writing data to FIFO");
for (int i = 0; i < 4; i++) begin
@(posedge clk);
data_in = i;
wr_en = 1;
rd_en = 0;
$display("Write Data: %h, Full: %b, Empty: %b", data_in, full, empty);
end
@(posedge clk);
wr_en = 0;
// Test 2: Read data from FIFO
$display("Test 2: Reading data from FIFO");
for (int i = 0; i < 4; i++) begin
@(posedge clk);
wr_en = 0;
rd_en = 1;
$display("Read Data: %h, Full: %b, Empty: %b", data_out, full, empty);
end
@(posedge clk);
rd_en = 0;
// Test 3: Simultaneous read and write
$display("Test 3: Simultaneous read and write");
for (int i = 0; i < 4; i++) begin
@(posedge clk);
data_in = i + 4;
wr_en = 1;
rd_en = 1;
$display("Write Data: %h, Read Data: %h, Full: %b, Empty: %b", data_in, data_out, full, empty);
end
@(posedge clk);
wr_en = 0;
rd_en = 0;
// Test 4: Test FIFO full condition
$display("Test 4: Testing FIFO full condition");
for (int i = 0; i < 5; i++) begin
@(posedge clk);
data_in = i + 8;
wr_en = 1;
rd_en = 0;
$display("Write Data: %h, Full: %b, Empty: %b", data_in, full, empty);
end
@(posedge clk);
wr_en = 0;
// Test 5: Test FIFO empty condition
$display("Test 5: Testing FIFO empty condition");
for (int i = 0; i < 5; i++) begin
@(posedge clk);
wr_en = 0;
rd_en = 1;
$display("Read Data: %h, Full: %b, Empty: %b", data_out, full, empty);
end
@(posedge clk);
rd_en = 0;
// End simulation
$display("Simulation completed.");
$finish;
end
endmodule
Test 1: Writing data to FIFO
Write Data: 00, Full: 0, Empty: 1
Write Data: 01, Full: 0, Empty: 1
Write Data: 02, Full: 0, Empty: 0
Write Data: 03, Full: 0, Empty: 0
Test 2: Reading data from FIFO
Read Data: xx, Full: 0, Empty: 0
Read Data: 00, Full: 0, Empty: 0
Read Data: 01, Full: 1, Empty: 0
Read Data: 02, Full: 0, Empty: 0
Test 3: Simultaneous read and write
Write Data: 04, Read Data: 03, Full: 0, Empty: 1
Write Data: 05, Read Data: 03, Full: 0, Empty: 1
Write Data: 06, Read Data: 03, Full: 0, Empty: 0
Write Data: 07, Read Data: 03, Full: 0, Empty: 0
Test 4: Testing FIFO full condition
Write Data: 08, Full: 0, Empty: 0
Write Data: 09, Full: 0, Empty: 0
Write Data: 0a, Full: 1, Empty: 0
Write Data: 0b, Full: 0, Empty: 0
Write Data: 0c, Full: 0, Empty: 0
Test 5: Testing FIFO empty condition
Read Data: 03, Full: 0, Empty: 0
Read Data: 0b, Full: 0, Empty: 0
Read Data: 0c, Full: 0, Empty: 0
Read Data: 08, Full: 0, Empty: 0
Read Data: 09, Full: 1, Empty: 0
Simulation completed.
- In my testbench, the first read operation outputs xx, even though data should have been correctly written into the FIFO.
- When performing simultaneous read and write operations, I observe unexpected outputs in the Read Data
- In Test 4 (FIFO full condition), full is sometimes not asserted when the FIFO is full, and in Test 5, empty remains 0 even when all elements are read.
Request for Help: How can I ensure that the first read correctly outputs the first written value (00 instead of xx)? Why is the read pointer (rd_ptr) seemingly stuck at 03 during simultaneous read/write? How can I ensure full/empty flags update properly, especially during simultaneous operations?
Any insights or suggestions would be greatly appreciated. Thanks in advance!