开发环境
MATLAB:2020.2b
Vivado:2024.2
FPGA:XC7A200TFBG484-2L
滤波参数
采样率:1MHz
FIR时钟频率:100MHz
滤波器阶数:21
滤波器参数:
- 采样频率:1MHz
- 通带频率:50KHz
- 阻带频率:200KHz
- 通带波纹:0.1dB
- 阻带波纹:80dB
- 滤波器系数量化位数:12;最佳精度小数长度:13
- ADC量化位数:12.满幅输入
输入:Q1.11
增益:Q1.13
输出:Q2.24 截取24:13 得到Q1.11
MATLAB FDATOOL


注意这里要勾选最佳小数精度长度。分子小数长度13,代表FPGA中量化后的实际小数位宽。最后截取结果需要依据此长度
点击应用后,点击目标,导出Xilinx系数(COE文件)
FIR Compiler





测试代码
cpp
module fir_test(
input logic clk,
input logic rstn,
input logic adc1_data_valid,
input logic [11 : 0] adc1_data
);
wire s_axis_data_tvalid = adc1_data_valid;
wire s_axis_data_tready;
wire [15 : 0] s_axis_data_tdata = {{4{adc1_data[11]}}, adc1_data};
wire m_axis_data_tvalid;
wire [31 : 0] m_axis_data_tdata;
wire signed [11 : 0] filt_res = m_axis_data_tdata[24 : 13];
quad_phase_detect_lpf_test I_mult_lpf (
.aclk(clk), // input wire aclk
.aresetn(rstn),
.s_axis_data_tvalid(s_axis_data_tvalid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tdata(s_axis_data_tdata), // input wire [31 : 0] s_axis_data_tdata
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata) // output wire [31 : 0] m_axis_data_tdata
);
endmodule
cpp
`timescale 1ns / 1ps
module tb_fir_test;
// fir_test Parameters
parameter PERIOD = 10; // 100M
parameter ADC_PERIOD = 1000; // 300K
parameter fir_clk_PERIOD = 1000; // 1M
// fir_test Inputs
reg clk = 0 ;
reg fir_clk = 0 ;
reg rstn = 0 ;
reg adc1_data_valid = 0 ;
reg [11 : 0] adc1_data = 0 ;
reg adc_clk = 0 ;
reg adc_clk_d;
wire [13 : 0] dds_data_i; // I路输出 (原波形,0°)
wire signed [13 : 0] s_dds_data = {1 - dds_data_i[13], dds_data_i[12 : 0]};
wire [13 : 0] dds_data_q; // Q路输出 (正交波形,90°)
// fir_test Outputs
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial begin
forever #(ADC_PERIOD/2) adc_clk=~adc_clk;
end
initial begin
forever #(fir_clk_PERIOD/2) fir_clk = ~fir_clk;
end
initial
begin
#(PERIOD*2) rstn = 1;
end
always_ff @(posedge clk) begin
if (!rstn)
adc_clk_d <= 1'b0;
else
adc_clk_d <= adc_clk;
end
always_comb begin
adc1_data_valid = {adc_clk_d, adc_clk} == 2'b01;
end
fir_test u_fir_test (
.clk ( clk ),
.rstn ( rstn ),
.adc1_data_valid ( adc1_data_valid ),
.adc1_data ( s_dds_data[13 : 2] )
);
dds_ctrl u_dds_ctrl(
.clk ( clk ),
.rstn ( rstn ),
.sync_run ( 1 ),
.wave_sel ( 'd0 ),
.freq_word ( 64'd9223372036854776 ),
.phase_word ( 'd0 ),
.amp_word ( 'd65535 ),
.duty_word ( 'd0 ),
.ena ( 1 ),
.enb ( 1 ),
.dds_data_i ( dds_data_i ),
.dds_data_q ( dds_data_q )
);
endmodule
仿真结果
满幅度输入,截位后的输出恰好也只有一位符号位。最大值为2021≈2042*10^(-0.0838854/20)。
0.0838854是fdatool中50KHz出的增益。2021为输出最大值,2042为输入最大值。可以看到通道单位增益输出,与matlab保持一致