乒乓操作及串并转换设计篇

 

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的另一端8I/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

//-----------------------------------------------------

串并转换很简单,就是移位寄存器,后面最好跟一个锁存器,实现你所要求的功能需要四位移位寄存器和四位锁存器,锁存器的作用就是保持并行数据在移位时不发生变化:

 

module shift(nreset,clk,en,in,out);

input  nreset,clk,en,in;
output [3:0] out;

reg [1:0] count;//移位计数,控制并行数据更新,这里是4bit并行数据
reg [3:0] data;
reg [3:0] out;

/* 移位计数,用于并行数据输出,也可以外加一个脉冲控制数据边界,这里移位4bit就并行输出一次*/
always@(posedge clk or negedge nreset)
     begin
          if(~nreset)
               count <= 2'b00;
          else if(en)
               count <= count + 2'b01;
     end
//移位
always@(posedge clk or negedge nreset)
     begin
          if(~nreset)
               data <= 4'b0000;
          eale if(en)
               data <= {data[2:0],in};
     end
//并行输出
always@(posedge clk or negedge nreset)
     begin
          if(~nreset)
               out <= 4'b0000;
          else if(en && (count==2'b11))
               out <= data;
     end
endmodule

我编译、仿真过了,没有问题,你原有的out<={out,in}应该写成像这样data <= {data[2:0],in};这就是一个移位寄存器!

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值