1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > FPGA学习记录(12)<切比雪夫滤波器IIR的FPGA实现>

FPGA学习记录(12)<切比雪夫滤波器IIR的FPGA实现>

时间:2018-11-03 03:43:23

相关推荐

FPGA学习记录(12)<切比雪夫滤波器IIR的FPGA实现>

目录

基于切比雪夫滤波器&IIR高通滤波器的FPGA实现1、切比雪夫滤波器的设计参数2、根据IIR滤波器的系统函数,滤波器的差分方程表示3、根据这个系统函数的系数,编写对应的滤波器的Verilog代码

Written by @hzj//JinXing Project#.11.28 V1.0

基于切比雪夫滤波器&IIR高通滤波器的FPGA实现

之前实现过了IIR滤波器,但是发现有部分的地方的实现不好,有点小毛刺,因此重新设计一个IIR滤波器,一是对过去的滤波器的流程的回顾,另外一个是为了探讨新的设计方案,让整个滤波器的设计更为简单。

1、切比雪夫滤波器的设计参数

还是像以前博文所讲述的那样,设计一个滤波器,参数如下所示:

采样频率:fsample=5000Hz采样频率:f_{sample} = 5000Hz采样频率:fsample​=5000Hz

截止频率:fstop=1000Hz截止频率:f_{stop} = 1000Hz截止频率:fstop​=1000Hz

衰减:ffalling=60dB衰减:f_{falling} = 60dB衰减:ffalling​=60dB

滤波器的阶数:numfilter=7滤波器的阶数:num_{filter}=7滤波器的阶数:numfilter​=7

通过cheby2cheby2cheby2参数进行实现,输入参数使用切比雪夫滤波器实现,对应构建的matlab代码如下所示:

clear ;clc;f_sample = 5000;%采样频率f_stop = 1000;%截止频率f_falling = 60;%db衰减num_filter = 7;%设置滤波器阶数%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%量化处理模块[Num, Den] = cheby2(7, f_falling, f_stop*2/f_sample, "low");max_den_num = max(max(abs(Num), abs(Den)));mid_compute = log2(max_den_num/Den(1));Number = floor(mid_compute);if Number < log2(max_den_num/Den(1))Number = Number + 1;endNumber = 2^Number;Q_den = round(Den/Number * (2^15-1));Q_num = round(Num/Number * (2^15-1));%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%fprintf("Num = \n")for i = 1:1:(num_filter+1)fprintf("\t %f",Num(i));endfprintf("\n");fprintf("Den = \n")for i = 1:1:(num_filter+1)fprintf("\t %f",Den(i));endfprintf("\n");fprintf("Q_num = \n")for i = 1:1:(num_filter+1)fprintf("\t %f",Q_num(i));endfprintf("\n");fprintf("Q_den = \n")for i = 1:1:(num_filter+1)fprintf("\t %f",Q_den(i));endfprintf("\n");

命令行中的得到的结果如下所示:

Num = 0.007046 0.008669 0.018551 0.020733 0.020733 0.018551 0.008669 0.007046Den = 1.000000 -3.027243 4.574142 -4.104494 2.348938 -0.839118 0.173509 -0.015738Q_num = 29.000000 36.000000 76.000000 85.000000 85.000000 76.000000 36.000000 29.000000Q_den = 4096.000000 -12399.000000 18735.000000 -16811.000000 9621.000000 -3437.000000 711.000000 -64.000000>>

2、根据IIR滤波器的系统函数,滤波器的差分方程表示

由于有如下的系数:

Q_num = 29 36 76 85 85 76 36 29Q_den = 4096-12399 18735 -16811 9621 -3437 711 -64>>

对应的差分方程展示如下所示:

4096y(n)=29∗[x(n)+x(n−7)]+36∗[x(n−1)+x(n−6)]+76∗[x(n−2)+x(n−5)]+85∗[x(n−3)+x(n−4)]−[−12399∗y(n−1)+18735∗y(n−2)−16811∗y(n−3)+9621∗y(n−4)−3437∗y(n−5)+711∗y(n−6)−64∗y(n−7)]4096y(n)=29*[x(n)+x(n-7)]+36*[x(n-1)+x(n-6)]+76*[x(n-2)+x(n-5)]+85*[x(n-3)+x(n-4)] - [-12399*y(n-1)+18735*y(n-2)-16811*y(n-3)+9621*y(n-4)-3437*y(n-5)+711*y(n-6)-64*y(n-7)]4096y(n)=29∗[x(n)+x(n−7)]+36∗[x(n−1)+x(n−6)]+76∗[x(n−2)+x(n−5)]+85∗[x(n−3)+x(n−4)]−[−12399∗y(n−1)+18735∗y(n−2)−16811∗y(n−3)+9621∗y(n−4)−3437∗y(n−5)+711∗y(n−6)−64∗y(n−7)]

因此FPGA对应的实现方式是,先将式子分为一个零点一个极点模块进行实现,然后进行一次运算之后,进行相减,再除以4096,这个地方故意设置成为是2的阶数,为的是将除法的操作变得更加简单,直接通过移位的操作,就可以实现除法,这样能够减少FPGA内部的器件的使用。这个观念对于以后的滤波器的设置,也相当重要。

3、根据这个系统函数的系数,编写对应的滤波器的Verilog代码

顶层模块,包括一个零点模块的调用,一个极点模块的调用,一个零点模块以及极点模块的相差最终输出的的差值sub进行一个除法,除法的大小已经由前期的设计所决定,大小为4096, 由于输出的值的大小与输入值的位数大小应该是相同的,所以这个地方进行除法之后,输出的数据位数应该也是为16位,因此,最后一步进行一个截取。

`timescale 1ns/1ps//-------------------------------------------------------// IIR滤波器顶层模块//-------------------------------------------------------module IIR_top(input clk ,input rst_n,input signed [15:0] IIR_input ,output reg signed [15:0] IIR_output);parameter U_DLY = 1;//时序仿真信号,加上U_DLY模拟信号的电路中传输的延迟//-------------------------------------------------------// 调用零点模块//-------------------------------------------------------wire signed [25:0] zero_out ;wire signed [15:0] pole_in ;wire signed [32:0] feedback ;wire signed [17:0] pole_div ;//-------------------------------------------------------// 根据时钟信号,来控制波形的输入值wave_in;//-------------------------------------------------------always@(posedge clk or negedge rst_n)if(rst_n == 1'b0)beginIIR_output <= #U_DLY 12'b0; //复位信号,下降沿有效endelse beginIIR_output <= #U_DLY pole_in; //正常周期信号clk状态下依次进行输入波形数据endzero_module zero(.rst_n (rst_n) ,.clk (clk) ,.zero_input (IIR_input) ,.zero_output(zero_out));//-------------------------------------------------------// 调用极点模块//-------------------------------------------------------pole_module pole(.clk (clk) ,.rst_n (rst_n) ,.pole_input (pole_in) ,.pole_output(feedback) );//-------------------------------------------------------// 顶层模块进行求差值以及乘积的工作,构成IIR模块//-------------------------------------------------------wire signed [32:0] sub_module;assign sub_module = {{{7{zero_out[25]}}, zero_out} - feedback};//零点的输出与极点的输出进行相减,21位assign pole_div = {sub_module[32:12]} ;//求出的差值进行移位除法assign pole_in = pole_div[15:0];endmodule

零点模块,这个模块相当于一个FIR滤波器,并通过其对称性,可以进行加法寄存器进行对称相加,然后分别乘以29、36、76、85。

`timescale 1ns/1ps//-------------------------------------------------------// IIR滤波器零点系数模块//-------------------------------------------------------//-------------------------------------------------------// 引脚模块定义//-------------------------------------------------------module zero_module(input clk, //时钟信号clkinput rst_n , //定义一个复位信号,复位信号按照下降沿有效input signed [15:0] zero_input , //零点模块的输入output signed [25:0] zero_output //零点模块的输出);parameter U_DLY = 1;//时序仿真信号,加上U_DLY模拟信号的电路中传输的延迟//-------------------------------------------------------// IIR滤波器中进行移位的部分,按照clk时钟周期,依次输入波// IIR形数据,同时也应该在rst_n为1'b0的时候进行置零//-------------------------------------------------------reg signed [15:0] data_reg [6:0];always@(posedge clk or negedge rst_n) beginif(rst_n == 1'b0) begin//复位信号,系统进行置零操作,复位信号低电平有效data_reg[0] <= #U_DLY 12'b0 ;data_reg[1] <= #U_DLY 12'b0 ;data_reg[2] <= #U_DLY 12'b0 ;data_reg[3] <= #U_DLY 12'b0 ;data_reg[4] <= #U_DLY 12'b0 ;data_reg[5] <= #U_DLY 12'b0 ;data_reg[6] <= #U_DLY 12'b0 ;endelse begin //普通时钟周期信号,依次进行移位操作,将新的数据进行送入data_reg[6] <= #U_DLY data_reg[5] ;data_reg[5] <= #U_DLY data_reg[4] ; data_reg[4] <= #U_DLY data_reg[3] ;data_reg[3] <= #U_DLY data_reg[2] ;data_reg[2] <= #U_DLY data_reg[1] ;data_reg[1] <= #U_DLY data_reg[0] ;data_reg[0] <= #U_DLY zero_input ;endend//-------------------------------------------------------// IIR滤波器的零点由于系数都是对称的,因此可以通过这样子减// 少器件,先进行加法运算//-------------------------------------------------------wire signed [16:0] add_reg [3:0];assign add_reg[0] = {zero_input[15], zero_input} + {data_reg[6][15], data_reg[6]} ;assign add_reg[1] = {data_reg[0][15], data_reg[0]} + {data_reg[5][15], data_reg[5]} ;assign add_reg[2] = {data_reg[1][15], data_reg[1]} + {data_reg[4][15], data_reg[4]} ;assign add_reg[3] = {data_reg[2][15], data_reg[2]} + {data_reg[3][15], data_reg[3]} ;//-------------------------------------------------------// IIR滤波器使用已经加好的数进行卷积//-------------------------------------------------------wire signed [24:0] mult_reg [3:0];assign mult_reg[0] = {{{8{add_reg[0][16]}}, add_reg[0]}+ {{6{add_reg[0][16]}}, add_reg[0], 2'b0}+ {{5{add_reg[0][16]}}, add_reg[0], 3'b0} + {{4{add_reg[0][16]}}, add_reg[0], 4'b0}} ;//*29_1 1101assign mult_reg[1] = {{{6{add_reg[1][16]}}, add_reg[1], 2'b0} + {{3{add_reg[1][16]}}, add_reg[1], 5'b0}} ;//*36_10 0100assign mult_reg[2] = {{{6{add_reg[2][16]}}, add_reg[2], 2'b0} + {{5{add_reg[2][16]}}, add_reg[2], 3'b0} + {{2{add_reg[2][16]}}, add_reg[2], 6'b0}} ;//*76_100 1100assign mult_reg[3] = {{{8{add_reg[3][16]}}, add_reg[3]} + {{6{add_reg[3][16]}}, add_reg[3], 2'b0} + {{4{add_reg[3][16]}}, add_reg[3], 4'b0} + {{2{add_reg[3][16]}}, add_reg[3], 6'b0}} ;//*85_101 0101//-------------------------------------------------------// 卷积运算之后进行求和输出//-------------------------------------------------------assign zero_output = {mult_reg[0][24], mult_reg[0]}+ {mult_reg[1][24], mult_reg[1]}+ {mult_reg[2][24], mult_reg[2]}+ {mult_reg[3][24], mult_reg[3]};endmodule

极点模块,极点模块的输入是整个模型的输出作为其输入,依次乘以-12399、18735、-16811、9621、-3437、711、-64。

`timescale 1ns/1ps//-------------------------------------------------------// IIR滤波器极点系数模块//-------------------------------------------------------module pole_module(input clk,//时钟信号input rst_n ,//复位信号,使能高电平有效input signed [15:0] pole_input,//输入信号output signed [32:0] pole_output//输出信号);parameter U_DLY = 1;//时序仿真信号,加上U_DLY模拟信号的电路中传输的延迟//-------------------------------------------------------// 还是pole模块由于是N-1位,因此这个地方我们只需要8-1个寄存器进行存储// 因此该处定义的是7位的reg信号,信号的带宽与输入的带宽相同,也就是即// 16位。复位信号清零;clk信号进行移位;//-------------------------------------------------------reg signed [15:0] data_reg [6:0];always@(posedge clk or negedge rst_n)if(rst_n == 1'b0) begin //复位信号,系统进行置零操作,复位信号低电平有效data_reg[0] <= #U_DLY 12'd0 ;data_reg[1] <= #U_DLY 12'd0 ;data_reg[2] <= #U_DLY 12'd0 ;data_reg[3] <= #U_DLY 12'd0 ;data_reg[4] <= #U_DLY 12'd0 ;data_reg[5] <= #U_DLY 12'd0 ;data_reg[6] <= #U_DLY 12'd0 ;end else begin //普通时钟周期信号,依次进行移位操作,将新的数据进行送入data_reg[6] <= #U_DLY data_reg[5] ;data_reg[5] <= #U_DLY data_reg[4] ;data_reg[4] <= #U_DLY data_reg[3] ;data_reg[3] <= #U_DLY data_reg[2] ;data_reg[2] <= #U_DLY data_reg[1] ;data_reg[1] <= #U_DLY data_reg[0] ;data_reg[0] <= #U_DLY pole_input ; end//-------------------------------------------------------// 滤波器的系数,量化之后,量化2^6// 使用组合逻辑进行乘法的操作。//-------------------------------------------------------wire [31:0] mult_pole [6:0];wire [31:0] reg_1;wire [31:0] reg_2;wire [31:0] reg_3;wire [31:0] reg_4;assign reg_1 = {{{16{data_reg[0][15]}}, data_reg[0]} + {{15{data_reg[0][15]}}, data_reg[0], 1'b0} + {{14{data_reg[0][15]}}, data_reg[0], 2'b0} + {{13{data_reg[0][15]}}, data_reg[0], 3'b0} + {{11{data_reg[0][15]}}, data_reg[0], 5'b0} + {{10{data_reg[0][15]}}, data_reg[0], 6'b0} + {{4{data_reg[0][15]}}, data_reg[0], 12'b0} + {{3{data_reg[0][15]}}, data_reg[0], 13'b0}};//*-12399_11 0000 0110 1111assign mult_pole[0] = ~reg_1 + 1'b1;assign mult_pole[1] = {{{16{data_reg[1][15]}}, data_reg[1]} + {{15{data_reg[1][15]}}, data_reg[1], 1'b0} + {{14{data_reg[1][15]}}, data_reg[1], 2'b0} + {{13{data_reg[1][15]}}, data_reg[1], 3'b0} + {{11{data_reg[1][15]}}, data_reg[1], 5'b0} + {{8{data_reg[1][15]}}, data_reg[1], 8'b0} + {{5{data_reg[1][15]}}, data_reg[1], 11'b0} + {{2{data_reg[1][15]}}, data_reg[1], 14'b0}};//*18735_100 1001 0010 1111assign reg_2 = {{{16{data_reg[2][15]}}, data_reg[2]} + {{15{data_reg[2][15]}}, data_reg[2], 1'b0} + {{13{data_reg[2][15]}}, data_reg[2], 3'b0} + {{11{data_reg[2][15]}}, data_reg[2], 5'b0} + {{9{data_reg[2][15]}}, data_reg[2], 7'b0} + {{8{data_reg[2][15]}}, data_reg[2], 8'b0} + {{2{data_reg[2][15]}}, data_reg[2], 14'b0}};//*-16811_100 0001 1010 1011assign mult_pole[2] = ~reg_2 + 1'b1;assign mult_pole[3] = {{{16{data_reg[3][15]}}, data_reg[3]} + {{14{data_reg[3][15]}}, data_reg[3], 2'b0} + {{12{data_reg[3][15]}}, data_reg[3], 4'b0} + {{9{data_reg[3][15]}}, data_reg[3], 7'b0} + {{8{data_reg[3][15]}}, data_reg[3], 8'b0} + {{6{data_reg[3][15]}}, data_reg[3], 10'b0} + {{3{data_reg[3][15]}}, data_reg[3], 13'b0}};//*9621_10 0101 1001 0101assign reg_3 = {{{16{data_reg[4][15]}}, data_reg[4]} + {{14{data_reg[4][15]}}, data_reg[4], 2'b0} + {{13{data_reg[4][15]}}, data_reg[4], 3'b0}+ {{11{data_reg[4][15]}}, data_reg[4], 5'b0}+ {{10{data_reg[4][15]}}, data_reg[4], 6'b0}+ {{8{data_reg[4][15]}}, data_reg[4], 8'b0}+ {{6{data_reg[4][15]}}, data_reg[4], 10'b0}+ {{5{data_reg[4][15]}}, data_reg[4], 11'b0}};//*-3437_1101 0110 1101assign mult_pole[4] = ~reg_3 + 1'b1;assign mult_pole[5] = {{{16{data_reg[5][15]}}, data_reg[5]} + {{15{data_reg[5][15]}}, data_reg[5], 1'b0}+ {{14{data_reg[5][15]}}, data_reg[5], 2'b0}+ {{10{data_reg[5][15]}}, data_reg[5], 6'b0}+ {{9{data_reg[5][15]}}, data_reg[5], 7'b0}+ {{7{data_reg[5][15]}}, data_reg[5], 9'b0}};//*711_10 1100 0111assign reg_4 = {{{10{data_reg[6][15]}}, data_reg[6], 6'b0}};//*-64_100 0000assign mult_pole[6] = ~reg_4 + 1'b1;//-------------------------------------------------------// 求卷积和;将前面所有的乘积进行求和,并且输出置Yout// 将前面7个已经完成乘法的寄存器中的数据进行加法运算//-------------------------------------------------------assign pole_output = {mult_pole[0] + mult_pole[1] + mult_pole[2] + mult_pole[3] + mult_pole[4] + mult_pole[5] + mult_pole[6] };endmodule

测试模块、tb文件代码如下:

//~ `New testbench`timescale 1ns / 1psmodule tb_IIR_top;// IIR_top Parametersparameter PERIOD = 10;// IIR_top Inputsreg clk ;reg rst_n ;reg [15:0] wave_in ;// IIR_top Outputswire [15:0] wave_out;integer i ;initial beginclk = 0;rst_n= 0;wave_in = 12'd0;i= 0;endinitialbeginforever #(PERIOD/2) clk=~clk;endinitialbegin#(PERIOD*2) rst_n = 1;endparameter DATA_NUM = 32'd1000000;reg [15:0] data_men[DATA_NUM:1];initial begin$readmemb("C:/Users/64441/Desktop/Verilog_IIR_Butterworth/tb/sin.txt",data_men); //注意斜杠的方向,不能反<<<<<<<endalways @(posedge clk or negedge rst_n) begin //每1个clk_sig信号来临后,进行一次数据输入,将新的一个波形数据输入Din中。wave_in <= data_men[i]; i <= i+1;endIIR_top u_IIR_top (.clk ( clk ),.rst_n ( rst_n ),.IIR_input( wave_in [15:0] ),.IIR_output ( wave_out [15:0] ));integer w_file;initial w_file = $fopen("C:/Users/64441/Desktop/Verilog_IIR_Butterworth/tb/simulation_after_IIR.txt");always @(i)begin$fdisplay(w_file,"%b",wave_out);end endmodule

为了验证此滤波器的功能,因此需要仿真一个源波形信号,源波形信号是由一个波形频率大小为500Hz以及一个2000Hz的波形进行合成,采样的频率大小为5000Hz。输出的位数大小为16位的数据。

f1 = 500;f2 = 2000;Fs = 5000;N = 16;End = 200;t = 0:1/Fs:End-1/Fs;c1 = 2*pi*f1*t;c2 = 2*pi*f2*t;s1 = sin(c1);s2 = 0.5*sin(c2);s = s1+s2;s = s/max(abs(s));Q_s = round(s*(2^(N-1) - 1));fid = fopen('..\tb\sin_ten.txt','w');fprintf(fid, '%12d\r\n',Q_s);fprintf(fid, ';');fclose(fid);fid = fopen('..\tb\sin.txt','w');for k=1:length(Q_s)%二进制变换B_s=dec2bin(Q_s(k)+((Q_s(k))<0)*2^N,N);for j=1:Nif B_s(j)=='1'tb=1;elsetb=0;endfprintf(fid,'%d',tb);endfprintf(fid,'\r\n');endfprintf(fid,';');fclose(fid);fid = fopen('..\tb\sin.txt','w');for k=1:length(Q_s)%二进制变换B_s=dec2bin(Q_s(k)+((Q_s(k))<0)*2^N,N);for j=1:Nif B_s(j)=='1'tb=1;elsetb=0;endfprintf(fid,'%d',tb);endfprintf(fid,'\r\n');endfprintf(fid,';');fclose(fid);

采用上述的代码进行仿真,输入模拟输入的波形,仿真之后的结果如下所示:

从上述的图像可以看出,wave_in代表的是输入波形的信号,wave_out代表的是输出波形的信号。可以看出,整个滤波的效果还是很明显的,当时这个不能验证我们的滤波功能,需要和实际的matalb仿真数据进行compare比对。因此,对应编写的IIR切比雪夫实现方式代码如下所示:

%将二进制转化为十进制的数据,所有的数据都是从sin.txt原始文件中导出%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%str_in = importdata('..\tb\sin.txt');str_length = length(str_in); str_out = zeros(str_length, 1);MAX_DATA = 2^15-1;for number = 1 : str_lengthstr_out(number) = bin2dec( num2str(str_in(number)) );if(str_out(number) > MAX_DATA)str_out(number) = bin2dec( num2str(str_in(number)) ) - 2^16;endend%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%设置IIR滤波器的卷积系数(一般设置的大小为8位)zero_1 = 29;zero_2 = 36;zero_3 = 76;zero_4 = 85;pole_1 = -12399;pole_2 = 18735;pole_3 = -16811;pole_4 = 9621;pole_5 = -3437;pole_6 = 711;pole_7 = -64;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%x_in= str_out;pole_out = 0;%定义每一个变量的初值,按照电路中复位的原则,所有的卷积器中的变量,都给予初值%初值的大小设置位为0x_in_2 = 0;x_in_3 = 0;x_in_4 = 0;x_in_5 = 0;x_in_6 = 0;x_in_7 = 0;x_in_8 = 0;div = 0;x_in_7_pole = 0;x_in_6_pole = 0;x_in_5_pole = 0;x_in_4_pole = 0; x_in_3_pole = 0;x_in_2_pole = 0; x_in_1_pole = 0;add_reg_1 = 0;add_reg_2 = 0;add_reg_3 = 0;add_reg_4 = 0;%定义一个矩阵数组,用来存放我们的输出值output = zeros(1, str_length);%定义一个二进制数组存储单元binary_tem = zeros(1, 16);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%for i=1:1:str_length%进行第一次卷积操作,第一次卷积操作是进行零点运算%卷积操作,将原来的寄存器中的数据进行卷积,卷积后的数据放入到y中。add_reg_1 = x_in(i) + x_in_8;add_reg_2 = x_in_2 + x_in_7;add_reg_3 = x_in_3 + x_in_6;add_reg_4 = x_in_4 + x_in_5;%y = x_in(i) * zero_1 + x_in_2 * zero_2 + x_in_3 * zero_3 + x_in_4 * zero_4 + x_in_5 * zero_4 + x_in_6 * zero_3 + x_in_7 * zero_2 + x_in_8 * zero_1;y = add_reg_1 * zero_1 + add_reg_2 * zero_2 + add_reg_3 * zero_3 + add_reg_4 * zero_4;%依次进行数据的搬移工作x_in_8 = x_in_7;x_in_7 = x_in_6;x_in_6 = x_in_5;x_in_5 = x_in_4;x_in_4 = x_in_3; x_in_3 = x_in_2;x_in_2 = x_in(i);%依次进行数据的搬移工作x_in_7_pole = x_in_6_pole;x_in_6_pole = x_in_5_pole;x_in_5_pole = x_in_4_pole;x_in_4_pole = x_in_3_pole; x_in_3_pole = x_in_2_pole;x_in_2_pole = x_in_1_pole;x_in_1_pole = div;%进行第二次卷积操作,第二次卷积操作是进行极点运算%卷积操作,将卷积后的值运算得出,放在pole中pole = x_in_1_pole * pole_1 + x_in_2_pole * pole_2 + x_in_3_pole * pole_3 + x_in_4_pole * pole_4 + x_in_5_pole * pole_5 + x_in_6_pole * pole_6 + x_in_7_pole * pole_7;%pole = x_in_1_pole * div + x_in_2_pole * pole_1 + x_in_3_pole * pole_2 + x_in_4_pole * pole_3 + x_in_5_pole * pole_4 + x_in_6_pole * pole_5 + x_in_7_pole * pole_6;%进行数据的相减,相当于零点的运算值与极点的运算值进行相差sub = y - pole;%相当于数据的截位运算,由于需要进行截位除法,因此,模拟一次数据的截位操作,原来的21位的数据,最终只需要得到12位的值%因此,只需要读取前十二位的数据,便相当于对后9位的数据进行一个截取B_s=dec2bin(sub+(sub<0)*2^33,33);for j=1:21if B_s(j)=='1'binary_tem(1, j) = 1;elsebinary_tem(1, j) = 0;endendif(binary_tem(1, 6) == 0)div = binary_tem(1, 6) * 32768 + binary_tem(1, 7) * 16384 + binary_tem(1, 8) * 8192 + binary_tem(1, 9) * 4096 + binary_tem(1, 10) * 2048 + binary_tem(1, 11) * 1024 + binary_tem(1, 12) * 512 + binary_tem(1, 13) * 256 + binary_tem(1, 14) * 128 + binary_tem(1, 15) * 64 + binary_tem(1, 16) * 32 + binary_tem(1, 17) * 16 + binary_tem(1, 18) * 8 + binary_tem(1, 19) * 4 + binary_tem(1, 20) * 2 + binary_tem(1, 21) * 1;elsediv = ~(binary_tem(1, 6)) * 32768 + ~(binary_tem(1, 7)) * 16384 + ~(binary_tem(1, 8)) * 8192 + ~(binary_tem(1, 9)) * 4096 + ~(binary_tem(1, 10)) * 2048 + ~(binary_tem(1, 11)) * 1024 + ~(binary_tem(1, 12)) * 512 + ~(binary_tem(1, 13)) * 256 + ~(binary_tem(1, 14)) * 128 + ~(binary_tem(1, 15)) * 64 + ~(binary_tem(1, 16)) * 32 + ~(binary_tem(1, 17)) * 16 + ~(binary_tem(1, 18)) * 8 + ~(binary_tem(1, 19)) * 4 + ~(binary_tem(1, 20)) * 2 + ~(binary_tem(1, 21)) * 1;div = div + 1;div = -div;end%获得div截位之后的值,得到的结果放入输出矩阵output(1, i)中去output(1, i) = div;end%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%波形数据的数据的写入,将截位之后的数据,也就是即输出的滤波波形数据进行输出fid = fopen('..\tb\simulation_MATLAB_IIR.txt','w');for k=1:length(output)B_s=dec2bin(output(k)+((output(k))<0)*2^16,16);for j=1:16if B_s(j)=='1'tb=1;elsetb=0;endfprintf(fid,'%d',tb);end fprintf(fid,'\r\n');endfprintf(fid,';');fclose(fid);

将两者输出的值进行比对,使用的Beyond Compare工具,两者的比对之后的结果如下所示:

可以看出,中间的100W的数据相同,因此数据是一样的,可以认为,这里已经实现了整个滤波的操作。

*tips:这个地方的MATLAB仿真看似不重要,其实是很重要的。因为这个仿真比对,可以发现很多问题,然后通过这个地方出现的问题,重新在波形里面进行逻辑推导,从而找出代码上的错误。本文在进行书写代码的过程中,其实也遇到了很多问题,比如乘法运算的时候,zero模块的最高位为16,而非15,但是笔者在书写的时候写成了15,但是这个错误在直接看滤波后的效果时又是有滤波效果的,因此很难发现这个问题,而在后面的比对过程中,才逐渐从逻辑数据的推导中才发现了这个问题,改正后便比对正常。

总结一下这次重新实现的收获:

1、采用了不使用FDA模块来进行模拟仿真IIR滤波器的方法。

2、明白了pole极点模块输出前进行除法的原由,同时实现了一种不使用耗费资源贼大情况下的除法(也就是移位除法),直接使用位移的工作,就实现了整个除法工作。

3、进一步明确了定点定位的方法,也就是加法的时候拓展一位,另外乘法的话是拓展a+b位。

4、明确了matlab比对数据的重要性。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。