Default timescale
Although Verilog modules are expected to have a timescale defined before the module, simulators may insert a default timescale. The actual timescale that gets applied at any scope in a Verilog elaborated hierarchy can be printed using the system task $printtimescale
which accepts the scope as an argument.
module tb;
initial begin
// Print timescale of this module
$printtimescale(tb);
// $printtimescale($root);
end
endmodule
See that even though a timescale directive was not placed before this module, simulator ended up applying a 1ns/1ns timescale value.
xcelium> run
Time scale of (tb) is 1ns / 1ns
xmsim: *W,RNQUIE: Simulation is complete.
Standard timescale scope
By default a timescale directive placed in a file is applied to all modules that follow the directive until the definition of another timescale directive.
`timescale 1ns/1ps
module tb;
des m_des();
alu m_alu();
initial begin
$printtimescale(tb);
$printtimescale(tb.m_alu);
$printtimescale(tb.m_des);
end
endmodule
module alu;
endmodule
`timescale 1ns/10ps
module des;
endmodule
In the above example, tb and alu end up with a timescale of 1ns/1ns while des gets a timescale of 1ns/10ps because of the placement of directive before module definition of des
xcelium> run Time scale of (tb) is 1ns / 1ps Time scale of (tb.m_alu) is 1ns / 1ps Time scale of (tb.m_des) is 1ns / 10ps xmsim: *W,RNQUIE: Simulation is complete.
Scope between Verilog files
Other files can be included into the current file using a `include
directive which is a pre-processor directive and makes the compiler place contents of the included file before compilation. So, this is equivalent to simply pasting the entire contents of the other file in this main file.
// main.v
`timescale 1ns/1ps
module tb;
des m_des();
alu m_alu();
initial begin
$printtimescale(tb);
$printtimescale(tb.m_alu);
$printtimescale(tb.m_des);
end
endmodule
`include "file_alu.v"
`include "file_des.v"
// file_alu.v
module alu;
endmodule
// file_des.v
`timescale 1ns/10ps
module des;
endmodule
See that results are exactly the same as in previous example. alu gets a timescale of 1ns/1ps because it was last directive that stayed valid until the compiler found alu definition inspite of placing it in a different file. des gets a timescale of 1ns/10ps because the directive was replaced before its definition.
xcelium> run
Time scale of (tb) is 1ns / 1ps
Time scale of (tb.m_alu) is 1ns / 1ps
Time scale of (tb.m_des) is 1ns / 10ps
xmsim: *W,RNQUIE: Simulation is complete.
Swapping files can change timescale
Order of inclusion of files play an important role in redefinition of timescale directives, which is evident in the example below.
// main.v
`timescale 1ns/1ps
module tb;
des m_des();
alu m_alu();
initial begin
$printtimescale(tb);
$printtimescale(tb.m_alu);
$printtimescale(tb.m_des);
end
endmodule
// NOTE! Swapped order of inclusion
`include "file_des.v"
`include "file_alu.v"
// file_alu.v
module alu;
endmodule
// file_des.v
`timescale 1ns/10ps
module des;
endmodule
See that the module alu now gets a timescale of 1ns/10ps.
xcelium> run
Time scale of (tb) is 1ns / 1ps
Time scale of (tb.m_alu) is 1ns / 10ps
Time scale of (tb.m_des) is 1ns / 10ps
xmsim: *W,RNQUIE: Simulation is complete.
This is one of the reasons for having a timescale directive at the top of files so that all modules in that file assume the correct timescale irrespective of file inclusion.
However this approach may make it difficult to compile with a different timescale precision (value following the oblique) without altering each file. Many compilers and simulators also provide an option to override default timescale values which will be applied to all modules.