本帖最后由 cyy13623649348 于 2019-9-3 12:12 编辑
1.FIR滤波器的原理与MATLAB设计
可以参考之前的串行FIR设计串行结构FIR滤波器设计
2.并行FIR滤波器设计与仿真验证
(1)原理框图设计
根据FIR直接型结构,滤波器是一个乘累加运算,乘累加的次数由滤波器的阶数决定。可以先设计出并行FIR的框图。
图1 并行FIR滤波器原理图 (2)程序设计 FIR滤波器接口设计: - module Fir_filter(
- rst_n,
- clk,
- Signal_in,
- Signal_out
- );
- input rst_n;
- input clk; //采样时钟
- input [11:0]Signal_in; //采样数据输入
- output [28:0]Signal_out; //滤波输出
-
- wire signed [11:0]Signed_in; //输入数据转换成有符号数
- assign Signed_in = Signal_in;
复制代码 将输入的数据缓存并对应相加: - /*----------------移位寄存器,用来存储采样数据----------------*/
- reg signed [11:0]In_reg[15:0];
- reg [3:0]i,j;
- always@(posedge clk or negedge rst_n)
- if(!rst_n)begin
- for(i=4'd0;i<15;i=i+1'b1)
- In_reg[i] = 12'd0;
- end
- else begin
- for(j=4'd0;j<15;j=j+1'b1)
- In_reg[j+1] <= In_reg[j];
- In_reg[0] <= Signed_in;
- end
- /*----------------将对称系数的输入数据相加----------------*/
- reg signed [12:0]Add_reg[7:0]; //为避免溢出,将两数相加的和扩展一位
- // reg [3:0]k,l;
- always@(posedge clk or negedge rst_n)
- if(!rst_n)begin
- for(i=4'd0;i<8;i=i+1'b1)
- Add_reg[i] = 13'd0;
- end
- else begin
- for(i=4'd0;i<8;i=i+1'b1)
- Add_reg[i] = {In_reg[i][11],In_reg[i]} + {In_reg[15-i][11],In_reg[15-i]};
- //要扩展一位符号位,使三个数长度相同,但其值不变
- end
复制代码 调用IP核进行乘法运算,并行执行需要8个乘法器: - /*----------------例化有符号数乘法器----------------*/
- wire signed [24:0]Mout[7:0];
- mult mult0 (
- .clock (clk),
- .dataa (coe0),
- .datab (Add_reg[0]),
- .result (Mout[0])
- );
复制代码 最后将乘法器的输出相加: - /*----------------将乘法结果累加----------------*/
- reg signed [28:0]sum;
- reg signed [28:0]yout;
- reg [3:0]m;
- always@(posedge clk or negedge rst_n)
- if(!rst_n)begin
- sum = 29'd0;
- yout <= 29'd0;
- end
- else begin
- yout <= sum;
- sum = 29'd0;
- for(m=4'd0;m<8;m=m+1'b1)
- sum = sum + Mout[m];
- end
复制代码(3)仿真验证 在串行FIR设计时通过加入混频来验证滤波正确性。也可以直接例化两个DDS,将其结果相加输入滤波器。这里我通过在仿真文件中读取TXT的方式来仿真。 首先使用MATLAB产生波形,并存入TXT文件。MATLAB代码参考下面。 在仿真文件中读取TXT文件中的数据,文件必须放置在"工程目录\simulation\modelsim"路径下。 - //从外部TXT文件(SinIn.txt)读入数据作为测试激励
- integer Pattern;
- reg [11:0] stimulus[200:0];
- initial
- begin
- //文件必须放置在"工程目录\simulation\modelsim"路径下
- $readmemb("E4_7_Bin_s.txt",stimulus);//读取原始波形数据读到stimulus中
- Pattern = 0;
- repeat(200)begin
- Pattern = Pattern + 1;
- Signal_in = stimulus[Pattern];
- #(`Clk_Period*1);
- end
- end
复制代码 然后将仿真数据写入另一个TXT文件,便于MATLAB对其数据进行分析。- //将仿真数据dout写入外部TXT文件中(out.txt)
- integer file_out;
- initial
- begin
- //文件放置在"工程目录\simulation\modelsim"路径下
- file_out = $fopen("E4_7_Sout.txt");
- if(!file_out)
- begin
- $display("could not open file!");
- $finish;
- end
- end
- wire clk_write;
- wire signed [28:0] dout_s;
- assign dout_s = Signal_out; //将dout转换成有符号数据
- assign clk_write = clk & rst_n;//产生写入时钟信号,复位状态时不写入数据
- always @(posedge clk_write)
- $fdisplay(file_out,"%d",dout_s);
复制代码 下面是仿真结果: 最后使用MATLAB读取滤波器输出的数据,得到频谱。MATLAB程序在附件。 |