Verilog中的`ifdef 条件编译语句

https://zhuanlan.zhihu.com/p/166147511

 

前言

`ifdef条件编译语句在逻辑设计中还是很常见的,但也常见一些滥用的情况,这应该避免。 应该在什么情况下使用呢?

例如:一部分代码可能有时候用,有时候不用,为了避免全部编译占用资源,可以使用条件编译语句。 下面正式介绍其语法。

正文

语法

// Style #1: Only single `ifdef
`ifdef <FLAG>
 // Statements
`endif

// Style #2: `ifdef with `else part
`ifdef <FLAG>
 // Statements
`else
 // Statements
`endif

// Style #3: `ifdef with additional ifdefs
`ifdef <FLAG1>
 // Statements
`elsif <FLAG2>
 // Statements
`elsif <FLAG3>
 // Statements
`else
 // Statements
`endif

 条件编译可以通过Verilog的  `ifdef `ifndef 关键字来实现。
 这些关键字可以出现在设计中的任何地方,并且可以相互嵌套。 
 它通常和预编译指令`define配套使用如果使用 `define定义了
 称为`FLAG`的宏,那么关键字`ifdef会告诉编译器包含这段代码直到下一个`else或`endif关键字`ifndef只是告诉编译器,如果给定的名为FLAG的宏没有使用
`define指令定义,则将这段代码包含在下一个`else "或`endif之前。

示例

module my_design (input clk, d,
`ifdef INCLUDE_RSTN
                  input rstn,
`endif
                  output reg q);

  always @ (posedge clk) begin
`ifdef INCLUDE_RSTN
    if (!rstn) begin
      q <= 0;
    end else
`endif
    begin
      q <= d;
    end
  end
endmodule

Testbench文件

module tb;
  reg clk, d, rstn;
  wire q;
  reg [3:0] delay;

  my_design u0 ( .clk(clk), .d(d),
`ifdef INCLUDE_RSTN
                .rstn(rstn),
`endif
                .q(q));

  always #10 clk = ~clk;

  initial begin

    {d, rstn, clk} = 0;

 #20 rstn = 1;
 
    for (integer i = 0 ; i < 20; i=i+1) begin
      delay = $random;
      #(delay) d = $random;
    end

    #20 $finish;
  end

endmodule

请注意, 默认情况下, rstn 不会在编译设计时被包含, 因此它不会出现在 port 列表中。但是, 如果在任何属于编译文件列表的 Verilog 文件中定义了名为 INCLUDE_RSTN 的宏, 或者通过命令行传递给编译器, rstn 就会在编译过程中被包括在内, 设计也将拥有它。

下面我们通过vivado平台编译看下: 默认情况下:

定了了宏INCLUDE_RSTN的情况下:

进一步证明了其用途。

仿真看下:

在默认情况下,没有定义宏INCLUDE_RSTN ,也就没有复位。

可以看到由于没有复位,所以q在初始阶段为X。

posted @ 2022-03-04 09:48  will_w  阅读(1068)  评论(0编辑  收藏  举报