olo_fix_fir_dec_ser_chtdm¶
Status Information¶
VHDL Source: olo_fix_fir_dec_ser_chtdm.vhd
Bit-true Model: olo_fix_fir_dec.py
Description¶
This entity implements a decimating FIR filter for multiple TDM (time-division-multiplexed) channels. All channels share the same coefficient set and are processed one after the other. A single shared multiplier computes filter taps serially. One tap after the other, then one tap after the other for the next channel, and so on.
Example: A 4 channel, 16 taps FIR filter requires 64 clock cylces to produce one output sample set (one sample for each channel).
Note that the filter can also be used non-decimation (ratio=1).
For details about the fixed-point number format used in Open Logic, refer to the fixed point principles.
Coefficients can be fixed (ROM) or runtime configurable (RAM) with optional readback.
Input Bandwidth Limitation¶
This entity does not generate backpressure. The serial MAC requires Taps x Channels clock cycles to compute one output sample set (for all channels). This calculation is repeated ever Ratio iput sample sets.
where f_in is the rate of complete TDM frames (one frame = Channels_g samples). If the input arrives faster than this limit, the filter will stop working correctly.
he second row calculates the number of taps that can be processed with given channels, ratio, input rate and clock frequency.
Use olo_base_rate_limit externally to enforce the rate limit.
Latency¶
This block changes the sample rate. Because not every input sample produces an output sample, the latency is not fixed and is therefore not documented in detail.
Generics¶
General Generics¶
| Name | Type | Default | Description |
|---|---|---|---|
| InFmt_g | string | - | Input format String representation of an en_cl_fix FixFormat_t |
| OutFmt_g | string | - | Output format String representation of an en_cl_fix FixFormat_t |
| CoefFmt_g | string | - | Coefficient format String representation of an en_cl_fix FixFormat_t |
| Channels_g | positive | - | Number of TDM channels (must be >= 2) |
| MaxRatio_g | positive | - | Maximum decimation ratio |
| MaxTaps_g | positive | - | Maximum number of filter taps (must be >= 2) |
| RuntimeCfg_g | boolean | false | true - the active ratio and tap count are taken from the Cfg_Ratio / Cfg_Taps ports. false - they are fixed to MaxRatio_g / MaxTaps_g and the Cfg_... ports are ignored. |
| GuardBits_g | natural | 1 | Number of integer guard bits in the accumulator above OutFmt_g |
| Round_g | string | "Trunc_s" | Rounding mode String representation of an en_cl_fix FixRound_t |
| Saturate_g | string | "Warn_s" | Saturation mode String representation of an en_cl_fix FixSaturate_t |
| MultRegs_g | positive | 1 | Number of pipeline registers in the multiplier |
Coefficient and Data Storate¶
| Name | Type | Default | Description |
|---|---|---|---|
| CoefInit_g | string | "0.0" | Comma-separated initial coefficient values (real numbers, quantized to CoefFmt_g) Example: "0.3, 0.55, 0.2" see olo_fix_coef_storage |
| CoefStorageType_g | string | "ROM" | Coefficient storage type: "ROM" (fixed) or "RAM" (runtime-updateable) see olo_fix_coef_storage |
| CoefRamReadback_g | boolean | false | Enable coefficient readback via Coef_Rd_... ports (RAM mode only) see olo_fix_coef_storage |
| CoefRamBehavior_g | string | "RBW" | Coefficient RAM behavior: "RBW" = read-before-write, "WBR" = write-before-read see olo_fix_coef_storage |
| CoefMemStyle_g | string | "auto" | Synthesis attribute for coefficient memory style (e.g. "block", "distributed") see olo_fix_coef_storage |
| DataRamBehavior_g | string | "RBW" | Data RAM behavior: "RBW" = read-before-write, "WBR" = write-before-read see olo_base_ram_sdp |
| DataMemStyle_g | string | "auto" | Synthesis attribute for data RAM style (e.g. "block", "distributed") see olo_base_ram_sdp |
Interfaces¶
Control¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Clk | in | 1 | - | Clock |
| Rst | in | 1 | - | Reset (synchronous, active high) |
Runtime Configuration¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Cfg_Ratio | in | log2ceil(MaxRatio_g) | MaxRatio_g-1 | Decimation ratio minus 1 (1 = ratio 2, 7 = ratio 8). |
| Cfg_Taps | in | log2ceil(MaxTaps_g) | MaxTaps_g-1 | Active tap count minus 1 (1 = 2 taps). A single tap (value 0) is not supported. |
Both ports have safe defaults (maximum ratio and tap count) and are only used when RuntimeCfg_g = true. They can be left unconnected to use the fixed maximum values. Change only when Rst = '1'.
Coefficient Configuration¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Coef_Addr | in | log2ceil(MaxTaps_g) | 0 | Coefficient address for read/write |
| Coef_WrEna | in | 1 | '0' | Coefficient write enable (RAM mode only) |
| Coef_WrData | in | width(CoefFmt_g) | 0 | Coefficient write data (RAM mode only) |
| Coef_RdEna | in | 1 | '0' | Coefficient read enable (RAM readback mode only) |
| Coef_RdData | out | width(CoefFmt_g) | N/A | Coefficient read data (0 in ROM mode) |
| Coef_RdValid | out | 1 | N/A | Coefficient read valid (0 in ROM mode) |
All Coef_* ports have safe defaults and can be left unconnected in ROM mode or when coefficient updates are not needed.
Input Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_Valid | in | 1 | - | Input valid |
| In_Data | in | width(InFmt_g) | - | Input data (TDM: channels interleaved, ch0 first) |
| In_Last | in | 1 | '0' | TDM frame boundary (optional) see TDM Conventions |
The In_Last signal is optional and has no functional effect. In simulation it is only used to check that it is asserted at the correct TDM position (last channel); an error is reported if In_Last is asserted on a sample of any other channel. See Last Handling.
Output Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Out_Valid | out | 1 | N/A | Output valid |
| Out_Data | out | width(OutFmt_g) | N/A | Output data (TDM: channels interleaved, ch0 first) |
| Out_Last | out | 1 | N/A | TDM frame boundary, asserted on the last channel see TDM Conventions |
Details¶
Example Instantiation¶
The example below shows the simplest possible instantiation: fixed coefficients stored in ROM, a fixed tap count and a fixed decimation ratio. The ratio and tap count are fixed by setting MaxRatio_g / MaxTaps_g to the desired values and leaving Cfg_Ratio / Cfg_Taps unconnected (they then default to those maxima). All coefficient configuration ports and In_Last are omitted as well.
i_fir : entity olo.olo_fix_fir_dec_ser_chtdm
generic map (
-- Formats
InFmt_g => "(1,0,15)",
OutFmt_g => "(1,0,15)",
CoefFmt_g => "(1,0,17)",
-- Filter parameters (ratio and taps are fixed to these maximum values)
Channels_g => 4,
MaxRatio_g => 4,
MaxTaps_g => 3,
-- Fixed coefficients stored in ROM
CoefInit_g => "0.25, 0.5, 0.25"
)
port map (
Clk => Clk,
Rst => Rst,
In_Valid => In_Valid,
In_Data => In_Data,
Out_Valid => Out_Valid,
Out_Data => Out_Data
);
Architecture¶
All channel data is stored in a single simple dual-port RAM (olo_base_ram_sdp). The higher address bits select the channel region; the lower bits address the tap (delay line) within that channel. The write port stores new input samples; the read port reads historical samples during computation.
Coefficients are stored in a dedicated olo_fix_coef_storage instance (ROM or RAM depending on CoefStorageType_g).
Below figure depics the conceptual architecture.

Because the data is written into the RAM as it arrives and is read out only when processed, the input may be bursty or have an constant rate. Both work fine.
Startup Behavior¶
At startup the data RAM may contain leftover data from before the reset. The filter replaces RAM reads of locations not yet written with zeros. This matches the Python model, which initializes its delay line to zero, ensuring bit-true agreement from the first output sample.
Coefficient Format¶
The accumulator operates at full multiply precision:
- MultFmt = (max(In.S, Coef.S), In.I + Coef.I, In.F + Coef.F)
- AccuFmt = (1, Out.I + GuardBits_g, In.F + Coef.F) (GuardBits_g guard bits above output)
Choosing OutFmt.I or GuardBits_g too small risks accumulator overflow. Ensure max_sum_of_products <= 2^(OutFmt.I + GuardBits_g) - 1 LSB.
Accumulator Guard Bits¶
The accumulator carries GuardBits_g integer guard bits above OutFmt_g (AccuFmt.I = OutFmt.I + GuardBits_g). These bits allow the sum of products to grow beyond the output range during the accumulation without overflowing. With the default of one guard bit, intermediate results of up to twice the OutFmt_g maximum are supported. The user is responsible for choosing GuardBits_g, the coefficients and the formats such that the accumulator does not overflow; otherwise the number of guard bits or the output format must be increased.
Last Handling¶
On the input, In_Last is not required for operation. It is only used in simulation to detect incorrect TDM framing: an error is reported if In_Last is asserted on a sample that does not belong to the last channel (Channels_g-1). It has no functional effect on the computation.
On the output, Out_Last is generated by the entity itself and is always asserted together with Out_Valid on the last channel (Channels_g-1) of every output sample set.
Runtime Configuration¶
The Cfg_Ratio and Cfg_Taps ports are only evaluated when RuntimeCfg_g = true. In that case they must only be changed while Rst = '1'; changing them during operation produces undefined behavior. When RuntimeCfg_g = false (default) the ports are ignored and the filter uses fixed MaxRatio_g / MaxTaps_g values.
A single-tap filter (Cfg_Taps = 0) is not supported. The minimum tap count is 2.