Verilog Timescales an jedem Scope verstehen und ausgeben
Standard-Timescale
Obwohl Verilog-Module erwartungsgemäß einen Timescale vor dem Modul definiert haben sollten, können Simulatoren einen Standard-Timescale einfügen. Der tatsächliche Timescale, der an einem beliebigen Scope in einer elaborierten Verilog-Hierarchie angewendet wird, kann mit dem System-Task $printtimescale ausgegeben werden, der den Scope als Argument akzeptiert.
module tb;
initial begin
// Timescale dieses Moduls ausgeben
$printtimescale(tb);
// $printtimescale($root);
end
endmodule
Man sieht, dass der Simulator am Ende einen 1ns/1ns-Timescale-Wert angewendet hat, obwohl keine Timescale-Direktive vor diesem Modul platziert wurde.
Simulationslog:
xcelium> run Time scale of (tb) is 1ns / 1ns xmsim: *W,RNQUIE: Simulation is complete.
Standard-Timescale-Scope
Standardmäßig wird eine Timescale-Direktive, die in einer Datei platziert ist, auf alle Module angewendet, die der Direktive folgen, bis die Definition einer anderen Timescale-Direktive erfolgt.
`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
Im obigen Beispiel enden tb und alu mit einem Timescale von 1ns/1ns, während des einen Timescale von 1ns/10ps erhält, wegen der Platzierung der Direktive vor der Moduldefinition von des.
Simulationslog:
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 zwischen Verilog-Dateien
Andere Dateien können mit einer `include-Direktive in die aktuelle Datei eingebunden werden, was eine Präprozessor-Direktive ist und den Compiler veranlasst, den Inhalt der eingebundenen Datei vor der Kompilierung einzufügen. Dies ist also äquivalent zum einfachen Einfügen des gesamten Inhalts der anderen Datei in diese Hauptdatei.
// 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
Man sieht, dass die Ergebnisse genau dieselben sind wie im vorherigen Beispiel. alu erhält einen Timescale von 1ns/1ps, weil es die letzte Direktive war, die gültig blieb, bis der Compiler die alu-Definition fand, obwohl es in einer anderen Datei platziert war. des erhält einen Timescale von 1ns/10ps, weil die Direktive vor seiner Definition ersetzt wurde.
Simulationslog:
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.
Dateien vertauschen kann Timescale ändern
Die Reihenfolge der Einbindung von Dateien spielt eine wichtige Rolle bei der Neudefinition von Timescale-Direktiven, was im folgenden Beispiel deutlich wird.
// 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
// HINWEIS! Reihenfolge der Einbindung vertauscht
`include "file_des.v"
`include "file_alu.v"
// file_alu.v
module alu;
endmodule
// file_des.v
`timescale 1ns/10ps
module des;
endmodule
Man sieht, dass das Modul alu jetzt einen Timescale von 1ns/10ps erhält.
Simulationslog:
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.
Dies ist einer der Gründe, eine Timescale-Direktive am Anfang von Dateien zu haben, damit alle Module in dieser Datei den korrekten Timescale annehmen, unabhängig von der Datei-Einbindung.
Dieser Ansatz kann jedoch erschweren, mit einer anderen Timescale-Präzision (Wert nach dem Schrägstrich) zu kompilieren, ohne jede Datei zu ändern. Viele Compiler und Simulatoren bieten auch eine Option an, Standard-Timescale-Werte zu überschreiben, die auf alle Module angewendet werden.
Verilog
- Verilog meistern: Komplettes Tutorial für digitales Schaltungsdesign
- Verilog Concatenation meistern: Praktischer Leitfaden
- Verilog Assignments verstehen: Typen, Syntax und Best Practices
- Verilog Blocking vs. Non-Blocking: Wichtige Unterschiede erklärt
- Verilog Functions meistern für effizientes RTL-Design
- Verilog Tasks verstehen: Functions vs. Tasks, Syntax und Verwendung
- Verilogs hierarchischen Referenz-Gültigkeitsbereich meistern: Namenskonflikte in Modulen und Blöcken vermeiden
- Verilog Clock Generator: Design & Implementierungsleitfaden
- Verilog Math Functions meistern für effizientes Hardware-Design
- Verilog $timeformat meistern: Präzision und Anzeigesteuerung