FIR filter coefficient overload

Keywords: Verilog FPGA

1, Implementation method:

  1. Multiple groups of coefficients are placed in the coe file at one time, and then the coefficients of different groups are loaded by configuring the AXI interface. The advantage is that the implementation is relatively simple, but the disadvantage is that although the coefficients can be switched, they can only be selected in the existing coe, which is not flexible enough.
  2. Via AXI_reload channel rewrites the coefficients to the IP core. The advantage is that it is more flexible, but the implementation is somewhat complex. In addition, it should be noted that the length of the overloaded coefficients should be consistent with the previous ones. This paper also focuses on this method.

2, Experimental process
The system clock is 40M, 5M and 10M single tone signals are generated respectively through two DDS, and the adder synthesizes the two signals to obtain mix_signal and FIR are set as a 128 order high pass filter by default. The filter coefficients are configured online to turn it into a low-pass filter. The change of filter output is observed through simulation.

3, Heavy load factor configuration process
The sequence diagram is as follows:

  • reload channel
    In S_ axis_ reload_ Start transmitting filter coefficient when valid is pulled high, s_axis_reload_tvalid and S_ axis_ reload_ The data is valid when the Tready is high at the same time. When transmitting the last coefficient, it is necessary to set s_axis_reload_tlast is pulled up once, indicating that this is the last coefficient.
  • config channel
    After the reload channel is configured, the s_axis_config_tvalid is raised once, indicating that the configuration is completed; The data and tlast transmitted through the reload channel do not need to be concerned.

Points needing attention:

  1. The coefficient of heavy load has a special transport format, which may not be sent in 1-N sequence. For details, see the implementation part of IP core; Or there is a fir under the IP core folder under src_ reload_ The order.txt file also describes the order when the coefficients are overloaded.

  2. If the clock rate and data rate of FIR are inconsistent, s_axis_data_tvalid cannot be raised all the time; If clock frequency=100M, input sample frequency=50M, then s_axis_data_tvalid should be pulled up every 20ns (consistent with the rate of input sample frequency) and the pull up duration should be 10ns (consistent with the cycle of clock frequency). Of course, you can also directly use an Axi stream fifo as data buffer.

4, Simulation results
After the coefficient is overloaded, the FIR output waveform changes from 10M to 5M, perfect!


5, Source code

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2021/09/18 09:16:50
// Design Name: 
// Module Name: reloadable_fir
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module reloadable_fir(
	input 		clk_100M,
	input 		rst_n  ,
	
	
	input			s_axis_config_tvalid   ,
	output			s_axis_config_tready   ,
	input	[7:0]	s_axis_config_tdata    ,
	
	input 			s_axis_reload_tvalid   ,
	output 			s_axis_reload_tready   ,
	input 			s_axis_reload_tlast    ,
	input 	[15:0]	s_axis_reload_tdata    ,
	
	output 			m_axis_data_tvalid     ,
	output 	[31:0]	m_axis_data_tdata      

    );
	wire			dds_5M_v;
	wire			dds_10M_v;
	wire	[15:0]	dds_5M;
	wire	[15:0]	dds_10M;
	wire	[16:0]	mix_signal;

	dds_5M u_dds_5M (
		.aclk(clk_100M),                              // input wire aclk
		.aresetn(rst_n),                        // input wire aresetn
		.m_axis_data_tvalid(dds_5M_v),  // output wire m_axis_data_tvalid
		.m_axis_data_tdata(dds_5M)    // output wire [15 : 0] m_axis_data_tdata
	);
	
	dds_10M u_dds_10M (
		.aclk(clk_100M),                              // input wire aclk
		.aresetn(rst_n),                        // input wire aresetn
		.m_axis_data_tvalid(dds_10M_v),  // output wire m_axis_data_tvalid
		.m_axis_data_tdata(dds_10M)    // output wire [15 : 0] m_axis_data_tdata
	);
	
	adder u_adder (
		.A(dds_5M),      // input wire [15 : 0] A
		.B(dds_10M),      // input wire [15 : 0] B
		.CLK(clk_100M),  // input wire CLK
		.CE(dds_5M_v&&dds_10M_v),    // input wire CE
		.S(mix_signal)      // output wire [16 : 0] S   17Q14
	);
	wire	s_fir_data_tready;
	
	fir u_fir (
		.aresetn(rst_n),                                                  // input wire aresetn
		.aclk(clk_100M),                                                        // input wire aclk
		
		.s_axis_data_tvalid(s_fir_data_tready),                            // input wire s_axis_data_tvalid
		.s_axis_data_tready(s_fir_data_tready),                            // output wire s_axis_data_tready
		.s_axis_data_tdata(mix_signal[16:1]),                              // input wire [15 : 0] s_axis_data_tdata
		
		.s_axis_config_tvalid(s_axis_config_tvalid),                        // input wire s_axis_config_tvalid
		.s_axis_config_tready(s_axis_config_tready),                        // output wire s_axis_config_tready
		.s_axis_config_tdata(s_axis_config_tdata),                          // input wire [7 : 0] s_axis_config_tdata
		
		.s_axis_reload_tvalid(s_axis_reload_tvalid),                        // input wire s_axis_reload_tvalid
		.s_axis_reload_tready(s_axis_reload_tready),                        // output wire s_axis_reload_tready
		.s_axis_reload_tlast( s_axis_reload_tlast ),                          // input wire s_axis_reload_tlast
		.s_axis_reload_tdata( s_axis_reload_tdata ),                          // input wire [15 : 0] s_axis_reload_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
		.event_s_reload_tlast_missing(),        // output wire event_s_reload_tlast_missing
		.event_s_reload_tlast_unexpected()  // output wire event_s_reload_tlast_unexpected
	);
	
	
	
endmodule

It took more than half a day to finish it. Sprinkle flowers!

Posted by Adeus on Sat, 18 Sep 2021 20:26:25 -0700