Skip to content

VHDL · Chapter 2.13 · Data Types

Physical Types and time

Most VHDL types are pure numbers, but a physical type is a number with a unit attached. The one you use constantly is time, expressed as values like ten nanoseconds or five picoseconds, and it is the type behind every after delay, every wait for, and every clock period in a testbench. This lesson shows how a physical type is built from a base unit plus scaled secondary units, how time schedules a value into the future, and the rule that keeps designs honest. Time and after are simulation constructs that synthesis ignores, so they belong in testbenches and as generic and constant parameters, never as the timing of synthesizable logic. Writing after delays in synthesizable code is a classic simulation-versus-synthesis trap.

Foundation13 min readVHDLPhysical TypestimeafterSimulationGenerics

1. Intuition — a number with a unit

A scalar like integer is just a value. A physical type binds a value to a unit so the quantity is self-describing: 10 ns is not the bare number 10, it is ten nanoseconds. VHDL predefines exactly one physical type you will use everywhere — time — and lets you declare your own for any measured quantity (resistance, capacitance, distance).

time_is_a_physical_type.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
constant CLK_PERIOD : time := 10 ns;   -- a value (10) and a unit (ns)
constant SETUP      : time := 200 ps;  -- another time, different unit, same type
-- CLK_PERIOD and SETUP are both `time`; the units interoperate by scale.

The point of the unit is that the compiler tracks it: you cannot accidentally add a time to an integer, and the simulator knows that 1 ns is 1000 ps.

2. How a physical type is built — base unit plus secondary units

A physical type declares one base unit (the smallest, indivisible step) and any number of secondary units defined as integer multiples of it. time's base unit is fs, and every larger unit is a scale of it:

the time type unit ladder from fs up to hr with scale factors×1000×1000×1000×1000×1000 / ×60fsbase unit (resolutionfloor)ps1 ps = 1000 fsns1 ns = 1000 psus1 us = 1000 nsms1 ms = 1000 ussec / min / hr1 sec = 1000 ms, min = 60sec, hr = 60 min12
The predefined time type: a base unit (fs) plus secondary units, each an exact integer multiple of the one below. 1 ps = 1000 fs, 1 ns = 1000 ps, and so on up through sec, with min = 60 sec and hr = 60 min. Every time value is internally an integer count of the base unit fs, which is why the simulator has a finite time resolution — delays smaller than the resolution round away. A custom physical type follows the same shape: one base unit and scaled secondary units.

You can declare your own physical type the same way — a base unit and scaled secondaries:

custom_physical_type.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
type resistance is range 0 to 2_000_000_000
  units
    ohm;                 -- base unit
    kohm = 1000 ohm;     -- secondary units, integer multiples of the base
    Mohm = 1000 kohm;
  end units;
 
constant R_PULLUP : resistance := 10 kohm;   -- self-documenting quantity

3. time in action — after schedules a value into the future

The reason time matters is the after clause: a signal assignment with after t does not take effect now — it schedules the new value to appear t later. This is the foundation of delay modelling and of every wait for in a testbench:

y <= x after 5 ns — the new value is scheduled, then appears 5 ns later

8 cycles
y <= x after 5 ns — the new value is scheduled, then appears 5 ns laterx rises to 1 herex rises to 1 herey follows 5 ns later — the 'after' delayy follows 5 ns later —…x00111111y00000011t0t1t2t3t4t5t6t7
`after` projects a transaction onto the signal's driver at a future time. The value of x at one instant reaches y only after the modelled delay, exactly as a real propagation/interconnect delay would. This is a simulation behaviour: it models timing, it does not build a delay element in hardware.
after_delay.vhd — simulation/testbench modelling
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
y    <= x after 5 ns;            -- model a 5 ns propagation delay
clk  <= not clk after CLK_PERIOD / 2;   -- a free-running clock in a testbench
wait for 100 ns;                 -- advance simulation time by 100 ns

4. Hardware interpretation — time is for simulation, not synthesis

This is the rule that separates a working design from a sim-only artifact: time and after are not synthesizable. Synthesis builds logic from behaviour, not from wall-clock delays — it has no way to realise "5 ns later" as gates. So after delays are simply ignored (or rejected) by synthesis, and a time signal cannot become hardware.

Where physical types do belong in real RTL is as parameters — generics and constants that configure a design or its testbench without ever becoming logic:

time_as_a_parameter.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
entity baud_gen is
  generic ( CLK_PERIOD : time := 10 ns;     -- a configuration value, not logic
            BAUD       : integer := 115200 );
  port ( clk : in std_logic; tick : out std_logic );
end entity;
-- Inside, the DIVISOR is computed as an integer (numeric_std arithmetic);
-- CLK_PERIOD documents the intended clock but is not itself synthesised.

5. Debugging example — the after that "did nothing" in synthesis

A frequent bring-up surprise: a delay that works perfectly in simulation vanishes in hardware.

the sim-only delay trap
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Intended (wrongly) as a real hold: works in sim, ignored by synthesis.
q <= d after 3 ns;
-- Simulation: q follows d 3 ns late, looks correct on the waveform.
-- Synthesis: the 'after 3 ns' is dropped — q <= d becomes a plain wire/assignment,
-- so the 3 ns never exists in silicon. The gate-level behaviour differs from RTL sim.

The fix is conceptual: never use after to create timing in synthesizable logic. Real timing comes from clocked registers and the place-and-route delays, not from after. Reserve after for testbench stimulus and for delay modelling in non-synthesizable models, and confirm RTL intent with a zero-delay or gate-level simulation rather than RTL after delays.

6. Common mistakes & what to watch for

  • Putting after delays in synthesizable RTL. They are simulation-only; synthesis ignores them, creating an RTL-vs-gate mismatch. Use clocked logic for real timing.
  • Assuming time can be a hardware signal. It cannot be synthesised; keep it in testbenches, generics, and constants.
  • Delays below the simulator's resolution. time is an integer count of fs (or the set resolution); a delay finer than the resolution rounds to zero and silently disappears.
  • Mixing a physical type with a plain number. CLK_PERIOD + 5 does not compile — add a time to a time (CLK_PERIOD + 5 ns); convert deliberately when you need an integer count.
  • Reaching for min/hr in hardware contexts. They exist for completeness; real designs live in ps/ns.

7. Engineering insight

Physical types make quantities self-documenting and type-safe: a CLK_PERIOD : time := 10 ns says what it means and cannot be confused with an integer, which is exactly what you want for testbench timing and configuration. The discipline is to keep them on the simulation/parameter side of the line. Synthesizable hardware expresses timing structurally — through clocks, registers, and the physical delays the tools compute — never through after. Knowing that after schedules a future transaction (rather than storing a value now) is also the bridge to the next module: signals update by scheduling, and time is just the explicit-delay form of the same mechanism.

8. Summary & next step

A physical type is a number plus a unit, built from a base unit and integer-scaled secondary units. time (fs…hr) is the predefined one, and after/wait for use it to schedule values into the future — the basis of delay modelling and testbench clocks. Crucially, time and after are simulation constructs: synthesis ignores them, so in real RTL physical types live as generics and constants, while timing comes from clocked logic.

That closes the Data Types module — you can now describe logic values, numbers, enumerations, composites, subtypes, and physical quantities. The next module steps from what values exist to how values move: the signal, VHDL's model of a real wire, including the scheduled, delta-delayed update behaviour that after just previewed — starting with the most important distinction in the language, signals vs variables.