1.乒乓操作原理
乒乓操作是一个主要用于数据流控制的处理技巧,典型的乒乓操作如图所示:
外部输入数据流通过“输入数据选择控制”模块送入两个数据缓冲区中,数据缓冲模块可以为任何存储模块,比较常用的存储单元为双口RAM(Dual RAM),SRAM,SDRAM,FIFO等。
在第1个缓冲周期,将输入的数据流缓存到“数据缓冲1”模块,在第2个缓冲周期,“输入数据选择控制”模块将输入的数据流缓存到“数据缓冲2”模块的同时,“输出数据选择控制”模块将“数据缓冲1”模块第一个周期缓存的数据流送到“后续处理”,模块进行后续的数据处理,在第三个缓冲周期,在“输入数据选择控制”模块的再次切换后,输入的数据流缓存到“数据缓冲1”模块,与此同时,“输出数据选择控制”模块也做出切换,将“数据缓冲2”模块缓存的第二个周期的数据送到“后续处理模块”,如此循环。
正是利用了乒乓操作完成数据的无缝缓冲与处理,乒乓操作可以通过“输入数据选择控制”和“输出数据选择控制”按节拍,相互配合地进行来回切换,将经过缓冲的数据流没有停顿的送到“后续处理模块”。
2.乒乓操作源代码
module pingpong_operation(
input clk,
input rst,
input [7:0] data_in,
output reg [7:0] data_out
);
reg [7:0] buffer_1;//缓存1
reg [7:0] buffer_2;//缓存2
reg wr_flag;//写标志,wr_flag=0,buffer_2写;wr_flag=1,buffer_1写
reg rd_flag;//读标志,rd_flag=0,buffer_1读;rd_flag=1,buffer_2读
reg state;// 状态机,1:写1读2, 0:写2读1,状态转移和输出分开编码
//状态转移
always@(posedge clk or negedge rst)
begin
if (!rst)
state<=0;
else
state<=~state;
end
//状态输出
always@(state)
begin
case(state)
0:
begin
wr_flag<=0;
rd_flag<=0;
end
1:
begin
wr_flag<=1;
rd_flag<=1;
end
default:
begin
wr_flag<=0;
rd_flag<=0;
end
endcase
end
//写缓存buffer数据
always@(posedge clk or negedge rst)
begin
if(!rst)
begin
buffer_1<=8'b0;
buffer_2<=8'b0;
end
else
begin
case(wr_flag)
0: buffer_2<=data_in;//wr_flag = 0,写buffer2
1: buffer_1<=data_in;//wr_flag = 1,写buffer_1
default:
begin
buffer_1<=0;
buffer_2<=0;
end
endcase
end
end
//读缓存buffer数据
always@(posedge clk or negedge rst)
begin
if(!rst)
data_out<=8'b0;
else
case(rd_flag)
0:data_out<=buffer_1;
1:data_out<=buffer_2;
default:data_out<=0;
endcase
end
endmodule
3.乒乓操作测试文件
`timescale 1ns / 1ps
module tb_pingpong_operation;
reg clk;
reg rst;
reg [7:0] data_in;
wire [7:0] data_out;
initial
begin
clk<=0;
rst<=0;
#100 rst<=1;
end
always #10 clk<=~clk;
always@(posedge clk or negedge rst)
begin
if(!rst)
data_in<=0;
else
data_in<=data_in+1;
end
pingpong_operation u_pingpong(
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_out(data_out)
);
endmodule
4.仿真波形