acc2[1],acc2}
+{acc1[1],acc1[1],acc1[1],acc1[1],acc1[1],acc1}; end endmodule 1.分析程序设计
使用MAC单元完成乘加运算(包括单MAC和多MAC的情况)这个方法可以利用FPGA中已有的MAC单元(像Xilinx Spartan 3E-100中有四个乘加单元),只要设计好数据运算流程,就能方便高效地实现FIR运算。使用MAC单元还有一个优点是系数可以存成系数表,可以方便地修改,这是移位方法代替乘法运算所不及的。
使用移位代替乘法运算这个方法的优点是速度快,例如11阶的滤波器,完成一次运算需要11次乘法,如果使用单MAC的话,需要11个时钟周期来完成,而使用移位方法可以在一个时钟周期完成11个乘法运算;缺点是需要另外去完成滤波系数到移位位数的换算,如果修改滤波系数的话,程序修改将会比较麻烦,同时硬件资源也要使用多一些。 t*0.125={t[7],t[7],t[7],t[7:3]} t*0.125 = t8 = t>>3;
t为有符号数,所以是带符号右移,于是t>>3 ={t[7],t[7],t[7],t[7:3]} 之所以这么些就是为了节省资源,提高频率 以 -4*0.5 为例
-4的原码:1000 0100B 补码:1111 1100B -4>>1=0111 1110
而符号位不能变 应用原来的位代替 1111 1110B 的原码 1000 0010B =-2 2. 对程序设计中的问题分析与总结
在最开始的设计中,本文初始计划使用乘法单元。但是在程序设计的过程中我们遇见了实数乘法的问题,程序的运行遇到了困难,在与指导老师的研究中我们发现问题出在实数乘法的问题上。在Verilog的运算中实数乘法需要特殊的小数乘法器来单元来实现。在原来的38阶滤波器的设计中出现了这样子的问题。我们使用过这样的程序: reg [63:0] filter_in_force [0:3344]; reg [63:0] filter_out_expected [0:3344]; Function definitions function real abs_real; input real arg; begin
abs_real = arg > 0 ? arg : -arg;
end
endfunction function abs_real Component Instances filter u_filter ( .clk(clk),
.clk_enable(clk_enable), .reset(reset), .filter_in(filter_in), .filter_out(filter_out) ); initial begin Constants
…
系统无法实现real值得计算,于是这里需要我们用小数乘法器进行特殊单元的方案解决。于是我们要进行小数乘法器的设计。 3.小数乘法器介绍及在设计中的作用
随着FPGA 的发展以及相应EDA 软件工具的成熟,FPGA 在高速数字信号处理领域得到了越来越广泛的应用。而乘法,尤其是浮点乘法运算是数值计算和数据分析中最常用的运算之一。目前,多数FPGA 上可以实现整数和标准逻辑矢量的乘法,但不支持浮点乘法运算, 因此使得FPGA 在数值计算、数据分析和信号处理等方面受到了限制。本文采用适合于FPGA 实现的自定义26 位浮点数据格式,利用改进的基4Boot ,in_a,in_b,x1,x2,x3,x4,x5,x6,x7,y_out ); inputclk,rst_n;时钟和复位信号
input[31:0] in_a,in_b;输入的被乘数和乘数 output[31:0] y_out;输出的乘积
*寄存器类型变量 为了能更清楚的了解全处理过程, 特地设计为输出的,不然仿真可能会被综合掉* output[15:0] x1,x2,x3,x4; output[0:0] x5; output[29:0] x6; output[31:0] x7; reg[31:0] y_out;
reg[15:0] x1,x2,x3,x4; reg[0:0] x5;
reg[29:0] x6; reg[31:0] x7; always@ (posedgeclk ) begin
if(!rst_n )复位时,全部寄存器变量清零 begin x1<=16'b0; x2<=16'b0; x3<=16'b0; x4<=16'b0; x5<=1'b0; x6<=30'b0; x7<=32'b0; y_out<=32'b0; end else begin
x1<=in_a[31:16];截取16位被乘数, x2<=in_b[31:16];截取16位乘数
x3<=(x1[15]==0)?x1:{x1[15],~x1[14:0]+1'b1}; 据最高位判断是否为负数, 若负数则把补码转成原码
x4<=(x2[15]==0)?x2:{x2[15],~x2[14:0]+1'b1};
x5<=x3[15]^x4[15];两数符号位相异或,得到乘积的符号位 x6<=x3[14:0]*x4[14:0];两数的数据位相乘
x7<={x5,x6,1'b0}; 乘积由1位符号位和30位数据位及1位无关组成; 因为是小数,往低位生长,所以无关位放置最低位 y_out<=(x7[31]==0)?x7:{x7[31],~x7[30:0]+1'b1}; end end endmodule
小数乘法器的仿真结果如下图2-14所示:
图2-14小数乘法器仿真结果
全过程可以看成:把32位的小数截取高16位左移16位,变为16位整数相乘得到32位整数乘积后,右移32位调整无关位的位置得到32位小数,这样就可以完成早期程序中的小数乘法功能,然后来进行设计中的FPGA数字滤波器设计的优化。
在先前的设计中我们使用Matlab进行综合仿真设计,并且借助FDAtool设计出滤波器。在Quartus 2的仿真中我们发现程序无法正常的完成运行,究其原因在于小数乘法器的问题。在原来的滤波器中需要对每一个参数进行单独设置,这样会使得程序占有巨量的篇幅大大的增加了工作量和容错度。于是,我们需求另外一种方法来解决这个问题,后来我们研究了移位算法。利用移位来把小数运算转换成整数运算,这样我们的11阶滤波器程序大大减少篇幅同时也增加了程序的可读程度和稳定程度。 3 滤波器仿真滤波 3.1设置混合信号
在Matlab中进行我们设计过的FIR数字滤波器的仿真,首先我们启动Matlab中的Simulink,启动方式是直接在文本窗口中输入命令Simulink,或者点击Matlab中的快速启动按钮。
图2-15 Simulink工具窗口图
这样一个信号: Fs=200; t=(1:200)Fs; x1=sin(2*pi*t*10); x2=sin(2*pi*t*30); x3=sin(2*pi*t*60); X= x1+ x2+ x3; plot(t,X);
title('杨成杰本科毕业设计混合正弦波信号X(t)-滤波前'); grid; Module end
整个模拟滤波信号结束 使用软件仿真出待滤波信号
混合信号设定之后利用Matlab工具进行模型仿真。
相关推荐: