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.
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.
| 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 |
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_widthcannot 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_widthcannot 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_lengthmust be evenly divided by ceil(1./sample_period), that is the SSR rate. -
output_lengthmust be evenly divided by ceil(1./sample_period) * ceil(interp_rate / decim_rate) -
output_lengthmust 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.
- 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: