FIFO:输出在发送下一个字节之前处于亚稳定状态

FIFO: Output is at meta-stable state before sending next byte

Objective: 使用并行输入 -> 串行输出实现 15 字节 FIFO。

预期结果:

FIFO 模块:

//`timescale 1 ns / 100 ps
module fifo(rd_clk, data_out, data_in, rst, data_available);
    // input & output ports
    output data_out; // 1b serial out
    input [7:0] data_in; // 8b parallel in
    input rd_clk;
    input rst;
    input data_available;

    // registers
    reg [3:0] cs, rp, wp; // 4b(max=15)
    reg data_out;

    // internal only
    reg data_out_ready;
    reg [7:0] data_ram[0:14]; // Buffer 15 x 8bit

    // common reset
    always @(posedge rd_clk or posedge rst)
    begin:Reset
        if(rst) begin
            wp <= 4'b0;
            rp <= 4'b0;
            cs <= 4'b0;
            data_out <= 1'b0;
            data_out_ready <= 1'b0;
        end
    end


    always @(posedge data_available)
    begin:Writing

        if(!eql_addr) begin
            data_ram[wp] = data_in;
            #1 wp <= wp + 4'b0001;

            if(wp == 14) begin
                #1 data_out_ready <= 1'b1;
                #1 wp <= 4'b0;
            end
        end

    end

    always @(posedge rd_clk)
    begin:Reading

        if(data_out_ready)
        begin
            data_out = data_ram[cs][rp];
            rp <= rp + 4'b0001;

            if(rp == 4'b1000) begin
                cs <= cs + 4'b0001;
                rp <= 4'b0;
            end

            if(cs == 15) begin
                cs <= 4'b0;
                data_out_ready <= 1'b0;
            end
        end
        else
            data_out <= 0;

    end

    assign eql_addr = (cs == wp) && data_out_ready;

endmodule

以下是我的测试平台模块

// `timescale 1 ns / 1 ps
module fifo_tb;

    reg rst, clk, wr_en;
    wire data_out;
    reg [7:0] data_in;

    // waveform dump for gtkwave
    initial
        begin
            $dumpfile("fifo.vcd");
        $dumpvars(0,fifo_tb);
    end

    fifo f1 (clk, data_out, data_in, rst, wr_en);

    initial
        begin
        wr_en <= 0;
        rst <= 1;
        clk <= 0;
        data_in <= 8'b0;
    end

    always #100 clk =~ clk; // flip clock every 100time-units

    initial
        begin
        #100 rst = 1'b1;
        #100 rst = 1'b0;
        #100 data_in = 8'b01010110;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b11001101;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b11011100;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00110011;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00111100;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b11001100;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00111100;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b10110011;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b11111111;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00001111;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00111010;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b01100110;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b00110000;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b01100010;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #100 data_in = 8'b11000001;
        #10 wr_en = 1'b0;
        #10 wr_en = 1'b1;
        #50000 ; // wait
        $finish;
    end

endmodule

这是波形研究:

问题:

我试图弄清楚为什么在每个字节(在 data_out 处)之后都会引入这种亚稳态,我还注意到 data_out 很好但是被移动了 1 位,即第 0 个位置 (rp = 0) 的位在读取时显示在第 1 个位置 (rp = 1)。

谢谢。

rp 递增到 8,因为读取 data_ram[n][8] 的数组元素(最多 7)正在生成 x。这也可能是位被移动的原因。 也可以更新 cs 比较以生成所有 15 个字节。

两个变化 - begin:Reading

        if(rp == 4'b0111) begin

        if(cs == 14 && rp == 4'b0111) begin

您可能不想在代码中使用#delay。 写接口是异步接口吗?