Counter Free Running — Control Systems/Sources
Control_Systems/Sources/Counter_Free_Running · 0 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.
Counter Free-Running
Control Systems / Sources
A sample counter that overflows like a fixed-width register:
y[k] = k mod 2bits, one step per sample
It emits 0 on the first sample, one more on each sample after it, and wraps back to 0 once the count no longer fits in the configured number of bits.
Ports
- Output – the current count, always a scalar. It has no inputs; the count comes from the block's own state, advancing once per sample.
Parameters
- Number of Bits – the width of the imaginary register, so the counter runs 0 to 2bits−1 and then wraps. A whole number from 1 to 53; the upper limit is where a count stops being exactly representable in the double a signal carries, and a value outside the range stops the run with a message naming the block.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. On this block it also sets how fast the count advances, since one sample is one increment.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The wrap length is baked into the arithmetic at export time rather than exposed as a tunable parameter: it is structural, and a counter whose modulus could be changed on a built core would be a different block. Alone among the sources this one reads no clock at all – it counts its own invocations – so the three HDL targets are not simulation-only here; they are an ordinary counting register.
The HDL caveat is range rather than timing. A signal is carried in Q16.16 there, which reaches 32767, so a counter configured wider than 15 bits produces counts the HDL signal cannot represent even though the software targets carry them without trouble. Keep Number of Bits at 15 or below for a model intended for the HDL backends.
Simulink bridge
Import and export, mapped to simulink/Sources/Counter Free-Running.
"Number of Bits" to NumBits. The rate crosses too, but under
Simulink's own name for it: this block is a masked subsystem there, and it calls
its rate parameter tsamp rather than SampleTime –
so "Sampling Time (s)" maps to tsamp, exactly as Tapped Delay does
for the same reason.
Notes
- Stateful: the whole state is the count, which starts at 0 at the beginning of every run, so a re-run reproduces the sequence exactly.
- Discrete by nature, so it always takes its period from its own "Sampling Time (s)".
- The count is driven by SAMPLES, not by elapsed time. Changing the rate changes how quickly the counter climbs in wall-clock terms but not the sequence of values it produces – y[k] is the same list either way.
- See Counter Limited for the same counter with an arbitrary upper limit rather than a power-of-two one.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Sources/Counter_Free_Running |
| family | Control_Systems/Sources |
| solver environment class | ICoreBlock_0_Control_Systems_1_Sources_2_Counter_Free_Running |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Counter_Free_Running/ICoreBlock_0_Control_Systems_1_Sources_2_Counter_Free_Running.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Counter_Free_Running/ICoreBlock_0_Control_Systems_1_Sources_2_Counter_Free_Running.h |
| default size on canvas | 80 × 70 px |
| ports at insert | 0 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 | 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 | 16 | NumBits |
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/Sources/Counter Free-Running |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
| rate parameter name | tsamp |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Number of Bits | NumBits | passes through |
Caveat (shown to the user): the rate crosses as 'tsamp' - Simulink's Counter Free-Running is a masked subsystem and does not use the standard 'SampleTime' parameter name
Catalog contract: src/ICoreSDK/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).
Counter Free-Running block — y[k] = k mod 2^bits A sample counter that overflows the way a hardware register does. It emits 0 on the first sample and one more on each sample after it, until the value a "Number of Bits"-wide register can no longer hold it, at which point it wraps back to 0 and starts again:
y[k] = k mod 2^bits k = 0, 1, 2, ... one per SAMPLE
Verified against simulink/Sources/Counter Free-Running: with NumBits = 3 that block emits 0,1,...,7,0,1,... beginning at t = 0, which is what this one does.
Discrete by nature (setDiscreteOnlyBlock): the count advances once per SAMPLE, so the block must take its period from its own "Sampling Time (s)" rather than be pushed through a continuous solver's intermediate stages -- which would advance it several times per step.
The count is held as an explicit integer state rather than derived from the clock as floor(t/Ts). Both would be right on paper, but the state is exact by construction where the division is one rounding away from reporting a whole count early or late, and the state is also what the HDL targets want anyway.
Code export: all ten targets, none of them simulation-only -- the block reads no clock, so the HDL cores are an ordinary counting register. The one HDL caveat is RANGE, not timing: a signal is Q16.16 there, so counts above 32767 do not fit. See the description.
Sample results#
Plotted: free — No input: the block run alone
Category source · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Control_Systems__Sources__Counter_Free_Running.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).