FIR Static Parameters - FIR Static Parameters - 2025.2 English - UG1399

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2026-01-22
Version
2025.2 English

The static parameters of the FIR define how the FIR IP is parameterized and specifies non-dynamic items such as the input and output widths, the number of fractional bits, the coefficient values, the interpolation and decimation rates. Most of these configurations have default values: there are no default values for the coefficients.

The hls_fir.h header file defines a struct hls::ip_fir::params_t to set the default values for most of the static parameters.

Important: There are no defaults defined for the coefficients. Therefore, AMD does not recommend using the pre-defined struct to directly initialize the FIR. A new user defined struct which specifies the coefficients should always be used to perform the static parameterization.

In this example, a new user struct my_config is defined and with a new value for the coefficients. These coefficients are specified as residing in array coeff_vec. All other parameters to the FIR use the default values.

struct myconfig : hls::ip_fir::params_t {
    coeff_vec[sg_fir_srrc_coeffs_len] = {...};
};
static hls::FIR<myconfig> fir1;
fir1.run(fir_in, fir_out);

Fir Struct Parameters

The following table describes the parameters used for the parametrization struct hls::ip_fir::params_tand lists the default values for the parameters as well as the possible values.

Table 1. FIR Struct Parameter Values
C Variable Name C Type Default Value Comment
data_width unsigned 16 No limitation
data_frac_width unsigned 0 Limited by size of input_width
output_width unsigned 24 No limitation (Not settable for output_rounding_mode=full_precision)
coeff_width unsigned 16 No limitation
coeff_fract_width unsigned 0 Limited by size of coeff_width
config_width unsigned 8 Deprecated. Will be removed in a future version.
num_coeffs bool 21 Full
coeff_sets unsigned 1 1-1024
data_length unsigned num_coeffs No limitation (but see below for constraints depending on interp_rate, decim_rate and sample_period)
output_length unsigned num_coeffs No limitation
num_channels unsigned 1 1-1024
total_num_coeff unsigned num_coeffs * coeff_sets Not applicable
coeff_vec double array None Not applicable
reloadable bool false Not applicable
filter_type unsigned single_rate single_rate, interpolation, decimation, hilbert_filter, interpolated
rate_change unsigned integer integer, fixed_fractional
interp_rate unsigned 1 1-1024
decim_rate unsigned 1 1-1024
zero_pack_factor unsigned 1 1-8
chan_seq unsigned basic basic, advanced
rate_specification unsigned input_period Not applicable
sample_period double 1 No Limitation
quantization unsigned integer_coefficients Not applicable
best_precision bool false

false

true

coeff_structure unsigned non_symmetric inferred, non_symmetric, symmetric, negative_symmetric, half_band, hilbert
output_rounding_mode unsigned full_precision full_precision, truncate_lsbs, non_symmetric_rounding_down, non_symmetric_rounding_up, symmetric_rounding_to_zero, symmetric_rounding_to_infinity, convergent_rounding_to_even, convergent_rounding_to_odd
filter_arch unsigned systolic_multiply_accumulate systolic_multiply_accumulate, transpose_multiply_accumulate
optimization_goal unsigned area area, speed
inter_column_pipe_length unsigned 4 1-16
column_config unsigned 1 Not applicable
config_method unsigned single single, by_channel
coeff_padding unsigned 0 Amount of zero padding added to the front of the filter
num_paths unsigned 1 Number of datapaths supported
data_sign unsigned value_signed Not applicable
coeff_sign unsigned value_signed Not applicable
Important: When specifying parameter values which are not integer or boolean, the HLS FIR namespace should be used. For example the possible values for rate_change are shown in the table to be integer and fixed_fractional. The values used in the C program should be rate_change = hls::ip_fir::integer and rate_change = hls::ip_fir::fixed_fractional.

Restrictions and Known Issues

Limitations based on the Vivado IP:

  • While input and output data width used inside the FIR IP can have any integer value supported by the FIR IP, the input and output data widths must be rounded up to the next multiple of 8, due to restrictions on the FIR IP interface.
    • output_width cannot be chosen arbitrarily when output_rounding_mode=full_precision. Refer to FIR Compiler LogiCORE IP Product Guide (PG149) or use the Vivado Integrated Design Environment (IDE) to check the legal value.
    • output_fract_width cannot be chosen arbitrarily at all. For more information refer to the FIR Compiler LogiCORE IP Product Guide (PG149) or use the Vivado Integrated Design Environment (IDE) to check the legal value.
  • The FIR with interpolation_rate>1 does not support switching filter parameters (coeff_sets must be 1).
  • Input and output data length for one execution of the FIR must match the length requirements dictated by the SSR rate and the interpolation and decimation:
    • input_length must be evenly divided by ceil(1./sample_period), that is the SSR rate.
    • output_length must be evenly divided by ceil(1./sample_period) * ceil(interp_rate / decim_rate)
    • output_length must be equal to input_length * interp_rate / decim_rate.
    • For example, if a FIR has:
      • sample_period = 0.5 (that is SSR rate == ceil(1./0.5) == 2)
      • interp_rate=3
      • decim_rate=2
      • Then:
        • For 2 input data it must have 2 * 3 / 2 = 3 output data
        • ceil(1./sample_period) * ceil(interp_rate/decim_rate)=2 * ceil(3 / 2)=4
        • To ensure that output_length is evenly divided by 4, one must use:
          • input_length=8
          • output_length=8 * 3 /2 = 12
    • For some of these violations assertions can be generated during C simulation and co-simulation, for example.:
      void hls::FIR<myconfig>::run_sim(in_data_t *, out_data_t *, config_t *, coeff_t *, sim_mode_t) [_CONFIG_T = myconfig]: 
        Assertion `fir_out->data_size == _CONFIG_T::output_length * _CONFIG_T::num_channels' failed.
    • For some other violations the IP packager of Vivado generates an error.
    • For the remaining violations, cosimulation hangs, because the FIR can be blocked waiting for inputs that will never arrive, or will not produce all the outputs that the test bench expects. In this case:
    • Either of the rules above must be followed
    • Or the test bench should produce one extra dummy array of input data, to enable the output data to be generated.
  • For SSR==1 and interpolation_rate==1, fir_in and fir_out must:
    • Either have an array data type, in this case they can be connected to:
    • Either local arrays with #pragma HLS stream
    • Top arguments with the ap_fifo interface protocol
    • Have an hls::stream data type, in this case they can be connected to:
    • Either local hls::streams
    • Top hls::stream arguments with the ap_fifo interface protocol.
    • If this rule is violated, a compilation error is generated during cosimulation or logic synthesis in Vivado.
  • For SSR>1 or interpolation_rate>1 the fir_in and fir_out arguments must only satisfy the usual C++ type constraints and can have any supported interface type for arrays and hls:;streams.

    For example, the following code doesn’t work with SSR==1 and interpolation_rate==1 (an error is generated in Vivado during cosim or logic synthesis).

    void top(s_data_t in[INPUT_LENGTH],
             m_data_t out[OUTPUT_LENGTH]) { 
    #pragma HLS interface m_axi port=in,out
        static hls::FIR<myconfig> fir1;
        fir1.run(in, out);
    }

    While this code works:

    void top(s_data_t in[INPUT_LENGTH],
             m_data_t out[OUTPUT_LENGTH]) { 
    #pragma HLS interface ap_fifo port=in,out
        static hls::FIR<myconfig> fir1;
        fir1.run(in, out);
    }

    This code works as well:

    void top(s_data_t in[INPUT_LENGTH],
             m_data_t out[OUTPUT_LENGTH]) { 
    #pragma HLS interface m_axi port=in,out
        hls::stream<s_data_t> in_t;
        hls::stream<m_data_t> out_t;
        static hls::FIR<myconfig> fir1;
    #pragma HLS dataflow
        for (int i = 0; i < INPUT_LENGTH; fir++)
            in_t.write(in[i]);
        fir1.run(in_t, out_t);
        for (int i = 0; i < OUTPUT_LENGTH; fir++)
            out[i] = out_t.read();
    }
  • Hence:
    • There is no need to add the copy-in and copy-out loops (as in the second example above, with #pragma HLS interface ap_fifo port=in,out) for:
      • Either FIRs with SSR>1 or interpolation_rate>1
      • Or FIRs with local input and output arrays or streams
    • The copy-in and copy-out loops are still needed to connect the filter to a non-stream top argument (as in the third example above, where the interface protocol can be any that is legal for arrays) for SSR==1 and interpolation_rate==1.