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