Generated reference › Digital Clock — Control Systems/Sources
kind: generated#block#control-systems-sources

Digital Clock — Control Systems/Sources

Control_Systems/Sources/Digital_Clock · 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.

Digital Clock

Control Systems / Sources

A source that outputs the time of the last sample hit – simulation time quantized down to the block's own rate:

y(t) = floor(t / Tq)·Tq, where Tq is Sampling Time (s)

Ports

  • Output – the quantized time in seconds, always a scalar. It has no inputs. The value holds steady between sample instants and steps up by Tq at each one, which is the time a discrete controller running at Tq actually observes.

Parameters

  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. On this block it is not only the rate but the quantization interval: it is the Tq in the formula above, and so it is the one parameter that changes what the output IS rather than merely how often it is refreshed. This is deliberate, and matches Simulink, whose Digital Clock also has exactly one parameter doing exactly these two jobs.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Tq is baked into the arithmetic at export time rather than exposed as a tunable parameter, because it is structural: it is also the rate the generated core is scheduled at, so retuning it on a built core would leave the staircase and the schedule disagreeing. Each target uses a per-block local sample clock rather than a global one. The three HDL targets are simulation-only: they read the testbench-driven sim_time real, which a synthesized core does not have.

Simulink bridge

Import and export, mapped to simulink/Sources/Digital Clock. "Sampling Time (s)" to SampleTime, which is the mapping the whole block rests on – Simulink's Digital Clock exposes no other parameter at all, so the two blocks are configured by the same single number and there is nothing left over on either side.

Notes

  • Time-driven and stateless: the output depends only on the current time, and a re-run reproduces it exactly.
  • Discrete by nature, so it always takes its period from its own "Sampling Time (s)" rather than inheriting the surrounding rate mid-model.
  • At a single rate this block equals Clock. When Tq is the same as the surrounding rate, every instant the block is asked about is already a multiple of Tq and the staircase has one sample per step – so the two blocks agree exactly, and the difference only appears once Tq is made coarser than the model's step. That is worth knowing before reaching for it: the reason to use Digital Clock is to model what a SLOWER discrete subsystem sees.
  • The floor is computed with a small tolerance so that an instant which is mathematically an exact multiple of Tq, but which floating point left a hair below one, still counts as having arrived. Without it the block would report the previous sample's time on every step.

Code facts#

FactValue
registered typeControl_Systems/Sources/Digital_Clock
familyControl_Systems/Sources
solver environment classICoreBlock_0_Control_Systems_1_Sources_2_Digital_Clock
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Digital_Clock/ICoreBlock_0_Control_Systems_1_Sources_2_Digital_Clock.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Digital_Clock/ICoreBlock_0_Control_Systems_1_Sources_2_Digital_Clock.h
default size on canvas70 × 70 px
ports at insert0 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1outICoreDouble

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#

No config variable beyond the Sampling Time (s) every block carries.

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 pathsimulink/Sources/Digital Clock
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): the rate is the whole mapping: Simulink's Digital Clock exposes only SampleTime, and on both sides that single number is both the block's period and the interval the reported time is quantized to

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).

Digital Clock block — y = the time of the last sample hit The quantized companion to Clock. Where Clock reports whatever instant it is asked about, this block reports the last instant its own rate actually landed on:

y(t) = floor(t / Tq) * Tq Tq = the block's "Sampling Time (s)"

which is a staircase whenever Tq is coarser than the surrounding rate, and plain t whenever the two agree. That is Simulink's semantics exactly: its Digital Clock has ONE parameter, SampleTime, and that single number both schedules the block and sets the step size — which is why this block adds no config variable of its own and reads the base class's rate.

Discrete by nature (setDiscreteOnlyBlock): the value only moves at its own sample instants, so it must take its period from its own config rather than be pushed through a continuous solver's intermediate stages.

THE FLOOR IS THE WHOLE BLOCK, AND IT IS WHERE IT CAN GO WRONG. t/Tq lands a hair below the integer it should be for the ordinary case where t is an exact multiple of Tq (0.03/0.01 = 2.9999999999999996), and a bare floor() then reports the PREVIOUS sample's time — for every sample, on every target. SAMPLE_EPS is what recovers the intended integer; see the header for why its size is the one that works.

Code export: all ten targets. The three HDL ones are SIMULATION-ONLY, reading the testbench-driven sim_time real, as Clock and the other time-driven sources do.

Sample results#

Digital Clock — No input: the block run aloneDigital Clock — No input: the block run alone0246012345t (s)

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__Digital_Clock.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).