小言_互联网的博客

Verilog语法之条件编译指令`ifdef, `ifndef,`else, `elsif, `endif

600人阅读  评论(0)

0、前言

        一般情况下,C语言中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译(conditional compile)。条件编译允许只编译源文件中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销,并提高程序的效率,可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。

        Verilog的编译和C语言的编译二者自然不可同日而语,具体到FPGA的开发,其条件编译可以通俗的理解为,根据条件选择性地将指定部分综合为电路,而未被指定部分则不综合成电路,这可以有效地减少电路面积和提高代码的复用性和灵活性。


1、一个小例子

        现在老板让我开发一个模块,功能是要能实现两个4bit输入的与、或、异或运算,但这三种运算不需要同时满足,也就是说在该模块的某次使用中或被调用中可能是使用或运算,也可能是使用与运算,具体是什么说不清楚,得看老板心情。

        这还不简单?针对与、或、异或运算写三条语句,再给它加个选择器就完事了,就像这样:


  
  1. module op_test(
  2. input [3:0] in1,
  3. input [3:0] in2,
  4. input [1:0] sel,
  5. output reg [3:0] out
  6. );
  7. wire [ 3: 0] out_and;
  8. wire [ 3: 0] out_or;
  9. wire [ 3: 0] out_xor;
  10. assign out_and = in1 & in2;
  11. assign out_or = in1 | in2;
  12. assign out_xor = in1 ^ in2;
  13. always@(*) begin
  14. case(sel)
  15. 2'd0: out = out_and;
  16. 2'd1: out = out_or;
  17. 2'd2: out = out_xor;
  18. default: out = out_and;
  19. endcase
  20. end
  21. endmodule

       

        用vivado分析出来的电路是这样的:

        嗯,完美满足老板要求。嘻嘻。

        不料老板看了代码后,对着我劈头盖脸就是一顿臭骂:说了一次只会做一种运算,你给我弄3个运算模块干嘛?做或运算的时候,异或运算和与运算模块就站着看戏?节约资源懂不懂伐?性价比懂不懂伐?钞票懂不懂伐? 

        虽然我内心立马条件反射般地对老板竖了个中指,但是仔细想想老板说的话也确实有道理,所以只好再找找其他办法。

        找了半天还真给我找着了(不愧是我),这就是Verilog语法中的条件编译指令`ifdef, `ifndef,`else, `elsif, `endif。


2、条件编译指令

        条件编译指令可以根据指定条件来生成对应的电路,这可以减少电路面积并提高代码的复用性。

2.1、 `ifdef 的使用  

         `ifdef 需要搭配 `endif 使用,其使用方法为:


  
  1. `ifdef <define_name>
  2. <statements>;
  3. `endif

        比如上面的例子(采用与运算时):


  
  1. `define OP_AND //指定条件为与运算,标识符建议使用大写
  2. //`define OP_OR //指定条件为或运算,标识符建议使用大写
  3. //`define OP_XOR //指定条件为异或运算,标识符建议使用大写
  4. module op_test(
  5. input [ 3: 0] in1,
  6. input [ 3: 0] in2,
  7. output [ 3: 0] out
  8. );
  9. `ifdef OP_AND
  10. assign out = in1 & in2;
  11. `endif
  12. `ifdef OP_OR
  13. assign out = in1 | in2;
  14. `endif
  15. `ifdef OP_XOR
  16. assign out = in1 ^ in2;
  17. `endif
  18. endmodule

        用vivado分析出来的电路是这样的: 

        可以看到,在希望进行与运算时,综合出来的电路已经只有与运算模块了,异或运算模块、或预算模块和选择器模块都没有被综合出来,这有效地减少了电路面积。

        下一次,如果需要进行或运算,则只需要把  `define    OP_AND    这一句注释掉,再把这一句  `define    OP_OR  给有效化,此时就会综合出这样的电路(仅有或运算模块):

        异或运算模块的使用则不赘述。


2.2、 `else 与 `elsif 的使用

        在2.1节为了实现3个模块的条件编译,使用了三个`ifdef···`endif 块,这使得代码看起来很臃肿。就像你通常会使用 else if 和 else 来搭配 if 语句使用一样,你也可以使用  `else 与 `elsif 来搭配 `ifdef 使用。

        `else 与 `elsif 的使用方法:


  
  1. `ifdef <define_name>
  2. <statements>;
  3. `elsif <define_name>
  4. <statements>;
  5. `else
  6. <statements>;
  7. `endif

        所以,上面的例子可以改成这样的形式(采用与运算时):


  
  1. `define OP_AND //指定条件为与运算,标识符建议使用大写
  2. //`define OP_OR //指定条件为或运算,标识符建议使用大写
  3. //`define OP_XOR //指定条件为异或运算,标识符建议使用大写
  4. module op_test(
  5. input [ 3: 0] in1,
  6. input [ 3: 0] in2,
  7. output [ 3: 0] out
  8. );
  9. `ifdef OP_AND
  10. assign out = in1 & in2;
  11. `elsif OP_OR
  12. assign out = in1 | in2;
  13. ` else
  14. assign out = in1 ^ in2;
  15. `endif
  16. endmodule

2.3、 `ifndef 的使用

        `ifndef 的作用与 `ifdef 是相反的----当其后的标识符未被定义时,则编译后续的代码段,Verilog语法:


  
  1. `ifndef <define_name>
  2. <statements>;
  3. `endif

        举个例子,通过标识符 OP_OR 实现功能:如果OP_OR 未被定义,则实现两个输入的或运算;如果 OP_OR被定义,则实现两个输入的与运算。

       

        不实现或运算(即实现与预算)情况的代码如下:


  
  1. `define OP_OR //指定条件为或运算,标识符建议使用大写
  2. module op_test(
  3. input [ 3: 0] in1,
  4. input [ 3: 0] in2,
  5. output [ 3: 0] out
  6. );
  7. `ifndef OP_OR
  8. assign out = in1 | in2;
  9. ` else
  10. assign out = in1 & in2;
  11. `endif
  12. endmodule

        此时,定义了  OP_OR ,所以会执行第二句:assign out = in1 & in2;   

        此时综合出来的电路:

        稍微修改一下,实现或运算情况的代码如下(仅注释掉了 `define    OP_OR):


  
  1. //`define OP_OR //指定条件为或运算,标识符建议使用大写
  2. module op_test(
  3. input [ 3: 0] in1,
  4. input [ 3: 0] in2,
  5. output [ 3: 0] out
  6. );
  7. `ifndef OP_OR
  8. assign out = in1 | in2;
  9. ` else
  10. assign out = in1 & in2;
  11. `endif
  12. endmodule

        此时,未定义  OP_OR ,所以会执行第一句:assign out = in1 | in2;   

        综合出来的电路:


转载:https://blog.csdn.net/wuzhikaidetb/article/details/128271376
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场