特权同学

基于FPGA的流水线设计

0
阅读(2747)

FPGA/CPLD重要设计思想及工程应用

流水线设计篇

概述

流水线设计是高速电路设计中的一个常用设计手段。如果某个设计的处理流程分为若干步骤,而且整个数据处理是“单流向”的,即没有反馈或者迭代运算,前一个步骤的输出是下一个步骤的输入,则可以考虑采用流水线设计方法来提高系统的工作频率。

流水线处理的应用

在很多领域的高速电子系统中都运用了流水线处理的方法,如高速通信系统、高速采集系统、高速导航系统、高速搜索系统等等。流水线处理方式之所以能够很大程度上提高数据流的处理速度,是因为复制了处理模块,它是面积换取速度思想的又一种具体体现。

流水线设计应用实验

假设该设计为某实时通信系统的一个模块,该系统采样频率为5MHz,采样精度为32位。我们需要设计的内容为:对采样数据先进行加减偏移量的运算,假设需要加十六进制数00000077h的偏移量,然后把该数据压缩为16位数据,便于采样后的信号处理运算,压缩数据时保持精度相对高些。这里我们假设信号处理运算很简单,就是将压缩后的数据先减去十六进制数00ffh,然后取差值的低八位数据值做为该设计的输出。

在程序里,进行了四步的流水线作业。所以在功能仿真出来的波形图中可以看到,在en使能(粗黄线)后的三个时钟周期(也即第四个时钟上升沿)后(细黄线)en_out拉高了,dout端开始有输出的数据,而且输出的数据是每一个时钟周期来一个,和输入的数据是同步的。所谓流水作业,在实际硬件电路中就是把一个大的组合逻辑分成各个小的组合逻辑,每一个输入的信号都必须顺次通过各个阶段的操作,而各个阶段的操作又是同步进行的,这就像工厂的生产流水线一样,会有源源不断的数据信号从输出端送出。另外,从这个实验中也可以更深刻的体会到Verilog的并行性。

另外从综合后的RTL视图中可以看到四级的流水结构:

程序:

module liu_shui(clk,rst,data,en,en_out,dout);

input clk;//时钟信号

input rst;//复位信号

input[31:0] data;//输入信号

input en;//输入信号使能,如果为1说明有信号输入

output en_out;//输出信号使能,如果为1说明输出经过处理的信号

output[7:0] dout;//输出信号


wire en_1,en_2,en_3;

wire[31:0] dout_1;

wire[15:0] dout_2,dout_3;


liu_1 liu_1(clk,rst,data,en,en_1,dout_1);

liu_2 liu_2(clk,rst,dout_1,en_1,en_2,dout_2);

liu_3 liu_3(clk,rst,dout_2,en_2,en_3,dout_3);

liu_4 liu_4(clk,rst,dout_3,en_3,en_out,dout);


endmodule



module liu_1(clk,rst,data,en,en_1,dout_1);

input clk;

input rst;

input[31:0] data;

input en;

output en_1;

output[31:0] dout_1;

reg[31:0] dout_1;

reg en_1;


always@(posedge clk)

begin

if(!rst) begin dout_1 <= 32'h00000000;en_1 <= 0; end

else if(en) begin dout_1 <= data+32'h00000077;en_1 <= 1; end

else en_1 <= 0;

end


endmodule



module liu_2(clk,rst,dout_1,en_1,en_2,dout_2);

input clk;

input rst;

input[31:0] dout_1;

input en_1;

output en_2;

output[15:0] dout_2;

reg[15:0] dout_2;

reg en_2;


always@(posedge clk)

begin

if(!rst) begin dout_2 <= 16'h0000;en_2 <= 0; end

else if(en_1) begin dout_2 <= dout_1[31:16];en_2 <= 1; end

else en_2 <= 0;

end


endmodule



module liu_3(clk,rst,dout_2,en_2,en_3,dout_3);

input clk;

input rst;

input[15:0] dout_2;

input en_2;

output en_3;

output[15:0] dout_3;

reg[15:0] dout_3;

reg en_3;

parameter num="16"'h00ff;


always@(posedge clk)

begin

if(!rst) begin dout_3 <= 16'h0000;en_3 <= 0; end

else if(en_2) begin dout_3 <= dout_2-num;en_3 <= 1; end

else en_3 <= 0;

end


endmodule



module liu_4(clk,rst,dout_3,en_3,en_out,dout);

input clk;

input rst;

input[15:0] dout_3;

input en_3;

output en_out;

output[7:0] dout;

reg[7:0] dout;

reg en_out;


always@(posedge clk)

begin

if(!rst) begin dout <= 8'h00;en_out <= 0; end

else if(en_3) begin dout <= dout_3[7:0];en_out <= 1; end

else en_out <= 0;

end


endmodule

Baidu
map