7.3. The `timescale Directive: Simulation Time Control
What is `timescale?
The `timescale directive specifies the time unit and time precision for delay values in simulation. It controls how the simulator interprets delays like #10 or #5.5.
`timescale time_unit / time_precision
​
Format:
​
-
time_unit: Base unit for delays (1s, 1ms, 1us, 1ns, 1ps, 1fs)
-
time_precision: Smallest resolvable time (must be ≤ time_unit)
​
Valid time units: 1s, 10s, 100s, 1ms, 10ms, 100ms, 1us, 10us, 100us, 1ns, 10ns, 100ns, 1ps, 10ps, 100ps, 1fs, 10fs, 100fs
7.3.1. Understanding Time Unit and Precision
​
Example 1: Basic Timescale
Verilog
`timescale 1ns / 1ps
module clock_gen;
reg clk;
initial begin
clk = 0;
forever #5 clk = ~clk; // 5 * 1ns = 5ns, toggles every 5ns
// Period = 10ns, Frequency = 100MHz
end
endmodule
Example 2: Effect of Different Timescales
Verilog
// Testbench 1
`timescale 1ns / 1ns
module tb1;
reg clk;
initial begin
clk = 0;
#10 clk = 1; // 10ns delay
#5.7 clk = 0; // 5.7ns rounds to 6ns (precision is 1ns)
end
endmodule
// Testbench 2
`timescale 1ns / 1ps
module tb2;
reg clk;
initial begin
clk = 0;
#10 clk = 1; // 10ns delay
#5.7 clk = 0; // 5.7ns (can represent exactly)
end
endmodule
// Testbench 3
`timescale 1us / 1ns
module tb3;
reg clk;
initial begin
clk = 0;
#10 clk = 1; // 10us delay (much longer!)
#5.7 clk = 0; // 5.7us
end
endmodule
7.3.2. Practical Applications
​
Application 1: Clock Generation with Precise Timing
Verilog
`timescale 1ns / 1ps
module multi_clock_system;
// System clock: 100 MHz (10ns period)
reg sys_clk;
parameter SYS_CLK_PERIOD = 10.0; // 10ns
initial begin
sys_clk = 0;
forever #(SYS_CLK_PERIOD/2) sys_clk = ~sys_clk;
end
// DDR clock: 800 MHz (1.25ns period)
reg ddr_clk;
parameter DDR_CLK_PERIOD = 1.25; // 1.25ns
initial begin
ddr_clk = 0;
forever #(DDR_CLK_PERIOD/2) ddr_clk = ~ddr_clk;
end
// USB clock: 48 MHz (20.833ns period)
reg usb_clk;
parameter USB_CLK_PERIOD = 20.833; // 20.833ns
initial begin
usb_clk = 0;
forever #(USB_CLK_PERIOD/2) usb_clk = ~usb_clk;
end
// UART clock: 1.8432 MHz (542.535ns period)
reg uart_clk;
parameter UART_CLK_PERIOD = 542.535;
initial begin
uart_clk = 0;
forever #(UART_CLK_PERIOD/2) uart_clk = ~uart_clk;
end
endmodule
Application 2: Setup and Hold Time Verification
Verilog
`timescale 1ns / 1ps
module timing_check_example;
reg clk;
reg data;
reg [7:0] capture;
// Clock: 100 MHz
initial begin
clk = 0;
forever #5 clk = ~clk;
end
// Timing parameters from datasheet
parameter T_SETUP = 2.5; // 2.5ns setup time required
parameter T_HOLD = 1.5; // 1.5ns hold time required
// Data changes with proper timing
initial begin
data = 0;
// Wait for clock edge
@(posedge clk);
// Change data with setup time margin
#(10 - T_SETUP - 0.5); // 0.5ns margin before setup requirement
data = 1;
// Hold data after clock edge
@(posedge clk);
#(T_HOLD + 0.3); // 0.3ns margin after hold requirement
data = 0;
end
// Capture data at clock edge
always @(posedge clk) begin
capture <= {capture[6:0], data};
end
// Timing checks using $setup and $hold
always @(posedge clk) begin
$setup(data, posedge clk, T_SETUP);
$hold(posedge clk, data, T_HOLD);
end
endmodule
Application 3: Protocol Timing Simulation
Verilog
`timescale 1ns / 1ps
module i2c_timing_tb;
reg scl, sda;
// I2C Standard Mode timing parameters (from spec)
parameter real T_LOW = 4700; // SCL low period (4.7us)
parameter real T_HIGH = 4000; // SCL high period (4.0us)
parameter real T_SU_STA = 4700; // START condition setup (4.7us)
parameter real T_HD_STA = 4000; // START condition hold (4.0us)
parameter real T_SU_STO = 4000; // STOP condition setup (4.0us)
parameter real T_BUF = 4700; // Bus free time (4.7us)
parameter real T_SU_DAT = 250; // Data setup time (250ns)
parameter real T_HD_DAT = 0; // Data hold time (0ns min)
// I2C START condition
task i2c_start;
begin
sda = 1;
scl = 1;
#T_SU_STA;
sda = 0; // SDA falls while SCL high
#T_HD_STA;
scl = 0;
end
endtask
// I2C STOP condition
task i2c_stop;
begin
sda = 0;
#T_LOW;
scl = 1;
#T_SU_STO;
sda = 1; // SDA rises while SCL high
#T_BUF;
end
endtask
// I2C write bit
task i2c_write_bit(input bit_val);
begin
sda = bit_val;
#T_SU_DAT; // Setup data before SCL rises
scl = 1;
#T_HIGH;
scl = 0;
#T_HD_DAT; // Hold data after SCL falls
end
endtask
// Test sequence
initial begin
scl = 1;
sda = 1;
#1000;
// Send START
i2c_start();
// Write address byte (0x50, write mode)
i2c_write_bit(0); // bit 7
i2c_write_bit(1); // bit 6
i2c_write_bit(0); // bit 5
i2c_write_bit(1); // bit 4
i2c_write_bit(0); // bit 3
i2c_write_bit(0); // bit 2
i2c_write_bit(0); // bit 1
i2c_write_bit(0); // bit 0 (write)
// Send STOP
i2c_stop();
$finish;
end
endmodule
Application 4: Gate-Level Timing Annotation
Verilog
`timescale 1ns / 1ps
module gate_level_example (
input wire a,
input wire b,
output wire y
);
wire and_out;
// Gate delays from technology library
and #(0.15, 0.18) u_and (and_out, a, b);
// Rise delay: 0.15ns, Fall delay: 0.18ns
not #(0.12, 0.10) u_not (y, and_out);
// Rise delay: 0.12ns, Fall delay: 0.10ns
endmodule
module gate_timing_tb;
reg a, b;
wire y;
gate_level_example dut (
.a(a),
.b(b),
.y(y)
);
initial begin
$dumpfile("timing.vcd");
$dumpvars(0, gate_timing_tb);
// Test vectors
a = 0; b = 0; #10;
a = 0; b = 1; #10;
a = 1; b = 0; #10;
a = 1; b = 1; #10; // Observe propagation delays
$finish;
end
endmodule
7.3.3. Timescale Scope and Rules
​
Rule 1: Timescale is File-Scoped
Verilog
// File: module_a.v
`timescale 1ns / 1ps
module module_a;
initial #10 $display("Module A: 10ns");
endmodule
// File: module_b.v
`timescale 1us / 1ns
module module_b;
initial #10 $display("Module B: 10us"); // Different timescale!
endmodule
// File: top.v
`timescale 1ns / 1ps
module top;
module_a inst_a(); // Uses its own 1ns timescale
module_b inst_b(); // Uses its own 1us timescale
initial #10 $display("Top: 10ns"); // Uses top's 1ns timescale
endmodule
Rule 2: Simulator Uses Most Precise Timescale
​
When multiple modules have different timescales, the simulator uses the finest precision:
Verilog
// Module 1: 1ns/1ps
// Module 2: 1ns/100ps
// Module 3: 1ns/1ns
// Simulator will use 1ps precision globally
Rule 3: Always Specify Timescale
Verilog
// Bad - no timescale specified
module no_timescale;
initial #10 $display("What unit is this?"); // Undefined!
endmodule
// Good - timescale always specified
`timescale 1ns / 1ps
module with_timescale;
initial #10 $display("This is 10ns"); // Clear!
endmodule
7.3.4. Choosing the Right Timescale
​
7.3.4.1. For Digital RTL Design (ASIC/FPGA)
Verilog
`timescale 1ns / 1ps
// Why?
// - 1ns unit matches typical clock periods (GHz range)
// - 1ps precision captures setup/hold times
// - Standard for most digital designs
7.3.4.2. For High-Speed Interfaces (SerDes, DDR, PCIe)
Verilog
`timescale 1ps / 1fs
// Why?
// - Multi-GHz clocks need picosecond accuracy
// - Jitter measurements require femtosecond precision
// - Critical timing margins in picoseconds
7.3.4.3. For Slow Peripherals (UART, I2C, SPI)
Verilog
`timescale 1us / 1ns
// Why?
// - Clock periods in microseconds
// - No need for sub-nanosecond precision
// - Faster simulation (fewer time steps)
7.3.4.4. For Mixed-Signal Simulation
Verilog
`timescale 1ns / 1ps
// Why?
// - Compromise between digital (ns) and analog (ps) domains
// - Compatible with most EDA tools
7.3.5. Best Practices for `timescale
​
7.3.5.1. Always Put Timescale at Top of File
Verilog
// Good practice
`timescale 1ns / 1ps
`include "definitions.vh"
module my_module (...);
// Module content
endmodule
7.3.5.2. Be Consistent Across Project
Verilog
// Create a standard timescale header
// File: project_timescale.vh
`timescale 1ns / 1ps
// Include in all files
// File: module1.v
`include "project_timescale.vh"
module module1 (...);
// File: module2.v
`include "project_timescale.vh"
module module2 (...);
7.3.5.3. Document Timescale Choice
Verilog
/**
* Timescale: 1ns / 1ps
* Rationale:
* - System clock: 100MHz (10ns period)
* - Setup time: 2.5ns (requires ns resolution)
* - Jitter spec: ±50ps (requires ps precision)
*/
`timescale 1ns / 1ps
module timing_critical_block (...);
7.3.5.4. Use Realistic Delays
Verilog
`timescale 1ns / 1ps
module realistic_delays;
reg clk;
// Good - realistic for 100MHz clock
initial begin
clk = 0;
forever #5 clk = ~clk; // 10ns period
end
// Avoid - unrealistic for digital design
initial begin
#0.001; // 1fs delay - too small for RTL
end
endmodule
7.3.6. Common Recommendations with `timescale
Case 1: Forgetting to Specify Timescale
Verilog
// No timescale directive!
module broken_module;
initial #10 $display("Time: %0t", $time);
// Behavior is tool-dependent!
endmodule
Solution: Always specify timescale, or use tool default carefully.
Case 2: Inconsistent Timescales Causing Confusion
Verilog
// File A: Uses microseconds
`timescale 1us / 1ns
module slow_module;
initial #10 $display("10us delay");
endmodule
// File B: Uses nanoseconds
`timescale 1ns / 1ps
module fast_module;
initial #10 $display("10ns delay"); // 1000x faster!
endmodule
Solution: Standardize timescale across project.
Case 3: Precision Too Coarse
Verilog
`timescale 1ns / 1ns
module precision_test;
reg data;
initial begin
data = 0;
#5.5 data = 1; // Rounds to 6ns!
#3.2 data = 0; // Rounds to 3ns!
end
// Expected: data = 1 at 5.5ns
// Actual: data = 1 at 6ns
endmodule
Solution: Use finer precision (1ps or 1fs).
