SystemVerilog 提供大量编译器指令来指导代码进程,比如`define、`ifdef、`elsif、`ifndef、`timescale、`default_nettype等。
它们前面是 ( ` ) 字符(重音字符)(不要将其与撇号字符 ( ' ) 混淆)。
`define
`define 是使用最广泛的编译器指令之一,它是一个文本替换宏。它可以为常用的文本片段提供有意义的名称。例如,在整个描述中重复使用常量的情况下,文本宏很有用,因为如果需要更改常量的值,则只需更改源描述中的一个位置。例如:
`define widebus 16'hFFFF
并在整个源描述中使用 `widebus。如果以后widebus的定义改成32'hFFFF_FFFF,只需要改一行: `define widebus 32'hFFFF_FFFF
新的定义将应用到源代码中。
允许重新定义文本宏;编译器以遇到的最新定义为准。
看一个例子,展示了许多不同的方式来使用 `define :
`define busWidth 31 // logic [0:`buswidth] bus;
`define delay #10 // forever `delay clk = !clk;
`define nandD(dly) nand #dly // `nandD(10) n1(o1, i1, i2); //expands to - nand #10 n1(o1, i1, i2);
`define comment $display("this is a long ”, \
“comment that spans multiple lines"); //定义一个跨越两行的宏文本。为了做到这一点,在文本的下一行行之前使用“\”(反斜杠)
//使用:initial `comment
`define disp(x,y) initial $display(x, y); // `disp("GoX"," GoY")
`define tdisp(a = 5, b = 10, c) initial $display(a,,b,,c); //`tdisp( , , 15) //5 10 15
`define conditional(a,b) (a > b ? a : b) // assign bus = `conditional(20,10); //=(20 > 10 ? 20 : 5)
`define mF(filename) `"/springer/mydir/filename`"
`undef and `undefineall
如果先前由 `define 宏定义,则指令 `undef 取消定义指定的文本宏。例如 `undef delay
`undefineall 将取消定义以前由 `define 指令定义的所有文本宏。它可以出现在源码中的任何位置,并且不带任何参数。
`ifdef, `else, `elsif, `endif, and `ifndef
模板:
`ifdef text_macro_identifier (OR `ifndef text_macro_identifier)
<lines of code>
`elsif text_macro_identifier
<lines of code>
`endif
请注意,可以在模块中声明 text_macro_identifier。也可以在命令行上将它们声明为编译类型选项(如下所述)。让我们看一个例子:
`define true
`define false
`define behavioral
module directive;
wire a, b, c;
initial begin
`ifdef true
$display("TRUE");
`ifdef false
$display("NESTED FALSE after TRUE");
`endif
`else
$display("NONE");
`endif
end
`ifndef behavioral //if 'behavioral' is -not- defined
and a1 (a, b, c);
initial $display("GATE LEVEL");
`else
assign a = b & c;
initial $display("BEHAVIORAL");
`endif
endmodule
仿真结果:
Compiler version S-2021.09; Runtime version S-2021.09; Aug 24 09:59 2022
TRUE
NESTED FALSE after TRUE
BEHAVIORAL
V C S S i m u l a t i o n R e p o r t
我们已经声明了三个`define,即`define true、`define false和`define behavior。注意这些是如何声明的,只是在 `define 关键字之后给出了一个 text_macro_name。这不同于做文本替换: `define true 1'b1
然后在代码中,我们使用`ifdef true 选择一个分支,并使用嵌套的`ifdef false 选择一个额外的分支。这两个嵌套的 `ifdef 被执行,如仿真中通过 $display 所示。
我们还在代码中使用`ifndef(即,如果未定义)在行为代码和结构代码之间进行选择。 `ifndef 行为意味着如果没有定义“behavioral”,则选择与 `ifndef 关联的分支。在我们的例子中,我们确实定义了“behavioral”,因此 `else 分支被执行。
请注意,如前所述,不必在代码本身中有 `defines。可以避免在代码中声明所有三个 `defines,编译指令上提供这些定义。例如,可以在命令行上执行以下操作:
+define+true
+define+false
+define+true+false+behavioral //all three with one +define+
在命令行上提供这些`define的优势就是不必更改源码。可以有条件地从命令行本身选择编译代码。
`timescale
这是一个广泛使用的编译器指令,主要在测试平台级别。它指定其后设计(和#<delay>)的时间单位和时间精度。时间单位是时间值的测量单位,例如仿真时长和延迟时长。
语法: `timescale time_unit / time_precision
time_unit 参数指定时间和延迟的测量单位,time_precision 参数指定延迟在用于仿真之前如何四舍五入。例如:`timescale 1 ns/1 ps
在你的代码中有:#1.123ns a = 0
仿真器会将 1.123 时间单位转换为 1123 时间刻度,即将 1.123 ns 转换为 1123 ps。
`timescale 作为编译器指令本质上是全局的。一旦定义,它将跨越文件/模块边界。
假设你有三个文件,TS1.v、TS2.v 和 TS3.v:
TS1.v
`timescale 1 ns/1 ns
module TS1 (…);
TS2.v
`timescale 10 ns/1 ns
module TS2(…);
TS3.v
//NO TIMESCALE
module TS3(…);
以下是根据编译顺序选择 `timescale 的结果:
verilog TS1.v TS2.v TS3.v //TS3 timescale is 10 ns/1 ns.
verilog TS2.v TS1.v TS3.v //TS3 timescale is 1 ns/1 ns. TS2也变成1ns/1ns?我觉得是,因为`timescale默认是全局的。
verilog TS3.v TS1.v TS2.v //Compile ERROR – TS3 has no timescale. 采用仿真器默认值
`default_nettype
设置默认线网类型。我们知道,默认情况下,线网(net)类型是“wire”。但是可以使用 `default_nettype 编译指令覆盖默认线网(net)类型:
`default_nettype default_nettype_value
其中 default_nettype_value 可以是任何线网类型,例如 wire、tri、tri0、tri1、wand、triand、wor、trior、trireg、uwire 或“none”。
当它设置为“none”时,所有网线网必须明确声明(否则会得到一个error)。该指令必须在模块之外定义
允许使用多个 `default_ nettype。最后一次出现控制线网的类型。 `resetall 指令将指令重置为其默认值。
`resetall
`resetall 将所有现有的编译器指令重置为默认值。在模块(任何设计元素)之前,使用`resetall 指令来重置所有先前定义的编译器指令。这确保只有编译特定源文件所需的指令才处于有效状态。请注意,`define 和 `include 没有默认值,因此不受`resetall 的影响。
标签:定义,timescale,SV,编译器,指令,Directives,display,define From: https://www.cnblogs.com/fuqiangblog/p/16622366.html