iir调试记录

1.目的

实现采样率fs=50MHz,通带为5MHz~15MHz,阻带衰减60dB的IIR带通滤波器

2.方案

采取直接型

3.详细设计

(1)确定滤波器的系数,系数和滤波器输出量化位宽

先根据要求的fs,fc1,fc2以及阻带衰减确定系数,当初如果设置截止频率f1=5MHz,f2 = 15MHz,实际的截止频率差很多,如图1。因此修改为f1 = 2.6MHz和f2 = 19.3MHz就能满足真正的通带为5MHz~15MHz,如图2满足要求后,再对系数量化。一定要确定好系数和输出数据的位宽,不满足就必须更改位宽,直到达到要求,才能进行下一步。例如:如图3,系数和输出数据的位宽都为8bits,量化后滤波器的响应与理想响应差太远,不能达到滤波要求。但如图4,系数13bits,输出数据位宽为14bit,量化后的幅频特性与理想滤波器的差不多,就能满足要求。(当然,位宽可以尽量量化大点,但相应的也更浪费资源)

(a)

(b)

图1 f1=5MHz,f2 = 15MHz滤波器的幅频特性

(a)

(b)

图2 f1=2.6MHz,f2 = 19.3MHz滤波器的幅频特性

图3 量化位宽不足

图4 量化位宽合适

文件:filter_coe.m

clc;

clear all;

fs = 50e6; %采样频率

f1 = 2.6e6;

f2 = 19.3e6;

N = 5; %5阶

Rp = 60;%阻带衰减

Wn = [2*f1/fs 2*f2/fs];%截止频率

% Qcoe=8; %滤波器系数字长

% Qout=8; %滤波器输出字长

Qcoe=13; %滤波器系数字长

Qout=14; %滤波器输出字长

delta=[1,zeros(1,511)]; %单位冲激信号作为输入信号

[b,a] = cheby2(N,Rp,Wn);

figure(1)

freqz(b,a,1024,fs);

%对滤波器系数进行量化,四舍五入截尾

%量化系数

m = max(max(abs(a)),max(abs(b)));

Qm = floor(log2(m/a(1))); %向下取整

if Qm < log2(m/a(1))

Qm = Qm + 1;

end

Qm = 2^Qm;

Qa = round(a/Qm*(2^(Qcoe-1)-1)) %四舍五入取整

Qb = round(b/Qm*(2^(Qcoe-1)-1)) %四舍五入取整

%求理想幅度响应

y=filter(b,a,delta);

%求量化后的幅度响应,QuantIIRDirectArith为自编的根据系数及输出数据量化位数计算

%IIR滤波器输出的函数

Quant = QuantIIR(Qb,Qa,delta,Qcoe,Qout);

%求滤波器输出幅频响应

Fy=20*log10(abs(fft(y))); Fy=Fy-max(Fy);

FQuant=20*log10(abs(fft(Quant))); FQuant=FQuant-max(FQuant);

%设置幅频响应的横坐标单位为Hz

x_f=[0:(fs/length(delta)):fs-1];

figure(2);

plot(x_f,Fy,’-‘,x_f,FQuant,’.’);

axis([0 fs/2 -100 5]); %只显示正频率部分的幅频响应

xlabel(‘频率(Hz)’);ylabel(‘幅度(dB)’);

legend(‘理想输出’,’量化后输出结果’);

grid on;

(2)产生激励信号用作仿真

这里产生频率分别为:80KHz,10MHz,20MHz的三个正弦波叠加,对它做14bit量化,并以二进制存入txt文件中。在modelsim仿真时,读取txt文件的数据作为设计输入。

                                                                                             图4  激励信号

文件:test_signal_produce.m

clc;

clear all;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%变量声明区

f1 = 80e3; %80KHz

f2 = 12e6; %12MHz

f3 = 20e6; %20MHz

fs = 50e6; %采样频率50MHz

data_num = 10000; %存10000个数据

width = 8; %输入数据量化位宽

len = 2^nextpow2(data_num); %fft长度

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%数据产生区

t = (0:data_num-1)/fs;

x = sin(2*pi*f1*t) + sin(2*pi*f2*t) + sin(2*pi*f3*t);

x = x/max(abs(x)); %归一化

Q_x = round(x*(2^(width-1)-1)); %量化

fft_x = fft(x,len);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%将数据以二进制形式写入txt文件

fid = fopen(‘C:\Users\lidong\Desktop\iir_bpf\Matlab\xin.txt’,’w+’);

for i=1:length(Q_x)

x_bit = dec2bin(Q_x(i)+(Q_x(i)<0)*2^width,width);

for j=1:width

if x_bit(j) == ‘1’

tb = 1;

else

tb = 0;

end

fprintf(fid,’%d’,tb);

end

fprintf(fid,’\n’);

end

fprintf(fid,’;’);

fclose(fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%滤波器

fs = 50e6; %采样频率

fc1 = 2.6e6;

fc2 = 19.3e6;

N = 5; %5阶

Rp = 60;%阻带衰减

Wn = [2*fc1/fs 2*fc2/fs];%截止频率

[b,a] = cheby2(N,Rp,Wn);

f = fs*(0:len/2 - 1)/len;

filter_x = filter(b,a,x);

y = fft(filter_x,len);

subplot(2,2,1);

plot(t,x);

title(‘原始信号(时域)’);

grid on;

subplot(2,2,2);

plot(f,abs(fft_x(1:len/2)));

title(‘原始信号(频域)’);

xlabel(‘Hz’);ylabel(‘幅值’);

grid on;

subplot(2,2,3);

plot(filter_x(1:200));

title(‘滤波后(时域)’);

grid on;

subplot(2,2,4);

plot(f,abs(y(1:len/2)));

title(‘滤波后(时域)’);

xlabel(‘Hz’);ylabel(‘幅值’);

grid on;

(3)根据直接型框图编写verilog程序

文件:iir_bpf.v

/*******************************************************************************************************************************************************

模块名:iir_bpf

功能:实现通带为5-15MHz,阻带衰减为60dB的5阶IIR带通滤波器(采样频率为50MHz),采用切比雪夫II型函数设计

参数:clk为模块的时钟,50MHz;rst_n是模块的复位信号,低电平有效,异步复位;xin是模块输入,位宽14bit;yout是滤波后的输出,也是14bit。

滤波器量化后的系数(13bits量化)为:

分子b = [38 -20 -131 27 230 0 -230 -27 131 20 -38]

分母a = [1024 -2337 3127 -3241 3071 -2227 1268 -587 238 -60 9]

时间:2016.3.26

作者:冬瓜

Email:[email protected]

*******************************************************************************************************************************************************/

module iir_bpf

(

input wire clk, //FPGA时钟50MHz

input wire rst_n, //复位信号,低电平有效

input wire [ 13:0 ] xin, // 数据输入

output reg [ 13:0 ] yout // 滤波后的数据输出

);

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//变量声明区

reg signed[ 13:0 ] xin_r1,xin_r2,xin_r3,xin_r4,xin_r5;

reg signed[ 13:0 ] xin_r6,xin_r7,xin_r8,xin_r9,xin_r10,xin_r11;

reg signed[ 13:0 ] yin_r1,yin_r2,yin_r3,yin_r4,yin_r5;

reg signed[ 13:0 ] yin_r6,yin_r7,yin_r8,yin_r9,yin_r10,yin_r11;

wire signed[ 26:0 ] xmult_w0,xmult_w1,xmult_w2,xmult_w3,xmult_w4;

wire signed[ 26:0 ] xmult_w5,xmult_w6,xmult_w7,xmult_w8,xmult_w9,xmult_w10;

wire signed[ 26:0 ] ymult_w1,ymult_w2,ymult_w3,ymult_w4,ymult_w5;

wire signed[ 26:0 ] ymult_w6,ymult_w7,ymult_w8,ymult_w9,ymult_w10;

wire signed[ 30:0 ] feedforward;

wire signed[ 30:0 ] feedback;

wire signed[ 31:0 ] ysum;

wire signed[ 31:0 ] ydiv;

wire signed[ 13:0 ] yin;

wire signed [12:0 ] coeb[10:0]; //滤波器系数,分子b

wire signed [12:0 ] coea[10:0]; //滤波器系数,分母a

assign coea[0] = 13’d1024;

assign coea[1] = -13’d2337;

assign coea[2] = 13’d3127;

assign coea[3] = -13’d3241;

assign coea[4] = 13’d3071;

assign coea[5] = -13’d2227;

assign coea[6] = 13’d1268;

assign coea[7] = -13’d587;

assign coea[8] = 13’d238;

assign coea[9] = -13’d60;

assign coea[10] = 13’d9;

assign coeb[0] = 13’d38;

assign coeb[1] = -13’d20;

assign coeb[2] = -13’d131;

assign coeb[3] = 13’d27;

assign coeb[4] = 13’d230;

assign coeb[5] = 13’d0;

assign coeb[6] = -13’d230;

assign coeb[7] = -13’d27;

assign coeb[8] = 13’d131;

assign coeb[9] = 13’d20;

assign coeb[10] = -13’d38;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

always @(posedge clk or negedge rst_n)

if (rst_n == 1’b0) //初始化寄存器

begin

xin_r1 <= ‘d0;

xin_r2 <= ‘d0;

xin_r3 <= ‘d0;

xin_r4 <= ‘d0;

xin_r5 <= ‘d0;

xin_r6 <= ‘d0;

xin_r7 <= ‘d0;

xin_r8 <= ‘d0;

xin_r9 <= ‘d0;

xin_r10 <= ‘d0;

xin_r11 <= ‘d0;

end

else

begin

xin_r1 <= xin;

xin_r2 <= xin_r1;

xin_r3 <= xin_r2;

xin_r4 <= xin_r3;

xin_r5 <= xin_r4;

xin_r6 <= xin_r5;

xin_r7 <= xin_r6;

xin_r8 <= xin_r7;

xin_r9 <= xin_r8;

xin_r10 <= xin_r9;

xin_r11 <= xin_r10;

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//分子b = [38 -20 -131 27 230 0 -230 -27 131 20 -38]

mult14x13 mult14x13_instb1 (

.dataa ( xin ),

.datab ( coeb[0] ),

.result ( xmult_w0 )

);

mult14x13 mult14x13_instb2 (

.dataa ( xin_r1 ),

.datab ( coeb[1] ),

.result ( xmult_w1 )

);

mult14x13 mult14x13_instb3 (

.dataa ( xin_r2 ),

.datab ( coeb[2] ),

.result ( xmult_w2 )

);

mult14x13 mult14x13_instb4 (

.dataa ( xin_r3 ),

.datab ( coeb[3] ),

.result ( xmult_w3 )

);

mult14x13 mult14x13_instb5 (

.dataa ( xin_r4 ),

.datab ( coeb[4] ),

.result ( xmult_w4 )

);

mult14x13 mult14x13_instb6 (

.dataa ( xin_r5 ),

.datab ( coeb[5] ),

.result ( xmult_w5 )

);

mult14x13 mult14x13_instb7 (

.dataa ( xin_r6 ),

.datab ( coeb[6] ),

.result ( xmult_w6 )

);

mult14x13 mult14x13_instb8 (

.dataa ( xin_r7 ),

.datab ( coeb[7] ),

.result ( xmult_w7 )

);

mult14x13 mult14x13_instb9 (

.dataa ( xin_r8 ),

.datab ( coeb[8] ),

.result ( xmult_w8 )

);

mult14x13 mult14x13_instb10 (

.dataa ( xin_r9 ),

.datab ( coeb[9] ),

.result ( xmult_w9 )

);

mult14x13 mult14x13_instb11 (

.dataa ( xin_r10 ),

.datab ( coeb[10] ),

.result ( xmult_w10 )

);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//计算总的零点系数

always @(posedge clk or negedge rst_n)

if( rst_n == 1’b0)

feedforward <= ‘d0;

else

feedforward <= {{4{xmult_w0[26]}},xmult_w0} + {{4{xmult_w1[26]}},xmult_w1} + {{4{xmult_w2[26]}},xmult_w2} + {{4{xmult_w3[26]}},xmult_w3} +

{{4{xmult_w4[26]}},xmult_w4} + {{4{xmult_w5[26]}},xmult_w5} + {{4{xmult_w6[26]}},xmult_w6} + {{4{xmult_w7[26]}},xmult_w7} +

{{4{xmult_w8[26]}},xmult_w8} + {{4{xmult_w9[26]}},xmult_w9} + {{4{xmult_w10[26]}},xmult_w10};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

always @(posedge clk or negedge rst_n)

if (rst_n == 1’b0 )

begin //初始化寄存器

yin_r1 <= ‘d0;

yin_r2 <= ‘d0;

yin_r3 <= ‘d0;

yin_r4 <= ‘d0;

yin_r5 <= ‘d0;

yin_r6 <= ‘d0;

yin_r7 <= ‘d0;

yin_r8 <= ‘d0;

yin_r9 <= ‘d0;

yin_r10 <= ‘d0;

yin_r11 <= ‘d0;

end

else

begin

yin_r1 <= yin;

yin_r2 <= yin_r1;

yin_r3 <= yin_r2;

yin_r4 <= yin_r3;

yin_r5 <= yin_r4;

yin_r6 <= yin_r5;

yin_r7 <= yin_r6;

yin_r8 <= yin_r7;

yin_r9 <= yin_r8;

yin_r10 <= yin_r9;

yin_r11 <= yin_r10;

end

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//分母a = [1024 -2337 3127 -3241 3071 -2227 1268 -587 238 -60 9]

mult14x13 mult14x13_insta1 (

.dataa ( yin_r1 ),

.datab ( coea[1] ),

.result ( ymult_w1 )

);

mult14x13 mult14x13_insta2 (

.dataa ( yin_r2 ),

.datab ( coea[2] ),

.result ( ymult_w2 )

);

mult14x13 mult14x13_insta3 (

.dataa ( yin_r3 ),

.datab ( coea[3] ),

.result ( ymult_w3 )

);

mult14x13 mult14x13_insta4 (

.dataa ( yin_r4 ),

.datab ( coea[4] ),

.result ( ymult_w4 )

);

mult14x13 mult14x13_insta5 (

.dataa ( yin_r5 ),

.datab ( coea[5] ),

.result ( ymult_w5 )

);

mult14x13 mult14x13_insta6 (

.dataa ( yin_r6 ),

.datab ( coea[6] ),

.result ( ymult_w6 )

);

mult14x13 mult14x13_insta7 (

.dataa ( yin_r7 ),

.datab ( coea[7] ),

.result ( ymult_w7 )

);

mult14x13 mult14x13_insta8 (

.dataa ( yin_r8 ),

.datab ( coea[8] ),

.result ( ymult_w8 )

);

mult14x13 mult14x13_insta9 (

.dataa ( yin_r9 ),

.datab ( coea[9] ),

.result ( ymult_w9 )

);

mult14x13 mult14x13_insta10 (

.dataa ( yin_r10 ),

.datab ( coea[10] ),

.result ( ymult_w10 )

);

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//计算总的极点系数

assign feedforward = {{4{xmult_w0[26]}},xmult_w0} + {{4{xmult_w1[26]}},xmult_w1} + {{4{xmult_w2[26]}},xmult_w2} + {{4{xmult_w3[26]}},xmult_w3} +

{{4{xmult_w4[26]}},xmult_w4} + {{4{xmult_w5[26]}},xmult_w5} + {{4{xmult_w6[26]}},xmult_w6} + {{4{xmult_w7[26]}},xmult_w7} +

{{4{xmult_w8[26]}},xmult_w8} + {{4{xmult_w9[26]}},xmult_w9} + {{4{xmult_w10[26]}},xmult_w10};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//计算最后的输出

assign ysum = {{{feedforward[30]}},feedforward} - {{feedback[30]},feedback};//31bits

assign ydiv = {{10{ysum[30]}},ysum[30:10]};

assign yin = ydiv[ 13:0 ];

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//最后结果加一级寄存器,提高系统频率

always @(posedge clk)

yout <= ydiv[ 13:0 ];

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

endmodule

(4)Modelsim仿真

编写激励文件iir_bpf_tb.v和脚本文件run.do,并新建工程,在命令窗运行run.do文件。如图5,图6输入数据(xin)为多个正弦波叠加,经过滤波器后,输出(yout)为单一的正弦波,运行完后Modelsim会把输出数据存储在txt文件中给Matlab分析。

                                                                                                                                     图5  Modelsim仿真1

                                                                                                                                     图6  Modelsim仿真2

文件:iir_bpf_tb.v

`timescale 1 ns/1 ns

module iir_bpf_tb();

///////////////////////////////////////////////////////////////////////////////////

//变量声明区

parameter clk_period = 20; //50MHz

parameter half_clk_period = clk_period/2;

parameter data_num = 10000;

parameter time_sim = data_num*clk_period;

integer i;

integer fid;

reg clk;

reg rst_n;

reg [7:0 ] xin;

reg [7:0 ] stimulus[1:data_num];

wire clk_write;

wire signed [13:0] yout;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//产生时钟和复位信号

initial

begin

clk = 0;

rst_n = 0;

#400;

rst_n = 1;

#time_sim stop;  
  end  
always #half_clk_period clk = ~clk;  
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
//读取文件数据,作为滤波器输入  
initial  
  beginreadmemb(“xin.txt”,stimulus);

i = 0;

#350;

repeat(data_num)

begin

i = i + 1;

@(posedge clk);

xin = stimulus[i];

end

end

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//将滤波器输出数据存入文件中,给Matlab分析

initial

begin

fid = fopen(“yout.txt”);if(!fid)begindisplay(“Cannot open the file!”);

$finish;

end

end

always @(posedge clk_write)

$fdisplay(fid,”%d”,yout);

assign clk_write = rst_n & clk;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//例化

iir_bpf iir_bpf_inst

(

.clk (clk), //FPGA时钟50MHz

.rst_n (rst_n), //复位信号,低电平有效

.xin (xin), // 数据输入

.yout (yout) // 滤波后的数据输出

);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

endmodule

文件:run.do

quit -sim

.main clear

vlib work

vmap work work

vlog ./iir_bpf_tb.v

vlog ./altera_lib/*.v

vlog ./../quartus_prj/ipcore_dir/mult8x16.v

vlog ./../quartus_prj/ipcore_dir/mult16x16.v

vlog ./../design/*.v

vsim -voptargs=+acc -L work work.iir_bpf_tb

add wave -divider { tb }

add wave iir_bpf_tb/*

add wave -divider { iir_bpf }

add wave iir_bpf_tb/iir_bpf_inst/*

run 50us

(5)Matlab仿真

用Matlab读取Modelsim产生的txt文件中的数据,如图7,滤波器输出数据的频谱为单一的10MHz的正弦波信号。

图7 Matlab仿真

文件:filter_analysis.m

clc;

clear all;

fs = 50e6;

%打开文件,并读取数据

fid_out = fopen(‘C:\Users\lidong\Desktop\iir_bpf\sim\yout.txt’,’r’);

[yout,N_out] = fscanf(fid_out,’%d’,inf);

fclose(fid_out);

%画时域波形

subplot(211);

plot(yout(1:100));

title(‘FPGA仿真滤波后的时域波形’);

grid on;

%归一化处理

NFFT2 = 2^nextpow2(N_out);

yout=yout/max(abs(yout));

Fout=20*log10(abs(fft(yout,NFFT2)));

Fout=Fout-max(Fout);

%画频域波形

subplot(212);

x_f=[0:(fs/length(Fout)):fs/2];

plot(x_f,Fout(1:length(x_f)),’–’);

axis([0 fs/2 -100 3]);

xlabel(‘频率(Hz)’);ylabel(‘幅度(dB)’);title(‘FPGA仿真滤波后的频谱’);

grid on;

4.遇到的问题及解决方案

(1)进行Modelsim仿真时,极点有关的寄存器以及输出均为未知状态x

解决方案:出现未知状态的原因是:开始输入数据的时间控制不对,必须在复位结束前把数据输入进来,例如复位时间是400ns,如果是在400ns之后数据输入就会导致这样的现象

图8 复位时间

图9 数据输入时间

图10 出现仿真问题

图11 修改输入数据开始时间

图12 正常仿真

(2)用Matlab对modelsim的输出仿真时,出现谐波和直流分量

解决方案:出现谐波的原因是:modelsim输出的数据(yout)不为signed型,可以在matlab仿真时,先检查文件中数据的时域波形,再看频域。

                                            图13

图14 Matlab仿真出错

5.系统优化

(1)在计算feedforward时,添加寄存器。对于一个FPGA时序电路来讲,决定整个电路运算速度是单个时钟周期内逻辑运算最多的环节。在上述程序中,完成一次完整的IIR滤波,需要10次常系数乘法运算,1次10输入的加减法运算和一次一位运算。显然一个时钟周期的逻辑运算量太大,因此在计算ysum之前,增加一级寄存器,相当于输入数据进行一个时钟周期的延迟,不影响滤波的结果。但在运算速度上,相当于原来1个周期的运算量采用两个时钟周期完成。

(2)乘法运算后的位宽可以优化1bit,因为位宽分别为N,M的两数据相乘,结果位宽是不超过M+N,而且只有在输入数据的最高位为1,其余位位0时,才会为(M+N)bit宽。因此用(M+N-1)bit表示输出结果时,相当于用-2^M + 1对 -2^M进行近似处理。

(3)可以用移位与加法运算代替乘法运算,例如系数为238时,如图15,但有些可能有多种移位方案,如图16,3071有两种方案,但显然方案2要优于方案1,因为方案2的加法运算级数更少。

图15 乘法优化

图16

技巧:通过移位和累加代替乘法限制了滤波器系数的灵活性,而且编程时比较头疼。总结一下经验(以编写yin_r4*3071为例):

先确定好几个数:assign ymult_w4 = {yin_r4,12’d0} + {yin_r4,12’d0} + {yin_r4,12’d0};

确定好前面的符号是加号还是减号:assign ymult_w4 = {yin_r4,12’d0} - {yin_r4,12’d0} - {yin_r4,12’d0};

确定拼接后面的数:assign ymult_w4 = {yin_r4,12’d0} - {yin_r4,10’d0} - {yin_r4,1’d0};

根据总位宽和输入位宽确定符号位扩展多少:assign ymult_w4 = {yin_r4,12’d0} - {{2{yin_r4[13]}},yin_r4,10’d0} - {{12{yin_r4[13]}},yin_r4};这里ymult_w* 位宽是26bit,而yin_r*是14bit,因此只需要移的位数(yin_r*右边的数)和扩展的符号位数(yin_r*左边的数)之和为26-14 = 12就行,后面计算 ymult_w5, ymult_w6。。。都是一样的。解皮带,绕大树。另外,在优化时也出现了错误,经过对比优化前后仿真图,找到了ymult_w1,ymult_w3移位算错了,从而定位到了a(1),a(3)移位移错了。

                                                                                                                                  (a)优化前

                                                                                                                                (b)优化后
                                                                                                                                         图17

(4)加法的优化。在得到feedback时,需要做9次加法,如果直接用连加,则这些加法器会一级一级的级联,组合逻辑延时太长。例如assign x = a + b + c +d + e + f;可以这样优化

assign x1 = a + b;

assign x2 = c+ d;

assign x3 = e+ f;

assign x4 = x1+ x2;

assign x = x3+ x4;

优化前后分别对应图18,图19。可以看出优化前数据要经过5个加法器,优化后只过3个加法器。

                                                                                                               图18  优化前

                                                                                                           图19  优化后

(5)由于本例采用cheby2型的IIR滤波器,分子b具有对称性,因此可以先做加/减法运算,再做乘法运算,可以节约一半乘法。例如b(1) = -b(10) = 38那么先做减法add1 = (xin_r1 - xin_r10 ),再算乘法38*add1,即可减少一次乘法。

优化前后资源对比,虽然优化后会占用多一点的逻辑资源,但优化前的乘法器用去了91%的乘法器,而优化后是0%。如图20,如图21,22,优化后功能并没有改变。

                                                   (a)  优化前                                                                                                                                                  (b)  优化后
                                                                                                                           图20  优化前后资源对比

图21

图22

//优化后

/********************************************************************************

模块名:iir_bpf

功能:实现通带为5-15MHz,阻带衰减为60dB的5阶IIR带通滤波器(采样频率为50MHz),采用切比雪夫II型函数设计

时间:2016.3.26

作者:冬瓜

Email:[email protected]

********************************************************************************/

module iir_bpf

(

input wire clk, //FPGA时钟50MHz

input wire rst_n, //复位信号,低电平有效

input wire [ 13:0 ] xin, // 数据输入

output reg [ 13:0 ] yout // 滤波后的数据输出

);

//////////////////////////////////////////////////////////////////////////////////////////////

//变量声明区

reg signed[ 30:0 ] feedforward;

reg signed[ 13:0 ] xin_r1,xin_r2,xin_r3,xin_r4,xin_r5;

reg signed[ 13:0 ] xin_r6,xin_r7,xin_r8,xin_r9,xin_r10;

reg signed[ 13:0 ] yin_r1,yin_r2,yin_r3,yin_r4,yin_r5;

reg signed[ 13:0 ] yin_r6,yin_r7,yin_r8,yin_r9,yin_r10;

wire signed[ 14:0 ] xadd0,xadd1,xadd2,xadd3,xadd4;

wire signed[ 25:0 ] xmult_w0,xmult_w1,xmult_w2,xmult_w3,xmult_w4;

wire signed[ 25:0 ] ymult_w1,ymult_w2,ymult_w3,ymult_w4,ymult_w5;

wire signed[ 25:0 ] ymult_w6,ymult_w7,ymult_w8,ymult_w9,ymult_w10;

wire signed[ 25:0 ] ymult_w1_1,ymult_w1_2;

wire signed[ 25:0 ] ymult_w2_1,ymult_w2_2;

wire signed[ 25:0 ] ymult_w3_1,ymult_w3_2;

wire signed[ 25:0 ] ymult_w5_1,ymult_w5_2;

wire signed[ 25:0 ] ymult_w6_1,ymult_w6_2;

wire signed[ 25:0 ] ymult_w7_1,ymult_w7_2;

wire signed[ 30:0 ] feedback;

wire signed[ 30:0 ] feedback1,feedback2,feedback3,feedback4;

wire signed[ 30:0 ] feedback5,feedback6,feedback7,feedback8;

wire signed[ 30:0 ] feedforward1,feedforward2,feedforward3;

wire signed[ 31:0 ] ysum;

wire signed[ 31:0 ] ydiv;

wire signed[ 13:0 ] yin;

//////////////////////////////////////////////////////////////////////////////////////////////

always @(posedge clk or negedge rst_n)

if (rst_n == 1’b0) //初始化寄存器

begin

xin_r1 <= ‘d0;

xin_r2 <= ‘d0;

xin_r3 <= ‘d0;

xin_r4 <= ‘d0;

xin_r5 <= ‘d0;

xin_r6 <= ‘d0;

xin_r7 <= ‘d0;

xin_r8 <= ‘d0;

xin_r9 <= ‘d0;

xin_r10 <= ‘d0;

end

else

begin

xin_r1 <= xin;

xin_r2 <= xin_r1;

xin_r3 <= xin_r2;

xin_r4 <= xin_r3;

xin_r5 <= xin_r4;

xin_r6 <= xin_r5;

xin_r7 <= xin_r6;

xin_r8 <= xin_r7;

xin_r9 <= xin_r8;

xin_r10 <= xin_r9;

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//分子b = [38 -20 -131 27 230 0 -230 -27 131 20 -38]

//系数具有对称性,因此先做减法,再做乘法,节约一半乘法器

assign xadd0 = {xin[13],xin} - {xin_r10[13],xin_r10}; //15bits

assign xadd1 = {xin_r1[13],xin_r1} - {xin_r9[13],xin_r9};

assign xadd2 = {xin_r2[13],xin_r2} - {xin_r8[13],xin_r8};

assign xadd3 = {xin_r3[13],xin_r3} - {xin_r7[13],xin_r7};

assign xadd4 = {xin_r4[13],xin_r4} - {xin_r6[13],xin_r6};

//用移位与加法运算代替乘法运算

assign xmult_w0 = {{10{xadd0[14]}},xadd0,1’d0} + {{9{xadd0[14]}},xadd0,2’d0} + {{6{xadd0[14]}},xadd0,5’d0}; //26bit

assign xmult_w1 = -{{9{xadd1[14]}},xadd1,2’d0} - {{7{xadd1[14]}},xadd1,4’d0}; //26bit

assign xmult_w2 = -{{11{xadd2[14]}},xadd2} - {{10{xadd2[14]}},xadd2,1’d0} - {{4{xadd2[14]}},xadd2,7’d0}; //26bit

assign xmult_w3 = {{6{xadd3[14]}},xadd3,5’d0} - {{11{xadd3[14]}},xadd3} - {{9{xadd3[14]}},xadd3,2’d0}; //26bit

assign xmult_w4 = {{3{xadd4[14]}},xadd4,8’d0} - {{10{xadd4[14]}},xadd4,1’d0} - {{8{xadd4[14]}},xadd4,3’d0} - {{7{xadd4[14]}},xadd4,4’d0};//26bit

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//由于加法的级数太长,对其拆分,减少组合逻辑延时,提高系统的Fmax

assign feedforward1 = {{4{xmult_w0[25]}},xmult_w0} + {{4{xmult_w1[25]}},xmult_w1};

assign feedforward2 = {{4{xmult_w2[25]}},xmult_w2} + {{4{xmult_w3[25]}},xmult_w3};

assign feedforward3 = {{4{xmult_w4[25]}},xmult_w4} + feedforward1;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//计算总的零点系数

always @(posedge clk or negedge rst_n)

if( rst_n == 1’b0)

begin

feedforward <= ‘d0;

end

else

begin

feedforward <= feedforward2 + feedforward3;

end

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

always @(posedge clk or negedge rst_n)

if (rst_n == 1’b0 )

begin //初始化寄存器

yin_r1 <= ‘d0;

yin_r2 <= ‘d0;

yin_r3 <= ‘d0;

yin_r4 <= ‘d0;

yin_r5 <= ‘d0;

yin_r6 <= ‘d0;

yin_r7 <= ‘d0;

yin_r8 <= ‘d0;

yin_r9 <= ‘d0;

yin_r10 <= ‘d0;

end

else

begin

yin_r1 <= yin;

yin_r2 <= yin_r1;

yin_r3 <= yin_r2;

yin_r4 <= yin_r3;

yin_r5 <= yin_r4;

yin_r6 <= yin_r5;

yin_r7 <= yin_r6;

yin_r8 <= yin_r7;

yin_r9 <= yin_r8;

yin_r10 <= yin_r9;

end

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//分母a = [1024 -2337 3127 -3241 3071 -2227 1268 -587 238 -60 9]

//用移位与加法运算代替乘法运算

//assign ymult_w1 = -{{12{yin_r1[13]}},yin_r1} - {{7{yin_r1[13]}},yin_r1,5’d0} - {{4{yin_r1[13]}},yin_r1,8’d0} -{{{yin_r1[13]}},yin_r1,11’d0};//26bits

//assign ymult_w2 = {{9{yin_r2[13]}},yin_r2,3’d0} + {{8{yin_r2[13]}},yin_r2,4’d0} + {{7{yin_r2[13]}},yin_r2,5’d0} + {{2{yin_r2[13]}},yin_r2,10’d0} + {{{yin_r2[13]}},yin_r2,11’d0} - {{12{yin_r2[13]}},yin_r2};//26bits

//assign ymult_w3 = -{{12{yin_r3[13]}},yin_r3} - {{9{yin_r3[13]}},yin_r3,3’d0} - {{7{yin_r3[13]}},yin_r3,5’d0} - {{5{yin_r3[13]}},yin_r3,7’d0} - {{2{yin_r3[13]}},yin_r3,10’d0} - {{yin_r3[13]},yin_r3,11’d0};//26bits

//assign ymult_w4 = {yin_r4,12’d0} - {{2{yin_r4[13]}},yin_r4,10’d0} - {{12{yin_r4[13]}},yin_r4}; //26bits

//assign ymult_w5 = -{{12{yin_r5[13]}},yin_r5} - {{11{yin_r5[13]}},yin_r5,1’d0} - {{8{yin_r5[13]}},yin_r5,4’d0} - {{7{yin_r5[13]}},yin_r5,5’d0} - {{5{yin_r5[13]}},yin_r5,7’d0} - {{yin_r5[13]},yin_r5,11’d0};//26bits

//assign ymult_w6 = {{2{yin_r6[13]}},yin_r6,10’d0} + {{4{yin_r6[13]}},yin_r6,8’d0} - {{10{yin_r6[13]}},yin_r6,2’d0} - {{9{yin_r6[13]}},yin_r6,3’d0}; //26bits

//assign ymult_w7 = -{{12{yin_r7[13]}},yin_r7} - {{11{yin_r7[13]}},yin_r7,1’d0} - {{9{yin_r7[13]}},yin_r7,3’d0} - {{6{yin_r7[13]}},yin_r7,6’d0} - {{3{yin_r7[13]}},yin_r7,9’d0};//26bits

//assign ymult_w8 = {{4{yin_r8[13]}},yin_r8,8’d0} - {{11{yin_r8[13]}},yin_r8,1’d0} - {{8{yin_r8[13]}},yin_r8,4’d0}; //26bits

//assign ymult_w9 = {{10{yin_r9[13]}},yin_r9,2’d0} - {{6{yin_r9[13]}},yin_r9,6’d0}; //26bits

//assign ymult_w10 = {{12{yin_r10[13]}},yin_r10} + {{9{yin_r10[13]}},yin_r10,3’d0};

assign ymult_w1_1 = -{{12{yin_r1[13]}},yin_r1} - {{7{yin_r1[13]}},yin_r1,5’d0};//26bits

assign ymult_w1_2 = -{{4{yin_r1[13]}},yin_r1,8’d0} - {{{yin_r1[13]}},yin_r1,11’d0};

assign ymult_w1 = ymult_w1_1 + ymult_w1_2;

assign ymult_w2_1 = {{9{yin_r2[13]}},yin_r2,3’d0} + {{8{yin_r2[13]}},yin_r2,4’d0} + {{7{yin_r2[13]}},yin_r2,5’d0};

assign ymult_w2_2 = {{2{yin_r2[13]}},yin_r2,10’d0} + {{{yin_r2[13]}},yin_r2,11’d0} - {{12{yin_r2[13]}},yin_r2};

assign ymult_w2 = ymult_w2_1 + ymult_w2_2;//26bits

assign ymult_w3_1 = -{{12{yin_r3[13]}},yin_r3} - {{9{yin_r3[13]}},yin_r3,3’d0} - {{7{yin_r3[13]}},yin_r3,5’d0};

assign ymult_w3_2 = -{{5{yin_r3[13]}},yin_r3,7’d0} - {{2{yin_r3[13]}},yin_r3,10’d0} - {{yin_r3[13]},yin_r3,11’d0};

assign ymult_w3 = ymult_w3_1 + ymult_w3_2; //26bits

assign ymult_w4 = {yin_r4,12’d0} - {{2{yin_r4[13]}},yin_r4,10’d0} - {{12{yin_r4[13]}},yin_r4}; //26bits

assign ymult_w5_1 = -{{12{yin_r5[13]}},yin_r5} - {{11{yin_r5[13]}},yin_r5,1’d0} - {{8{yin_r5[13]}},yin_r5,4’d0};

assign ymult_w5_2 = -{{7{yin_r5[13]}},yin_r5,5’d0} - {{5{yin_r5[13]}},yin_r5,7’d0} - {{yin_r5[13]},yin_r5,11’d0};

assign ymult_w5 = ymult_w5_1 + ymult_w5_2; //26bits

assign ymult_w6_1 = {{2{yin_r6[13]}},yin_r6,10’d0} + {{4{yin_r6[13]}},yin_r6,8’d0};

assign ymult_w6_2 = -{{10{yin_r6[13]}},yin_r6,2’d0} - {{9{yin_r6[13]}},yin_r6,3’d0};

assign ymult_w6 = ymult_w6_1 + ymult_w6_2; //26bits

assign ymult_w7_1 = -{{12{yin_r7[13]}},yin_r7} - {{11{yin_r7[13]}},yin_r7,1’d0} - {{9{yin_r7[13]}},yin_r7,3’d0};

assign ymult_w7_2 = -{{6{yin_r7[13]}},yin_r7,6’d0} - {{3{yin_r7[13]}},yin_r7,9’d0};

assign ymult_w7 = ymult_w7_1 + ymult_w7_2; //26bits

assign ymult_w8 = {{4{yin_r8[13]}},yin_r8,8’d0} - {{11{yin_r8[13]}},yin_r8,1’d0} - {{8{yin_r8[13]}},yin_r8,4’d0}; //26bits

assign ymult_w9 = {{10{yin_r9[13]}},yin_r9,2’d0} - {{6{yin_r9[13]}},yin_r9,6’d0}; //26bits

assign ymult_w10 = {{12{yin_r10[13]}},yin_r10} + {{9{yin_r10[13]}},yin_r10,3’d0};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////计算总的极点系数,由于加法的级数太长,对其拆分,减少组合逻辑延时,提高系统的Fmax

assign feedback1 = {{4{ymult_w1[25]}},ymult_w1} + {{4{ymult_w2[25]}},ymult_w2};

assign feedback2 = {{4{ymult_w3[25]}},ymult_w3} + {{4{ymult_w4[25]}},ymult_w4};

assign feedback3 = {{4{ymult_w5[25]}},ymult_w5} + {{4{ymult_w6[25]}},ymult_w6};

assign feedback4 = {{4{ymult_w7[25]}},ymult_w7} + {{4{ymult_w8[25]}},ymult_w8};

assign feedback5 = {{4{ymult_w9[25]}},ymult_w9} + {{4{ymult_w10[25]}},ymult_w10};

assign feedback6 = feedback1 + feedback2;

assign feedback7 = feedback3 + feedback4;

assign feedback8 = feedback6 + feedback7;

assign feedback = feedback5 + feedback8;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//计算最后的输出

assign ysum = {{{feedforward[30]}},feedforward} - {{feedback[30]},feedback};//31bits

assign ydiv = {{10{ysum[30]}},ysum[30:10]};

assign yin = ydiv[ 13:0 ];

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//最后结果加一级寄存器,提高系统频率

always @(posedge clk)

yout <= ydiv[ 13:0 ];

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

endmodule

时间: 2024-10-24 22:20:29

iir调试记录的相关文章

Android KitKat 4.4 Wifi移植之AP模式与网络共享功能调试记录

Tethering技术在移动平台上已经运用的越来越广泛了,它可以把移动设备当做一个接入点,其它的设备可以通过Wi-Fi,USB或是Bluetooth等方式连接到此移动设备.在Android中可以将Wifi设为AP模式作为WLAN接入点,从而与其他设备共享Android的互联网连接.Android成为接入点后,就无法通过WLAN连接使用Android的应用程序访问互联网,但可以通过其他方式如以太网或移动网络访问互联网.此时以太网或移动网络在网络共享(Tethering)中是作为upstream的角

ORACLE 11G 触发器调试记录Error: PLS-00201: identifier&#39;SYS.DBMS_SYSTEM&#39; must be declared

1,触发器内容如下 CREATE OR REPLACE TRIGGER"LOGON_DENIED_TO_ALERT" AFTER servererror ON DATABASE DECLARE message   VARCHAR2(168); ip        VARCHAR2(15); v_os_user VARCHAR2(80); v_module  VARCHAR2(50); v_action  VARCHAR2(50); v_pid     VARCHAR2(10); v_s

【原】各种语言疑难BUG调试记录

之前遇到棘手的BUG总是在处理过后就不管了,导致后面碰到后重复工作太多.现专门开辟一篇日志以记录接下来一路上的DEBUG记录. [C++] 1.mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file 说明:由于VC需要把生成的文件中嵌入MANIFEST文件,而由于杀毒软件之类的会握有这个文件句柄(因为杀毒软件发现这个EXE,DLL正在读写),于是VC就写不进去了,方

上海机房阵列柜调试记录

1.vmare部分 vmotion http://qingping.blog.51cto.com/335806/404718/ storage vmotion http://qingping.blog.51cto.com/335806/396488 一些基本概念. vCenter的基本单位是DataCenter数据中心,一般以机房位置来划分,是vCenter的最高级的划分单位. Cluster:集群,多台ESXi服务器组成一个集群,可以提供高级功能,通常同一机房计算机会放入一个DataCente

stm32调试记录一

..\..\SYSTEM\usart\usart.c(1): error:  #5: cannot open source input file "sys.h": No such file or directory #include "..\sys\sys.h"这样就可以找到路径了 再次编译出现了问题 ..\..\SYSTEM\usart\..\sys\sys.h(3): error:  #5: cannot open source input file "

Video Test Pattern Generator(7.0)软件调试记录

Video Test Pattern Generator(7.0)软件调试记录 1 1. 2 XVidC_VideoMode 3 XVIDC_VM_576_50_I = XVIDC_VM_720x576_50_I 4 5 2. 6 typedef struct { 7 u16 HActive; 8 u16 HFrontPorch; 9 u16 HSyncWidth; 10 u16 HBackPorch; 11 u16 HTotal; 12 u8 HSyncPolarity; 13 u16 VAc

mysql 存储过程错误调试记录

 mysql存储过程错误调试记录 公司平台在mysql数据库上运行,一些存储过程报错,调试过程痛苦,记录错误及解决办法,供参考. 调试环境:dbForge Studio for MySQL 6.1版本,试用版: 1.BIZ_GET_ORGAN_BY_CONDITION 问题1:提示递归调用错误,递归次数太多:根据业务设置,最大255: [email protected]@max_sp_recursion_depth = 10; 常见如乱码造成导致条件失效,出现死循环: 问题2:变量的内容是乱

IOS真机调试记录

首先,登录到http://developer.apple.com/devcenter/ios/index.action,如果已经购买了iPhone Develop Program(iDP),登录进去后,页面右上角会看到如下图所示的页面: 点击第一项:iOS Provisioning Portal,然后会看到下面的页面: 点击进入Certificates,然后看到如下所示的页面: 点击图中的click here to download now,这会下载下来一个AppleWWDRCA.cer文件,这

Qualnet 调试记录

在Qualnet里添加了一个应用层协议,编译完全通过,但在运行时总是在63s内存读取错误.可以肯定是路由表更新处指针调用错误了.为了定位错误,最可靠的办法就是使用VS进行调试.但按照官方手册设置调试时,却出现了如下错误信息: 'qualnet.exe': Loaded 'C:\snt\qualnet\5.0\bin\qualnet.exe', Symbols loaded. 'qualnet.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll' 'qualne