FPGA乒乓操作Verilog程序

module ping_pong_buffer(
    input clk,
    input rst_n,
    
    //external write interface
    input[7:0] i_data,
    input i_data_valid,
    
    //ping ram buffer interface
    output ping_ram_buffer_wclk,
    output ping_ram_buffer_wea,
    output[9:0] ping_ram_buffer_w_addr,
    output[7:0] ping_ram_buffer_w_data,
    output ping_ram_buffer_rclk,
    output[8:0] ping_ram_buffer_r_addr,
    input[15:0] ping_ram_buffer_r_data,
    
    //pong ram buffer interface
    output pong_ram_buffer_wclk,
    output pong_ram_buffer_wea,
    output[9:0] pong_ram_buffer_w_addr,
    output[7:0] pong_ram_buffer_w_data,
    output pong_ram_buffer_rclk,
    output[8:0] pong_ram_buffer_r_addr,
    input[15:0] pong_ram_buffer_r_data,
    
    //internal read interface
    input    r_clk,
    output    o_data_valid,//256x16
    output[15:0]    o_data
);
 
    reg i_data_valid_delay_1,i_data_valid_delay_2;
    reg wr_buffer_sel;
    reg ping_buffer_wea,pong_buffer_wea;
    reg[9:0] ping_buffer_wr_addr,pong_buffer_wr_addr;    
    reg wr_finish;
    
    
    reg wr_finish_sync1,wr_finish_sync2,wr_finish_sync3;
    reg[8:0] buffer_rd_addr;
    reg buffer_rd_ena,buffer_rd_ena_delay;
    reg buffer_rd_sel;
    
    
    //-------------------------------write operation--------------------------------//
    always@(posedge clk)begin
        if(rst_n == 1'b0)begin
            i_data_valid_delay_1 <= 1'b0;
            i_data_valid_delay_2 <= 1'b0;
        end    
        else begin
            i_data_valid_delay_1 <= i_data_valid;
            i_data_valid_delay_2 <= i_data_valid_delay_1;
        end
    end
 
    always@(posedge clk)begin
        if(rst_n == 1'b0)
            wr_buffer_sel <= 1'b0;
        else if(i_data_valid == 1'b0 && i_data_valid_delay_1 == 1'b1)
            wr_buffer_sel <= ~wr_buffer_sel;
    end
    
    always@* begin
        ping_buffer_wea <= ~wr_buffer_sel & i_data_valid;
        pong_buffer_wea <= wr_buffer_sel & i_data_valid;
    end
    
    assign ping_ram_buffer_wea = ping_buffer_wea;
    assign pong_ram_buffer_wea = pong_buffer_wea;
    assign ping_ram_buffer_wclk = clk;
    assign pong_ram_buffer_wclk = clk;
    assign ping_ram_buffer_w_data = i_data;
    assign pong_ram_buffer_w_data = i_data;
    
    always@(posedge clk)begin
        if(rst_n == 1'b0)
            ping_buffer_wr_addr <= 10'b0;
        else if(ping_buffer_wea == 1'b1)
            ping_buffer_wr_addr <= ping_buffer_wr_addr+1;
        else
            ping_buffer_wr_addr <= 10'b0;
    end
    
    always@(posedge clk)begin
        if(rst_n == 1'b0)
            pong_buffer_wr_addr <= 10'b0;
        else if(pong_buffer_wea == 1'b1)
            pong_buffer_wr_addr <= pong_buffer_wr_addr+1;
        else
            pong_buffer_wr_addr <= 10'b0;
    end
    
    assign ping_ram_buffer_w_addr = ping_buffer_wr_addr;
    assign pong_ram_buffer_w_addr = pong_buffer_wr_addr;
    
    always@(posedge clk)begin
        if(rst_n == 1'b0)
            wr_finish <= 1'b0;
        else if(i_data_valid == 1'b0 && i_data_valid_delay_2 == 1'b1)
            wr_finish <= 1'b1;
        else
            wr_finish <= 1'b0;
    end
    
    //-----------------------------read operation--------------------------------//
    assign ping_ram_buffer_rclk = r_clk;
    assign pong_ram_buffer_rclk = r_clk;
    
    always@(r_clk)begin
        if(rst_n == 1'b0)begin
            wr_finish_sync1 <= 1'b0;
            wr_finish_sync2 <= 1'b0;
            wr_finish_sync3 <= 1'b0;
        end
        else begin
            wr_finish_sync1 <= wr_finish;
            wr_finish_sync2 <= wr_finish_sync1;
            wr_finish_sync3 <= wr_finish_sync2;
        end
    end
    
    always@(r_clk)begin
        if(rst_n == 1'b0)
            buffer_rd_ena <= 1'b0;
        else if(wr_finish_sync2 == 1 && wr_finish_sync3 == 0)
            buffer_rd_ena <= 1'b1;
        else if(buffer_rd_addr == 9'd511)
            buffer_rd_ena <= 1'b0;
    end
    
    always@(r_clk)begin
        if(rst_n == 1'b0)
            buffer_rd_ena_delay <= 1'b0;
        else
            buffer_rd_ena_delay <= buffer_rd_ena;
    end
    
    always@(r_clk)begin
        if(rst_n == 1'b0)
            buffer_rd_addr <= 9'b0;
        else if(buffer_rd_ena)
            buffer_rd_addr <= buffer_rd_addr + 1;
        else
            buffer_rd_addr <= 9'b0;
    end
    
    always@(r_clk)begin
        if(rst_n == 1'b0)
            buffer_rd_sel <= 1'b0;
        else if(buffer_rd_ena == 1'b0 && buffer_rd_ena_delay == 1'b1)
            buffer_rd_sel <= ~buffer_rd_sel;
    end
    
    assign ping_ram_buffer_r_addr = (buffer_rd_sel == 1'b0)?buffer_rd_addr:9'b0;
    assign pong_ram_buffer_r_addr = (buffer_rd_sel == 1'b1)?buffer_rd_addr:9'b0;
    
    assign o_data = (buffer_rd_sel == 1'b0)?ping_ram_buffer_r_data:pong_ram_buffer_r_data;
    assign o_data_valid = buffer_rd_ena_delay;
    
endmodule

testbench的编写:

`timescale 1ns/1ns
`define clock_period 10
 
module tb_ping_pong_buffer;
    
    reg clk;
    reg rst_n;
    
    wire wclk,rclk;
    wire ping_ram_buffer_wea,pong_ram_buffer_wea;
    wire[9:0] ping_ram_buffer_w_addr,pong_ram_buffer_w_addr;
    wire[7:0] ping_ram_buffer_w_data,pong_ram_buffer_w_data;
    wire[8:0] ping_ram_buffer_r_addr,pong_ram_buffer_r_addr;
    wire [15:0] ping_ram_buffer_r_data,pong_ram_buffer_r_data;
    
    reg i_data_valid;
    reg [7:0] i_data;
    wire o_data_valid;
    wire[7:0] o_data;
    integer i;
    
    
    ping_pong_buffer inst1(
        .clk(clk),
        .rst_n(rst_n),
        
        //external write interface
        .i_data(i_data),
        .i_data_valid(i_data_valid),
        
        //ping ram buffer interface
        .ping_ram_buffer_wclk(wclk),
        .ping_ram_buffer_wea(ping_ram_buffer_wea),
        .ping_ram_buffer_w_addr(ping_ram_buffer_w_addr),
        .ping_ram_buffer_w_data(ping_ram_buffer_w_data),
        .ping_ram_buffer_rclk(rclk),
        .ping_ram_buffer_r_addr(ping_ram_buffer_r_addr),
        .ping_ram_buffer_r_data(ping_ram_buffer_r_data),
        
        //pong ram buffer interface
        .pong_ram_buffer_wclk(wclk),
        .pong_ram_buffer_wea(pong_ram_buffer_wea),
        .pong_ram_buffer_w_addr(pong_ram_buffer_w_addr),
        .pong_ram_buffer_w_data(pong_ram_buffer_w_data),
        .pong_ram_buffer_rclk(rclk),
        .pong_ram_buffer_r_addr(pong_ram_buffer_r_addr),
        .pong_ram_buffer_r_data(pong_ram_buffer_r_data),
        
        //internal read interface
        .r_clk(clk),
        .o_data_valid(o_data_valid),//256x16
        .o_data(o_data)
    );
    
    initial clk = 1;
    always #(`clock_period/2) clk = ~clk;
    
    initial begin
        rst_n = 1'b0;
        #(`clock_period*100+1);
        rst_n = 1'b1;
        i_data_valid = 1'b0;
        i_data = 8'b0;
        #(`clock_period*20);
        
        for (i=0;i<=1023;i=i+1)begin
            i_data_valid = 1;
            i_data = i;
            #`clock_period;
        end
        i_data_valid = 1'b0;
        
        #(`clock_period*20);
        for (i=0;i<=1023;i=i+1)begin
            i_data_valid = 1;
            i_data = i;
            #`clock_period;
        end
        i_data_valid = 1'b0;
        
        #(`clock_period*600);
        
        $stop;
    end
 
endmodule

猜你喜欢

转载自blog.csdn.net/wordwarwordwar/article/details/82828713