olo_fix_lin_approx_calc¶
Status Information¶
VHDL Source: olo_fix_lin_approx_calc
Bit-true Model: olo_fix_lin_approx
Description¶
This entity implements the calculation part of a piecewise linear approximation of an arbitrary function. The function is approximated by a table which contains the function value (offset) and the derivative of the function (gradient) for regularly spaced points. Between those points the function is approximated linearly.
The olo_fix_lin_approx_calc can calculate one approximation per clock cycle.
The table itself is not part of this entity. It is attached through the Tbl_Addr / Tbl_Data interface. Normally the table is not written by hand but generated from Python. The Python class olo_fix_lin_approx generates a wrapper entity that contains the table and instantiates olo_fix_lin_approx_calc - this is the normal way of using this entity.
Latency of this entity is 7 + TableLatency_g clock cycles (8 clock cycles for the default settings). The entity is fully pipelined, hence it accepts one input sample per clock cycle. As a result, back-pressure is not supported.
For details about the fixed-point number format used in Open Logic, refer to the fixed point principles.
Approximation Principle¶
The full range of InFmt_g is split into TableSize_g segments of equal width. For each segment, the table contains the value of the function at the center of the segment (offset, red) and the derivative of the function at the same point (gradient, blue).

Generics¶
| Name | Type | Default | Description |
|---|---|---|---|
| InFmt_g | string | - | Input data format String representation of an en_cl_fix Format_t (e.g. "(1,1,15)") |
| OutFmt_g | string | - | Output data format String representation of an en_cl_fix Format_t (e.g. "(1,1,15)") |
| OffsFmt_g | string | - | Format of the offset (function value) table entries String representation of an en_cl_fix Format_t |
| GradFmt_g | string | - | Format of the gradient (derivative) table entries String representation of an en_cl_fix Format_t |
| TableSize_g | positive | - | Number of entries in the table. Must be a power of two and smaller than 2^width(InFmt_g) |
| TableLatency_g | positive | 1 | Read latency of the table in clock cycles (range 1 to 3). Increasing the value improves timing for slow ROMs, see Table Interface |
| Round_g | string | "NonSymPos_s" | Rounding mode of the output stage String representation of an en_cl_fix FixRound_t. |
| Saturate_g | string | "Sat_s" | Saturation mode of the output stage String representation of an en_cl_fix FixSaturate_t. |
All generics except TableLatency_g, Round_g and Saturate_g are defined by the table content. They must not be modified without regenerating the table.
Interfaces¶
Control¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Clk | in | 1 | - | Clock |
| Rst | in | 1 | - | Reset input (high-active, synchronous to Clk) |
Input Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| In_Valid | in | 1 | '1' | AXI4-Stream handshaking signal for In_Data |
| In_Data | in | width(InFmt_g) | - | Input data Format: InFmt_g |
Output Data¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Out_Valid | out | 1 | N/A | AXI4-Stream handshaking signal for Out_Result |
| Out_Result | out | width(OutFmt_g) | N/A | Result data Format: OutFmt_g |
Table Interface¶
| Name | In/Out | Length | Default | Description |
|---|---|---|---|---|
| Tbl_Addr | out | log2(TableSize_g) | N/A | Table read address |
| Tbl_Data | in | width(OffsFmt_g)+width(GradFmt_g) | - | Table read data. The gradient is stored in the MSBs (format GradFmt_g), the offset in the LSBs (format OffsFmt_g). |
The table must be a synchronous memory with a read latency of exactly TableLatency_g clock cycles (address registered, data available TableLatency_g clock cycles later). A read latency of one clock cycle corresponds to a ROM with registered address. Values of two or three add output registers to the ROM, which improves timing for (slow) ROMs at the cost of latency. Reads must not be gated - the table must deliver data for every address applied.
Details¶
Architecture¶
Below figure illustrates how the linear approximation is implemented.

N-M is the number of address bits for the table. The figure shows TableLatency_g = 1. For higher values, the remainder path (lower branch) is delayed by the additional table read latency.
Table Details¶
The upper log2(TableSize_g) bits of In_Data are used as table index, the remaining lower bits are the position within the segment. The lower bits are unsigned and relative to the beginning of the segment. By inverting their MSB, they are converted into the signed offset relative to the center of the segment - which is exactly what the multiplication above requires.
For signed InFmt_g, negative input values wrap into the upper half of the table (the table index is simply the unsigned interpretation of the upper input bits). The code generator arranges the table content accordingly.
Precision¶
The multiplication and the addition are executed at full precision (no rounding, no saturation). This allows the adder to be implemented within a DSP slice. Rounding and saturation are applied in separate pipeline stages at the output, controlled by Round_g and Saturate_g.
The approximation error depends on the number of table entries and the formats chosen for the table. The Python class olo_fix_lin_approx provides an analyze() method that helps finding suitable settings.
Usage Example¶
Below example shows how a table is attached manually. Normally the wrapper entity generated by olo_fix_lin_approx is used instead.
signal Tbl_Addr : std_logic_vector(7 downto 0);
signal Tbl_Data : std_logic_vector(34 downto 0);
...
-- Table with one clock cycle read latency (matches the default TableLatency_g = 1)
p_table : process (Clk) is
begin
if rising_edge(Clk) then
Tbl_Data <= Table_c(to_integer(unsigned(Tbl_Addr)));
end if;
end process;
i_approx : entity olo.olo_fix_lin_approx_calc
generic map (
InFmt_g => "(0, 0, 16)",
OutFmt_g => "(1, 0, 16)",
OffsFmt_g => "(1, 0, 18)",
GradFmt_g => "(1, 3, 12)",
TableSize_g => 256
)
port map (
Clk => Clk,
Rst => Rst,
In_Valid => In_Valid,
In_Data => In_Data,
Out_Valid => Out_Valid,
Out_Result => Out_Result,
Tbl_Addr => Tbl_Addr,
Tbl_Data => Tbl_Data
);