同步FIFO--方法一:以计数原则判断FIFO空满

使用计数器对写入的数据个数进行计数,进而实现FIFO的空满判断。调用一个双端口RAM,以地址的方式对RAM深度进行编码。例如RAM深度为16,则地址为4位。

module sync_fifo_1(clk,rst,w_en,r_en,w_data,r_data,empty,full,Fcounter);

parameter DATA_WIDTH=8;
parameter ADDR_WIDTH=9;

input clk;
input rst;
input w_en;
input r_en;
input [DATA_WIDTH-1:0]w_data;
output [DATA_WIDTH-1:0]r_data;
output empty;
output full;
output [ADDR_WIDTH-1:0]Fcounter;

reg empty;
reg full;
reg [ADDR_WIDTH-1:0]Fcounter;
wire [DATA_WIDTH-1:0]r_data;
reg [ADDR_WIDTH-1:0]w_addr;
reg [ADDR_WIDTH-1:0]r_addr;

wire rd=(r_en && !empty);
wire we=(w_en && !full);

ram_dual u1(
        //Input
        .d(w_data),
        .addr_in(w_addr),
        .rd(rd),
        .clk1(clk),
        .clk2(clk),
        .we(we),
        //output
        .addr_out(r_addr),
        .r_data(r_data));

always @(posedge clk or negedge rst)
    begin
    if(!rst)
        empty<=1'b1;
    else
        empty<=(!w_en && Fcounter[8:1]==8'h0)&&(r_en||Fcounter[0]==0);
    end
always @(posedge clk or negedge rst)
    begin
    if(!rst)
        full<=1'b0;
    else
        full<=(w_en || Fcounter[0]==1'b1)&&(!r_en && Fcounter[8:1]==8'hF);
    end
always @(posedge clk or negedge rst)
    begin
    if(!rst)
        w_addr<=9'b0;
    else if(!full && w_en)
        w_addr<=w_addr+1'b1;
    end
always @(posedge clk or negedge rst)
    begin
    if(!rst)
        r_addr<=9'b0;
    else if(!empty && r_en)
        r_addr<=r_addr+1'b1;
    end
always @(posedge clk or negedge rst)
    begin
    if(!rst)
       Fcounter<=9'b0;
    else if((w_en && !r_en)||(!w_en && r_en))
         begin
             if(w_en)
                 Fcounter<=Fcounter+1'b1;
             else
             Fcounter<=Fcounter-1'b1;
         end
    end
endmodule

module ram_dual(
        //Input
        d,
        addr_in,
        rd,
        clk1,
        clk2,
        we,
        //output
        addr_out,
        r_data);

    input [7:0]d;
    input [8:0]addr_in;
    input rd;
    input clk1;
    input clk2;
    input we;
    input [8:0]addr_out;
    output [7:0]r_data;

    reg [7:0]r_data;
    reg [7:0]mem[511:0];

    always @(posedge clk1)
        begin
        if(we && !rd)
            mem[addr_in]<=d;
        end
    always @(posedge clk2)
            begin
        if(rd && !we)
                r_data<=mem[addr_out];
            end
endmodule

module sync_fifo_1_tb;
reg clk;
reg rst;
reg w_en;
reg r_en;
reg [7:0]w_data;
wire [7:0]r_data;
wire [8:0]Fcounter;
wire full;
wire empty;

sync_fifo_1 u2(clk,rst,w_en,r_en,w_data,r_data,empty,full,Fcounter);
initial
begin
rst=1;
clk=0;
#1 rst=0;
#5 rst=1;
end

initial
begin
w_en=0;
#1 w_en=1;
end

initial
begin
r_en=0;
#650 w_en=0;r_en=1;
end

always #20 clk=~clk;

initial
begin
  $vcdpluson;
end

initial
begin
w_data=8'h0;
#40 w_data=8'h1;
#40 w_data=8'h2;
#40 w_data=8'h3;
#40 w_data=8'h4;
#40 w_data=8'h5;
#40 w_data=8'h6;
#40 w_data=8'h7;
#40 w_data=8'h8;
#40 w_data=8'h9;
#40 w_data=8'ha;
#40 w_data=8'hb;
#40 w_data=8'hc;
#40 w_data=8'hd;
#40 w_data=8'he;
#40 w_data=8'hf;

#700 $finish;
end
endmodule

 

posted @ 2020-07-27 21:05  影-fish  阅读(2356)  评论(0编辑  收藏  举报