乒乓FIFO源代码

module gm_fifo_pingpang(
        input  wire       clk         ,
        input  wire       rst_n       ,
        input  wire [7:0] data_in     ,
        input  wire       wr_en       ,
        output reg        fifo1_wr_en ,
        output reg        fifo2_wr_en ,
        output reg        fifo1_rd_en ,
        output reg        fifo2_rd_en ,
        output wire [7:0] data_out       
);


    wire [8:0] fifo_cnt1;
    wire [8:0] fifo_cnt2;

    wire [7:0] data_out1;
    wire [7:0] data_out2;

    parameter idle  = 4'b0000,
              start = 4'b0001,
              ping  = 4'b0010,
              pang  = 4'b0100;

    reg[3:0]state;

always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                state <= idle;
                fifo1_wr_en <= 1'b0;
                fifo2_wr_en <= 1'b0;
            end
        else
            begin
                case(state)
                    idle:begin
                        fifo1_wr_en <= 1'b0;
                        fifo2_wr_en <= 1'b0;
                        fifo1_rd_en <= 1'b0;
                        fifo2_rd_en <= 1'b0;
                        if(wr_en)
                            state <= start;
                        else
                            state <= idle;
                    end

                    start:begin
                        fifo1_wr_en <= 1'b1;
                        fifo2_wr_en <= 1'b0;
                        fifo1_rd_en <= 1'b0;
                        fifo2_rd_en <= 1'b1;
                        if(fifo_cnt1 == 500)
                            state <= ping;
                        else
                            state <= start;
                    end

                    ping:begin
                        fifo1_wr_en <= 1'b0;
                        fifo2_wr_en <= 1'b1;
                        fifo1_rd_en <= 1'b1;
                        fifo2_rd_en <= 1'b0;
                        if(fifo_cnt2 == 500)
                            state <= pang;
                        else
                            state <= ping;
                    end

                    pang:begin
                        fifo1_wr_en <= 1'b1;
                        fifo2_wr_en <= 1'b0;
                        fifo1_rd_en <= 1'b0;
                        fifo2_rd_en <= 1'b1;
                        if(fifo_cnt1 == 500)
                            state <= ping;
                        else
                            state <= pang;
                    end
    
                    default :begin
                        state <= idle;
                        fifo1_wr_en <= 1'b0;
                        fifo2_wr_en <= 1'b0;
                        fifo1_rd_en <= 1'b0;
                        fifo2_rd_en <= 1'b0;
                    end
                endcase
            end
    end

gm_syn_fifo u_fifo1(
            .clk       (clk         ),
            .rst_n     (rst_n       ),
            .wr_en     (fifo1_wr_en ),
            .rd_en     (fifo1_rd_en ),
            .data_in   (data_in     ),
            .data_out  (data_out1   ),
            .fifo_cnt  (fifo_cnt1   )
);

gm_syn_fifo u_fifo2(
            .clk       (clk         ),
            .rst_n     (rst_n       ),
            .wr_en     (fifo2_wr_en ),
            .rd_en     (fifo2_rd_en ),
            .data_in   (data_in     ),
            .data_out  (data_out2   ),
            .fifo_cnt  (fifo_cnt2   )
);

    assign data_out = fifo1_rd_en ? data_out1 : data_out2;

endmodule

module gm_syn_fifo(
        input  wire        clk       ,
        input  wire        rst_n     ,
        input  wire        wr_en     ,
        input  wire        rd_en     ,
        input  wire  [7:0] data_in   ,
        output reg   [7:0] data_out  ,
        output reg   [8:0] fifo_cnt  ,
        output wire        wr_full   ,
        output wire        rd_empty  
);

reg [8:0] rd_ptr     ;
reg [8:0] wr_ptr     ;
reg [7:0] fifo[0:512];

always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            begin
                rd_ptr <= 0;
                wr_ptr <= 0;
            end
        else if(!rd_empty && rd_en)
            begin
                if(rd_ptr == 500)
                    rd_ptr <= 0;
                else
                    rd_ptr <= rd_ptr + 1'b1;
            end
        else if(!wr_full && wr_en)
            begin
                if(wr_ptr == 500)
                    wr_ptr <= 0;
                else
                    wr_ptr <= wr_ptr + 1'b1;
            end
    end
always@(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            fifo_cnt <= 0;
        else if( (!rd_empty && rd_en) && (!wr_full && wr_en) )
            fifo_cnt <= fifo_cnt;
        else if(!rd_empty && rd_en)
            fifo_cnt <= fifo_cnt - 1'b1;
        else if(!wr_full && wr_en)
            fifo_cnt <= fifo_cnt + 1'b1;
        else 
            fifo_cnt <= fifo_cnt;
    end

always@(posedge clk or negedge rst_n)   
    begin
        if(!rst_n)
            data_out <= 0;
        else if(!rd_empty && rd_en)
            data_out <= fifo[rd_ptr];
        else if(!wr_full && wr_en)
            fifo[wr_ptr] <= data_in;
    end

assign wr_full =  (fifo_cnt == 500) ? 1'b1 : 1'b0;
assign rd_empty = (fifo_cnt == 0  ) ? 1'b1 : 1'b0;

endmodule
`timescale 1ns/1ns
module tb();

reg          clk        ;
reg          rst_n      ;
reg  [7:0]   data_in    ;
reg          wr_en      ;
wire         fifo1_wr_en;
wire         fifo2_wr_en;
wire         fifo1_rd_en;
wire         fifo2_rd_en;
wire [7:0]   data_out   ;



gm_fifo_pingpang u_pingpang(
        .clk         (clk        ),
        .rst_n       (rst_n      ),
        .data_in     (data_in    ),
        .wr_en       (wr_en      ),
        .fifo1_wr_en (fifo1_wr_en),
        .fifo2_wr_en (fifo2_wr_en),
        .fifo1_rd_en (fifo1_rd_en),
        .fifo2_rd_en (fifo2_rd_en),
        .data_out    (data_out   )   
);

always #10 clk = ~clk;
always #12 data_in = data_in + 1'b1;

initial begin
        clk     <= 1'b1;
        rst_n   <= 1'b0;
        data_in <= 8'd0;

    #50 rst_n   <= 1'b1;
        wr_en   <= 1'b1;

    #5000
        $stop;
end

endmodule

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值