In short: The `timescale directive tells the simulator what one delay number means (the unit) and how finely it rounds that delay (the precision), so a wrong or missing timescale silently changes when your signals move.
Why simulation needs a timescale at all
Verilog delays such as #5 are plain numbers. They carry no physical meaning until the simulator is told whether 5 means 5 nanoseconds, 5 picoseconds or 5 microseconds. The `timescale compiler directive supplies that meaning. Its syntax is `timescale time_unit / time_precision, for example `timescale 1ns/1ps.
The first number is the time unit: the length that a delay value of 1 represents inside every module that follows the directive. The second is the time precision: the smallest step to which the simulator rounds delays written in that module. Both must be a power of ten (1, 10 or 100) combined with s, ms, us, ns, ps or fs, and the precision can never be coarser than the unit. `timescale 1ns/10ns is illegal; `timescale 10ns/1ns is fine.
Key fact: The directive is not a module property you declare once. It is a compiler directive that stays in force for every file compiled after it, until another `timescale or `resetall replaces it.
Unit versus precision, with real numbers
Take a module compiled with `timescale 1ns/1ps. A statement #2.5678 a = 1; is first scaled by the unit to 2.5678 ns, then rounded to the precision, giving 2.568 ns. The simulator never schedules the event at 2.5678 ns because it cannot represent anything finer than 1 ps in that module.
Now change the directive to `timescale 10ns/1ns and write #1.54. One unit is 10 ns, so the delay is 15.4 ns, which rounds to 15 ns. The fractional part you typed is mostly thrown away, and that is exactly the kind of surprise that makes a testbench behave differently from what the author expected.
The simulator's global time resolution
A simulator keeps one master clock for the whole design. Its tick is the smallest precision found in any compiled module. If one block is compiled at 1ns/1ps and another at 10ns/1ns, the global tick is 1 ps. Every delay is converted to integer multiples of that tick before it enters the event queue.
This has a cost. A single stray `timescale 1ns/1fs in a vendor model forces the entire run to femtosecond resolution, which inflates simulation time and memory for large netlists. Gate-level teams working with Synopsys VCS, Cadence Xcelium or Siemens Questa routinely audit precision for this reason; 1 ps is the usual compromise for SDF back-annotated runs because standard-cell delays are quoted to picosecond accuracy.
Key fact: Precision does not change how fast a module runs, but the finest precision anywhere in the design sets the tick for everybody.
Mixed timescales: the classic bug
Suppose a clock generator is compiled with `timescale 1ns/1ps and says #5 clk = ~clk;. A DUT file compiled earlier has `timescale 10ns/1ns and contains #5 q <= d;. The clock toggles every 5 ns, while the DUT delay is 50 ns. The design looks logically correct, yet the output arrives ten clock edges late. Nothing errors out; the waveform is simply wrong.
Watching time advance
The animation below shows an event marker walking along a 1 ns/1 ps axis. It does not jump continuously; it lands only on the precision grid, which is how every simulator schedules real events.
Reading time inside the testbench
$time returns an integer in the time unit of the module that calls it, rounded to the nearest whole unit. In a 10ns/1ns module, an event at 15 ns shows as 2 (15 / 10 = 1.5 rounds up). $realtime returns a real number in the same unit, so it prints 1.5. Use $realtime whenever you work with sub-unit delays, and format output with $timeformat so logs are readable. $printtimescale prints the scale of the calling module and is a quick sanity check, especially when you are unsure which file wins. Pair these with the usual print and finish tasks when you instrument a testbench.
| Item | Meaning | Example result |
|---|---|---|
`timescale 1ns/1ps | Unit 1 ns, rounding step 1 ps | #2.5678 becomes 2.568 ns |
`timescale 10ns/1ns | Unit 10 ns, rounding step 1 ns | #1.54 becomes 15 ns |
$time | Integer, in caller's unit | 15 ns in a 10 ns unit gives 2 |
$realtime | Real, in caller's unit | 15 ns in a 10 ns unit gives 1.5 |
Best practices that avoid the usual traps
- Put one
`timescaleat the top of every file, RTL and testbench alike. Relying on compile order is fragile: the same file behaves differently depending on which file precedes it. If you want a deeper walkthrough of the syntax, see our timescale directive in Verilog guide and the companion Verilog timescale note. - Use a single project-wide scale, commonly 1ns/1ps, via a shared include file.
- Know your tool's default. A file with no directive inherits whatever came before it, or a tool default that is implementation specific and often 1ns/1ns. Tools expose overrides such as
-timescale=1ns/1psin VCS and Xcelium, and a similar option in Questa and Vivado Simulator. Use them only to fix legacy code, not as a habit. - Use
`resetallcarefully at the end of library files so their scale does not leak into the next file. - In SystemVerilog prefer the
timeunitandtimeprecisiondeclarations inside modules and packages; they bind to the scope and remove the compile-order problem. - Remember delays on nonblocking assignments follow the same scaling; see blocking vs non-blocking assignments for how those delays interact with the scheduler.
Key fact: Synthesis ignores `timescale and all # delays. It only affects simulation, which is why a design can pass synthesis and still fail a timing-sensitive testbench.
Interview angles
Interviewers like three questions. First, what does #1.55 do under `timescale 1ns/100ps? The answer is 1.6 ns after rounding to the 100 ps step. Second, why does a testbench in a different timescale change DUT behaviour? Because every file scales its own delays and the global tick follows the finest precision. Third, how do you choose a precision for gate-level simulation? Match the SDF timing granularity, usually 1 ps, and avoid femtosecond unless a model demands it. You can practise all of these on real tools in the structured CourseTron courses, and teams that want hands-on training can also look at ChipXpert's VLSI training programs.
Ready to go deeper? Join the CourseTron Verilog and FPGA courses and simulate every example in this article yourself, with guided labs and interview practice.
Frequently asked questions
What is the default timescale if I do not write one?
The standard leaves it implementation defined. Many simulators fall back to 1ns/1ns or inherit the previous file's directive, so you should always state it explicitly.
Can precision be larger than the unit?
No. The precision must be equal to or finer than the unit. `timescale 1ns/1ps is valid; `timescale 1ps/1ns is an error.
Does timescale affect synthesis or FPGA hardware?
No. Synthesis tools ignore the directive and the delays, so real timing comes from constraints and place and route, not from the simulation scale.
Why do my waveforms show times that do not match my delays?
Usually the module that owns the delay is compiled under a different timescale than you assumed, or a fractional delay was rounded to the precision. Check with $printtimescale.