首页 > 技术文章 > 【FPGA篇章六】FPGA编译向导:详解编译预处理功能

streetlive 2020-04-06 18:32 原文

欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章

 

 

Verilog HDL语言和C语言一样也提供了编译预处理功能。

Verilog HDL允许在程序中使用特殊的编译预处理语句。

在编译时,通常先对这些特殊语句进行“预处理”,然后再将预处理的结果和源程序一起进行编译。

预处理命令以符号“`”开头(注意,“`”不是单引号,叫反单引号,在键盘左上角数字1的左边),以区别于其他语句。

 

1 宏定义 `define
  `define语句用来将一个简单的名字或标志符(或称为宏名)来代表一个复杂的名字或字符串,其一般形式为:

    define 标志符(宏名) 字符串

  在程序中,引用宏的方法是在宏名前面加上符号“`”。

 

  宏定义主要可以起到两个作用:

    (1)用一个有意义的标识符取代程序中反复出现的含义不明显的字符串。例如:

1 `define  WORDSIZE   8
2 reg[ `WORDSIZE : 1 ]  data;    
3 //这相当于定义 reg[8:1] data;

    (2)用一个较短的标识符代替反复出现的较长的字符串。例如:

 1  `define  sum1  ina+inb+inc+ind
 2 
 3  module calculate( out1,out2,ina,inb,inc,ind,ine);
 4    input ina,inb,inc,ind,ine;
 5    output[2:0]out1,out2;
 6    wire ina,inb,inc,ind,ine;
 7    reg[2:0]out1,out2;
 8 
 9    always@(ina or inb or inc or ine)
10     begin
11        out1=`sum1+ine;
12        out2=`sum1-ine;
13      end
14  endmodule

 

2 文件包含语句 `include

  使用Verilog HDL设计数字系统时,一个设计可能包含很多模块,而每个模块都单独存为一个文件。

  当顶层模块调用子模块时,就需要到相应的文件中寻找,文件包含的作用就是指明这些文件的位置

  也可以将宏定义、任务或者函数等语句写在单独的文件中,通过文件包含供其他模块调用。

  `include是文件包含语句,它可将一个文件全部包含到另一个文件中。其一般形式为:

  `include “文件名”`

  例用 `include 语句设计的16位加法器:

 1  //addr.v文件的代码为:
 2     module addr(cout,sum,a,b,cin);
 3        parameter  size =16;
 4        output cout;
 5        output[size-1:0]  sum;
 6        input cin;
 7        input[size-1:0] a, b; 
 8 
 9        assign {cout,sum} = a+b+cin;
10 
11     endmodule
12 
13 //调用文件addr.v中模块addr完成16位加法器
14 `include "addr.v"
15     module addr16(cout,sum,a,b,cin);
16        parameter MySize =16; 
17        output cout;
18        output[MySize-1:0]  sum;
19        input[MySize-1:0]  a, b;
20        input cin;
21 
22        addr #(MySize)   myAddr(cout,sum,a,b,cin);
23 
24     endmodule

 

3 条件编译指令 `ifdef `else `endif

  根据环境需要对一部分代码有选择地进行编译。

  条件编译有两种表达形式:

 1 // 第一种形式:
 2   `ifdef  宏名
 3        程序段
 4   `endif
 5 
 6  //第二种形式
 7  `ifdef   宏名 
 8        程序段1
 9  `else
10        程序段2
11  `endif
 1 `define sum  a+b
 2 module condition_compile(out,a,b,c); 
 3  output[2:0] out;
 4  input a,b,c;
 5 
 6  `ifdef sum 
 7       assign out=sum+c;
 8  `else
 9       assign out=a+c;
10 `endif
11 
12 endmodule
13 
14 //在上面的例子中,因为定义了“`define sum”,
15 //所以程序执行“assign out=a+b+c;” 

 

4 时间尺度 `timescale

  `timescale语句用于定义模块的时间单位和时间精度,其使用格式如下:

  ​  `timescale 时间单位/时间精度

  用于时间单位和时间精度的数字只能是1、10和100。 其中用来表示时间度量的符号有:

​     s、ms、μs 、ns、ps和fs 。

  时间精度是指模块仿真时间和延时的精确程度,比如定义时间精度为10ns,那么程序中所有的延时至多能精确到10ns。

1 `timescale 100ns/10ns
2   …………
3      always @(din)
4        fork
5             #3  dout1 = din;        //延时300ns
6             #3.1  dout2 = din;     //延时310ns
7         #3.14  dout3 = din;   //延时310ns   
8        join

 

小结

  宏定义字符串引用时,不要忘记要用“`”引导。这与C语言不同。
  include等编译预处理也必须用“`”引导,而不是与C语言一样用“#”引导或不需要引导符。
  合理地使用条件编译和条件执行预处理可以使测试程序适应不同的编译环境,也可以把不同的测试过程编写到一个统一的测试程序中去,简化测试的过程,对于复杂设计的验证模块的编写很有实用价值。

推荐阅读