设计一个2kHz采样,500Hz截止的15阶低通滤波器(h(n)长度为16),过渡带500~600Hz的FIR滤波器,量化位数为12bit,输入信号位宽也为12bit。
参考如何快速设计一个FIR滤波器(一)
参考如何快速设计一个FIR滤波器(二)
// An highlighted block
function b = lpf
fs = 2000;%采样频率
n = 15;%阶数
qm = 12;%量化位数
f = [500 600];
fc = [0 f(1)*2/fs f(1)*2/fs f(2)*2/fs f(2)*2/fs 1];%过渡带
mag = [1 1 0.2 0.2 0 0];%低通
b = fir2(n,fc,mag);
subplot(211);
freqz(b);
b_pm = round(b/max(abs(b))*(2^(qm-1) -1));%12量化
%生成系数写入文件
fid=fopen('E:\Work\IC\Modem\code\Chapter_4\FIR\coe.txt','w');
for i = 1: length(b_pm)
B_hex=dec2hex(b_pm(i)+(b_pm(i)<0)*2^qm,qm);
for j = 1:qm
%k = strcat(B_hex);
fprintf(fid,'%c',B_hex(j));
end
fprintf(fid,'\r\n');
end
fprintf(fid,';');
fclose(fid);
%画图
f_b = 20*log10(abs(fft(b)));%幅频响应
f_b = f_b-max(f_b); %归一化
f_b_pm = 20*log10(abs(fft(b_pm)));
f_b_pm = f_b_pm-max(f_b_pm);
x_f = 0:(fs/length(f_b)):fs/2;%正频率部分
f_b = f_b(1:length(x_f));
f_b_pm = f_b_pm(1:length(x_f));
subplot(212);
plot(x_f, f_b,'--',x_f, f_b_pm,'-')
xlabel('frequency(MHz)');ylabel('Magnitude(dB)');
legend('No quantitative','12 bits quantitative');
// An highlighted block
var foo = 'bar';
f1 = 200;
f2 = 800;
fs = 2000;
N = 12;
len = 2000;
t = 0:1/fs:(len - 1)/fs;
s1 = sin(2*pi*f1*t);
s2 = sin(2*pi*f2*t);
s = s1 + s2;
hn = lpf;
filter_s = filter(hn,1,s);
%求信号的幅频响应
m_s = 20*log10(abs(fft(s,1024)));
m_s = m_s - max(m_s);
%滤波后的幅频响应
m_filter_s = 20*log10(abs(fft(filter_s,1024)));
m_filter_s = m_filter_s - max(m_filter_s);
%滤波器本身的幅频响应
m_hn = 20*log10(abs(fft(hn,1024)));
m_hn = m_hn - max(m_hn);
%设置幅频响应的横坐标单位为Hz
x_f = 0:(fs/length(m_s)):fs/2;
%只显示正频率部分的幅频响应
m_s = m_s(1:length(x_f));
m_filter_s = m_filter_s(1:length(x_f));
m_hn = m_hn(1:length(x_f));
%绘制幅频响应曲线
subplot(211)
plot(x_f,m_s,'r-.',x_f,m_filter_s,'b-.',x_f,m_hn,'g-.');
xlabel('频率(Hz)');ylabel('幅度(dB)');title('Matlab仿真合成单频信号滤波前后的频谱');
legend('输入信号频谱','输出信号频谱','滤波器响应');
grid;
%绘制滤波前后的时域波形
%设置显示数据范围,设置横坐标单位s
subplot(212)
x_t = 0:1/fs:80/fs;
t_s=s(1:length(x_t));
t_filter_s=filter_s(1:length(x_t));
plot(x_t,t_s,'--',x_t,t_filter_s,'-');
xlabel('时间(s)');ylabel('幅度');title('FPGA仿真合成单频信号滤波前后的时域波形');
legend('输入信号波形','输出信号波形');
grid;
%对仿真产生的合成单频信号进行量化处理
s=s/max(abs(s)); %归一化处理
Q_s=round(s*(2^(N-1)-1));%12比特量化
%将生成的数据以二进制数据格式写入txt文件中
fid=fopen('E:\Work\IC\Modem\code\Chapter_4\FIR\testdata.txt','w');
for i=1:length(Q_s)
B_noise=dec2bin(Q_s(i)+(Q_s(i)<0)*2^N,N);
for j=1:N
if B_noise(j)=='1'
tb=1;
else
tb=0;
end
fprintf(fid,'%d',tb);
end
fprintf(fid,'\r\n');
end
fprintf(fid,';');
fclose(fid);
// An highlighted block
module fir #(
parameter iwidth = 12,
parameter owidth = 29 ,
parameter order = 16
)
(
input clk,
input rst,
input[iwidth :0] din,
output reg [owidth :0] dout
);
reg[iwidth -1 :0] X[0: order-1];
reg[iwidth :0] add_X[0: order-1];
wire [iwidth -1 :0] coe [0 :7];
assign coe[7] = 12'h7ff;
assign coe[6] = 12'h21e;
assign coe[5] = 12'heb2;
assign coe[4] = 12'hf88;
assign coe[3] = 12'h05a;
assign coe[2] = 12'h018;
assign coe[1] = 12'hff0;
assign coe[0] = 12'hffb;
reg [24: 0] sum[0:7];
reg[owidth -1 :0] sum1,sum2;
genvar i;
generate
for (i = 0; i < order; i = i + 1) begin:shift
always@ (posedge clk or negedge rst) begin
if (!rst)
X[i] <= 1'b0;
else if (i == 0) X[i] <= din;
else if (i > 0) X[i] <= X[i-1];
end
end
endgenerate
integer j;
always@(posedge clk or negedge rst) begin
if(!rst)
add_X[j] <= 13'b0;
else begin
for (j =0; j <8; j = j +1) begin
add_X[j] <= {{X[j][11]},X[j]} + {{X[15 - j][11]},X[15 -j]};
end
end
end
always@ (posedge clk or negedge rst) begin
if (!rst) begin
for (j = 0; j < 8; j = j + 1)
sum[j] <= 25'b0;
end
else begin
for (j =0; j <8; j = j +1) begin
sum[j] <= {{13{coe[j][11]}},coe[j]} * ({{12{add_X[j][12]}},add_X[j]});
end
end
end
always@ (posedge clk or negedge rst) begin
if (!rst) begin
sum2 <= 29'b0;
sum1 <= 29'b0;
dout <= 29'b0;
end
else begin
sum1 <= {{4{sum[0][24]}},sum[0]} + {{4{sum[1][24]}},sum[1]} + {{4{sum[2][24]}},sum[2]} + {{4{sum[3][24]}},sum[3]};
sum2 <= {{4{sum[4][24]}},sum[4]} + {{4{sum[5][24]}},sum[5]} + {{4{sum[6][24]}},sum[6]} + {{4{sum[7][24]}},sum[7]};
dout <= {{sum1[28]},sum1} + {{sum2[28]},sum2};
end
end
endmodule
`timescale 1ns/1ps
module test();
reg clk;
reg rst;
reg [11: 0] din;
wire[28: 0] dout;
fir #
(
.iwidth(12),
.owidth (29),
.order (16)
)
u1
( .clk(clk),
.rst(rst),
.din(din),
.dout(dout)
);
//rst
initial begin
rst = 1'b1;
#10 rst = 1'b0;
#20 rst = 1'b1;
#400000 $finish;
end
//clk
initial begin
clk = 1'b1;
forever #10 clk = ~clk;
end
reg [11: 0] mem [0:1999];
integer i;
initial begin
$readmemb("/home/IC/Mylearn/FIR/testdata.txt", mem);
i = 0;
repeat(1999) begin
i = i + 1;
din = mem[i];
#20;
end
end
initial begin
$fsdbDumpfile("fir.fsdb");
$fsdbDumpvars;
end
endmodule