Integer To Bit Converter — Control Systems/Logic And Bit Operations
Control_Systems/Logic_And_Bit_Operations/Integer_To_Bit_Converter · 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.
Integer to Bit Converter
Control Systems / Logic And Bit Operations
Unpacks every entry of the input into n separate entries carrying 0 or 1, where n is Number of Bits. At 3 bits, most significant first, 5 becomes [1 0 1]. A negative value is written in two's complement over the same width: at 4 bits, -8 becomes [1 0 0 0] and -1 becomes [1 1 1 1].
Each entry's bits sit contiguously in that entry's own place, so an input of w entries gives an output of w×n entries. The value unpacked is the entry rounded to the nearest whole number and reduced modulo 2n, which is what makes the block total on a wire that carries doubles – see Notes.
Ports
- Input – the signal u whose entries are unpacked. A vector: [m,1], [1,n] or a scalar. A matrix with both dimensions above one is reported rather than flattened, because which way it would be flattened is exactly the question a user would be guessing at.
- Output – y, the bits. Its size follows the input's: a column of w entries gives a column of w×n, a row gives a row of w×n, and a scalar gives a column of n.
Parameters
- Number of Bits – how many bits each entry becomes. A whole number from 1 to 32; the default is 3, which is the Simulink block's default too.
- Bit Order – which end of the word comes out first.
- MSB first – the most significant bit is the first of each entry's n outputs. The default.
- LSB first – the least significant bit comes first; the same word, reversed.
- Input Signedness – whether the input is meant to carry signed values.
It changes no emitted bit, and that is arithmetic rather than an omission: the
two's-complement pattern of a negative value and the unsigned residue of that value modulo
2n are the same pattern, so at 4 bits both -1 and 15 give
[1 1 1 1]. The setting declares what the input means and is carried so that it survives
a round trip through Simulink.
- Unsigned – entries are meant to lie in 0, 2n). The default.
- Signed – entries are meant to lie in [-2n-1, 2n-1).
- 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. The bit count, the order and the whole unpacking are resolved at export time and inlined, so a generated core carries a fixed list of assignments with no loop and no index arithmetic; none of the three is a tunable parameter on the exported core.
The seven software targets compute the residue with floor only – never a
remainder operator, whose sign convention differs between languages on exactly the negative
inputs this block is most often given – so all seven are bit-identical.
PLC Structured Text has no FLOOR and its TRUNC rounds toward
zero, so the floor is rebuilt from TRUNC with the standard sign correction.
The three HDL targets are genuine synthesizable Q16.16: the round is one add and one
arithmetic shift (fx_to_int), and the rest is integer division by constants. Their
fixed-point format holds whole numbers up to about ±32768, so a word wider than
15 bits unsigned (16 signed) exceeds what a fixed-point port can represent and those
three columns will not match; the seven software targets are exact to the full 32.
Simulink bridge
Import and export, mapped to simulink/Logic and Bit Operations/Integer to Bit
Converter. Number of Bits → nbits, Bit Order →
bitOrder and Input Signedness → signedInputValues, each
1:1 and therefore lossless both ways. Simulink's outDtype selects the integer
TYPE of the emitted bits and has no counterpart here, every ICore signal being a matrix of
doubles, so it is left at its Simulink default.
The rate does NOT cross. That block defines no SampleTime parameter
– verified by set_param against R2026a, which answers "Integer to Bit
Converter block (mask) does not have a parameter named 'SampleTime'" – so
"Sampling Time (s)" stays on the ICore side. Writing it anyway would be a hard error that
aborts the whole generated script rather than a warning that degrades.
Notes
- Algebraic, with no state: the output depends only on the current input.
- The block is total, where Simulink's is not. Simulink's counterpart takes an integer-typed input, so it can refuse anything else, and it does – a non-integer or out-of-range value STOPS the simulation with "Inputs must be integers in the range 0 to (2^(BitsPerInteger) - 1)". An ICore wire carries doubles and has no type to refuse with, so this block defines the value instead: the entry is rounded with floor(v + ½) and reduced modulo 2n. The two agree exactly on every input Simulink accepts; where they differ, Simulink gives no answer at all rather than a different one.
- The output is a different SIZE from the input, and it is fixed for the run. A downstream block that requires its inputs to agree in size must be given signals that do.
- No state space, deliberately. The map is a rounding and a modulus, so it is not linear, and its output is a different size from its input; carrying one would offer the block for model-reduction merges it cannot serve.
- To go the other way – a group of bits back into one number – use Bit to Integer Converter, whose parameters are the mirror of these.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Logic_And_Bit_Operations/Integer_To_Bit_Converter |
| family | Control_Systems/Logic_And_Bit_Operations |
| solver environment class | ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Integer_To_Bit_Converter |
| source | [src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Logic_And_Bit_Operations/Integer_To_Bit_Converter/ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Integer_To_Bit_Converter.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Logic_And_Bit_Operations/Integer_To_Bit_Converter/ICoreBlock_0_Control_Systems_1_Logic_And_Bit_Operations_2_Integer_To_Bit_Converter.h |
| default size on canvas | 80 × 70 px |
| ports at insert | 1 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | — |
| 2 | out | ICoreDouble | — |
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 variable | Default | Simulink parameter |
|---|---|---|
Number of Bits | 3 | nbits |
Bit Order | MSB first%~%LSB first~~MSB first | bitOrder |
Input Signedness | Unsigned%~%Signed~~Unsigned | signedInputValues |
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.
Simulink bridge#
| support | Support::Both |
| Simulink path | simulink/Logic and Bit Operations/Integer to Bit Converter |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Number of Bits | nbits | passes through |
Bit Order | bitOrder | MSB first → MSB first, LSB first → LSB first |
Input Signedness | signedInputValues | Unsigned → Unsigned, Signed → Signed |
Caveat (shown to the user): Simulink's outDtype selects the integer TYPE of the emitted bits, which has no counterpart here -- every ICore signal is a matrix of doubles -- so it is left at its Simulink default. "Input Signedness" crosses but changes no emitted bit on either side: two's complement and the unsigned residue modulo 2^n are the same pattern. The rate does not cross: the Simulink block defines no SampleTime parameter, so "Sampling Time (s)" stays on the ICore side
Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:
B0no sample under docs/generated/samples/ — nothing to cross-check (P8.1)
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).
Integer to Bit Converter -- one signal entry becomes n separate 0/1 entries Each entry of the input is unpacked into "Number of Bits" entries of the output, in the entry's own place and contiguously: at 3 bits MSB first, 5 becomes [1 0 1]. A negative value is written in two's complement over the same width -- at 4 bits, -8 is [1 0 0 0] and -1 is [1 1 1 1], both measured in R2026a rather than assumed.
ONE FORMULA, TEN BACKENDS. Everything below goes through the same three lines:
n = floor(v + 0.5) the entry, rounded m = n - M*floor(n/M), M = 2^n_bits its residue, always in [0, M) bit at position p = floor(m/2^p) - 2*floor(m/2^(p+1))
Written with FLOOR and nothing else on purpose. The obvious spelling uses a remainder operator, and
%truncates toward zero in C, C++, Java, Rust and Verilog whilemodis floored in MATLAB, Python and VHDL -- so the same source line means two different things on a negative value, which is exactly half this block's inputs. A floored modulus built out of floor() means the same thing in all ten, and it is why the software targets are bit-exact rather than nearly so."INPUT SIGNEDNESS" CHANGES NO BIT, AND THAT IS NOT AN OVERSIGHT. The two's-complement pattern of a negative value and the unsigned residue of that value modulo 2^n are the same pattern -- at 4 bits, -1 and 15 both give [1 1 1 1]. The setting declares which values the input is meant to carry, and it is carried here so that it survives a round trip through Simulink. The description says so in as many words rather than leaving a user to discover that a combo box does nothing.
WHERE THIS BLOCK IS DEFINED AND SIMULINK IS NOT. Simulink's counterpart takes an integer TYPE, so it can refuse anything else, and it does: a non-integer or out-of-range input STOPS the simulation with "Inputs must be integers in the range 0 to (2^(BitsPerInteger) - 1)" -- measured. An ICore wire carries doubles and has no type to refuse with, so this block defines the value instead of rejecting it (the round and the residue above). The two agree exactly on every input Simulink accepts; where they differ, Simulink has no answer at all rather than a different one.
Algebraic and stateless. No state space -- see the header.
Sample results#
No sample run is committed for this block. Samples come from the headless harness (DOCS_PLAN.md P8.1) into docs/generated/samples/; until one exists this block's behaviour is witnessed by the parity and export-verification suites, not by a plot here.