Generated reference › Uniform Encode — Control Systems/Quantization
kind: generated#block#control-systems-quantization

Uniform Encode — Control Systems/Quantization

101

Control_Systems/Quantization/Uniform_Encode · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Uniform Encode

Control Systems / Quantization

Maps a real signal in [−V, +V] onto the 2N whole-numbered codes of an N-bit uniform quantizer, entry by entry:

T = 2N / (2V), then y = floor( clamp( (u + V)·T + offset ) )

In unsigned format the offset is zero and the clamp is [0, 2N−1]; in signed format the offset is −2N−1 and the clamp is [−2N−1, 2N−1−1]. This is MATLAB's uencode and the block Uniform Decode inverts.

Ports

  • u – the real signal to quantize, of any size [m,n]. Values outside [−V, +V] are not an error: they saturate at the end code.
  • y – the codes, the same size [m,n] as the input. They are whole numbers carried in ICore's ordinary real signal, since every wire in this tree is a matrix of doubles.

Parameters

  • Number of Bits – N, a whole number from 2 to 32, which is uencode's own range. It fixes the number of codes at 2N and the step at 2V/2N.
  • Peak Value – V, the positive end of the input range. The quantizer covers [−V, +V]; a larger V spreads the same 2N codes over a wider span and quantizes more coarsely.
  • Output Format – which codes come out:
    • unsigned – 0 … 2N−1, with −V at code 0. The default, as in MATLAB.
    • signed – −2N−1 … 2N−1−1, the same lattice shifted so that the middle of the range sits at code 0.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text.

N, V and the format are structural: they are folded into the three constants T, the offset and the clamp bounds and inlined into the arithmetic at export time rather than exposed as tunable parameters. Re-export after changing any of them.

The three HDL targets are genuinely synthesizable Q16.16 – a multiply, an add, two comparisons and an arithmetic shift, which is what the floor is in fixed point. That bounds N in hardware: the datapath's whole-number range is ±32767, so a code fits while N ≤ 15 and the fixed-point cores saturate at the datapath rather than at the block's own bounds above that. The seven software targets are exact to N = 32.

Simulink bridge

Import and export, mapped to DSP System Toolbox's dspquant2/Uniform Encoder. "Number of Bits" to bits, "Peak Value" to peak, and "Output Format" to otype with unsigned ↔ Unsigned integer and signed ↔ Signed integer – one option for one option, so the round trip is lossless.

That block has no SampleTime parameter (measured: set_param refuses it), so the rate does not cross and a block configured with an explicit positive period reports that it stayed on the ICore side.

Simulink's encoder emits an integer-typed signal (uint8, int16 and so on, the width chosen from N). ICore has one signal type, a matrix of doubles, so the same whole numbers arrive as doubles here.

Notes

  • Algebraic and stateless: the output depends on this sample alone.
  • The clamp comes before the floor, and the rounding is a floor rather than a round-to-nearest – so a code owns the half-open interval that starts at its own level. Measured at N = 2, V = 1: an input one eps below −0.5 encodes to 0 and −0.5 itself encodes to 1.
  • Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable – a floor and two clamps are not an A/B/C/D pair.
  • Uniform Decode is the inverse, and a code round-trips through the pair to the middle of its own interval rather than to the original value: that is what quantizing costs, and the two blocks agree about it.
  • Not the same block as Quantizer in Discontinuities, which rounds a signal onto a lattice and answers in the signal's own units. This one answers a code.

Code facts#

FactValue
registered typeControl_Systems/Quantization/Uniform_Encode
familyControl_Systems/Quantization
solver environment classICoreBlock_0_Control_Systems_1_Quantization_2_Uniform_Encode
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Quantization/Uniform_Encode/ICoreBlock_0_Control_Systems_1_Quantization_2_Uniform_Encode.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Quantization/Uniform_Encode/ICoreBlock_0_Control_Systems_1_Quantization_2_Uniform_Encode.h
default size on canvas112 × 72 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubleu
2outICoreDoubley

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Number of Bits8bits
Peak Value1peak
Output Formatunsigned%~%signed~~unsignedotype

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::Both
Simulink pathdspquant2/Uniform\nEncoder
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
ICore configSimulink parameterValue translation
Number of Bitsbitspasses through
Peak Valuepeakpasses through
Output Formatotypeunsigned → Unsigned integer, signed → Signed integer

Caveat (shown to the user): Simulink's encoder emits an integer-typed signal whose width follows from the bit count; ICore carries one signal type, a matrix of doubles, so the same whole numbers arrive as doubles here. The block has no SampleTime parameter, so the rate stays on the ICore side

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Uniform Encode -- a real signal onto the whole-numbered codes of an N-bit uniform quantizer ONE EXPRESSION, TEN TIMES. Every target emits the same three steps entry by entry: scale the input onto the code axis, clamp it to the format's range, and take the FLOOR. There is no state, no loop bound that depends on data, and the only branch is the clamp.

THE RULE IS MEASURED. Read out of uencode.m in R2026a and reproduced term for term -- T = 2^N/(2V), p = (u+V)*T, clamp, floor -- and then checked against the block DSP System Toolbox ships: driven with the same twelve samples at N = 4, V = 2, signed, both dspquant2/Uniform Encoder and uencode() answered [-8 6 -4 6 7 0 0 -8 -2 -1 7 7], max difference 0. That is why this block carries a real Simulink bridge rather than the "no equivalent" entry it was first expected to need: the Signal Processing Toolbox ships no Simulink library, but the library a function's block lives in need not be its own toolbox's.

⚠ THE CLAMP COMES BEFORE THE FLOOR and the rounding is a FLOOR, not a round-to-nearest, so a code owns the half-open interval that STARTS at its own level. Probed at N = 2, V = 1 (a step of 0.5): -0.5-eps encodes to 0 and -0.5 encodes to 1.

⚠ THE HDL TARGETS ARE SYNTHESIZABLE, WHICH BOUNDS N THERE. The datapath is Q16.16, whose whole-number range is +/-32767, so a code fits it while N <= 15. The seven software targets are exact to N = 32, and the description says so where a user will read it.

Sample results#

Uniform Encode — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleUniform Encode — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample0100200-2-10123inputoutput
tin ICoreDouble-Out-0out ICoreDouble-Out-0
0-20
0.40.5192
0.8-20
1.20.5192
1.6-20
20.5192
2.4-20
2.80.5192
3.2-20
3.60.5192
4-20
4.40.5192
4.8-20
5.20.5192

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)128 … 255
rampRamp: slope 1 from t = 0128 … 255
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias0 … 255
stepStep: 0 -> 1 at t = 1 s128 … 255

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

Category static · sample time 0.1 · 60 steps · commit 7ca20bb04513709749749f4b67447f47781efd02 · produced by docsSample --out <folder> --blocks Uniform_Encode --steps 60 · data docs/generated/samples/Control_Systems__Quantization__Uniform_Encode.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).