乒乓操作及串并转换设计篇
0赞FPGA/CPLD重要设计思想及工程应用
乒乓操作及串并转换设计篇
概述
“乒乓操作”是一个常常应用于数据流控制的处理技巧,典型的乒乓操作方法如下 图所示。
乒乓操作的处理流程
输入数据流通过“输入数据选择单元”将数据流等时分配到两个数据缓冲区,数据缓冲模块可以为任何存 储模块,比较常用的存储单元为双口RAM(DPRAM) 、单口RAM(SPRAM) 、FIFO等。
在第一个缓冲周期,将输入的数据流缓存到“数据缓冲模块1”。在第2 个缓 冲周期,通过“输入数据选择单元”的切换,将输入的数据流缓存到“数据缓冲模块2”,同时将“数据缓冲模块1”缓存的第1 个周期数据通过“输出数据选择单元”的选择,送到“数据流运算处理模块”进行运算处理。
在第3 个缓冲周期通过“输入数据选择单元”的再次切换,将输入的数据流缓存到“数据缓冲模块1”,同时将“数据缓冲模块2”缓存的第2 个周期的数据通过“输出数据选择单元”切换,送到“数据流运算处理模块”进行运算处理。如此循环。
利用乒乓操作完成 数据的无缝缓冲与处理
乒乓操作可以通过“输入数据选择单元”和“输出数据选择单元”按节拍、相互配合的切换,将经过缓冲的数据流没有停顿地送到“数据流运算处理模块”进行运算与处理。
把乒乓操作模块当做一个整体,站在这个模块的两端看数据,输入数据流和输出数据流都是连续不断的,没有任何停顿,因 此非常适合对数据流进行流水线式处理。所以乒乓操作常常应用于流水线设计中,完成数据的无缝缓冲与处理。
串并转换
串并转换是FPGA 设计的一个重要技巧,它是高速数据流处理的常用手段,串并转换的实现方法多种多样,根据数据的排序和数量的要求,可 以选用寄存器、双口RAM(DPRAM) 、单口RAM(SPRAM) 、FIFO 等实现。
若想数据的缓冲区开得很大,可以通过DPRAM 实现了数据流的串并转换,对于数量比较小的设计可以采用寄存器完成串并转换。如无特殊需求,系统中应该 用同步时序设计完成串并之间的转换。
那么在工程应用中,程序里怎么才能体现出串并转换设计的思想呢?怎么才能提高系统的处理速度呢?我们可以先来做一个 串并转换的框架型设计。
这个章节老师没有给留下什么固定题目,所以自己构思起来也有点麻烦。想来想去就做个串入并出的设计吧。
设计的思想是这样的,有一组数据以50MHZ的速率从FPGA的一个I/O口传入,要实现在FPGA的另一端8个I/O口以50/8MHZ的速率把传入的速率吐出。也就 是说每隔8个主时钟周期要从8个输出口输出 从输入口输入的8个数据。
功能仿真的波形如下:
如图,从rst完成复位(拉低)并且输入使能信号en置位(拉高)后输入的数据(头8个时钟周期)为10101010,在第9个时钟周期,输出使能信号en_out拉高了,说明此时可以从8位并行数据输出 口取数了,data_out的输出16进制aa正好就是输入的10101010,所以第一个数据 的串并转换正确无误。往后输入11110000,输出是16进 制f0也没错……
该程序实现了串并转换的要求,这样原来50MH速率传送的数 据经过FPGA串并转换后只要用1/8的时 钟频率就能完成数据流的传输,也可以说这是一个面积换速度的典型。
程序:
module sp_top(scl,rst,en,sda,data_out,en_out);
input scl;//50MHz主时钟信号
input rst;//复位信号,高有效
input en;//数据输入使能,高有效
input sda;//串行输入数据
output[7:0] data_out;//并行输出数据
output en_out;//输出使能信号,高有效
wire[7:0] data_reg;//并行输出数据寄存器
wire rdy;
series_in series_in(scl,rst,en,sda,data_reg,rdy);
parallel_out parallel_out(scl,rst,data_reg,rdy,data_out,en_out);
endmodule
module series_in(scl,rst,en,sda,data_reg,rdy);
input scl;
input rst;
input en;
input sda;
output[7:0] data_reg;
output rdy;
reg[7:0] data_reg;
reg[2:0] i;
reg rdy;
always @ ( posedge scl )
begin
if(rst) begin i <= 3'd0; data_reg <= 8'dz; rdy <= 0; end
else if(en)
begin
data_reg <= {data_reg[6:0],sda};
i <= i+1;
if(i==3'd7) rdy <= 1;
else rdy <= 0;
end
else begin i <= 3'd0; data_reg <= 8'dz; rdy <= 0; end
end
endmodule
module parallel_out(scl,rst,data_reg,rdy,data_out,en_out);
input scl;
input rst;
input[7:0] data_reg;
input rdy;
output[7:0] data_out;
output en_out;
reg[7:0] data_out;
reg en_out;
always @ ( posedge scl )
begin
if(rst) begin data_out <= 8'dz; en_out <= 0; end
else if(rdy) begin data_out <= data_reg; en_out <= 1; end
else begin data_out <= 8'dz; en_out <=0; end
end
endmodule