最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

verilog - Issues with FIFO Implementation – Incorrect Data Read & Flag Behavior - Stack Overflow

programmeradmin0浏览0评论

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.

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


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.
  1. In my testbench, the first read operation outputs xx, even though data should have been correctly written into the FIFO.

  2. When performing simultaneous read and write operations, I observe unexpected outputs in the Read Data

  3. 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.

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.

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


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.
  1. In my testbench, the first read operation outputs xx, even though data should have been correctly written into the FIFO.

  2. When performing simultaneous read and write operations, I observe unexpected outputs in the Read Data

  3. 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.

Share Improve this question edited Feb 6 at 12:10 toolic 62.1k19 gold badges79 silver badges127 bronze badges asked Feb 6 at 4:00 apnaapna 112 bronze badges 2
  • You have race conditions in your testbench. Make sure all your simulus is driven by non-blocking assignments. Using the negedge of the clock makes it easer to debug the simulation. – dave_59 Commented Feb 6 at 5:22
  • Thanks for the suggestions. However, after implementing the modifications, I am still encountering issues. The full/empty flags are not always set correctly. During simultaneous read/write operations, the full flag may not be updated properly. The empty flag behaves unpredictably after certain read/write operations. Could you suggest further improvements or identify any other factors that might be causing these inconsistencies? – apna Commented Feb 6 at 8:13
Add a comment  | 

1 Answer 1

Reset to default 0

Any insights or suggestions would be greatly appreciated.

From the comments on the question, it looks like you already fixed the testbench timing problems.

To help with debugging, you should always add the simulation time to the $display statements. For example:

$display($time, " Write Data: %h, Full: %b, Empty: %b", data_in, full, empty);

For designs like this, it is insufficient to debug only using $display statements. You must view simulation waveforms.

You have bugs in the fifo design logic, specifically the flags and the pointers. Essentially, you need to redesign the FIFO.

The % DEPTH code looks suspect; I don't think you need that since the pointers are only 2-bit.

With read and write pointers, I don't think there is any need for a separate counter (count).

I recommend looking at other Verilog FIFO code on the internet. For example: FIFO on the VLSI Verify site.

发布评论

评论列表(0)

  1. 暂无评论