首页 > 技术知识 > 正文

前言

在提高模块通用性的设计中,也叫可重用性,有好多种方式,例如:

FPGA的设计艺术(13)使用generate语句构建可重用的逻辑设计

FPGA的设计艺术(14)使用函数和任务提升逻辑的可重用性

FPGA的设计艺术(12)使用parameter构建可重用的逻辑设计

这些对技能的灵活应用,会让你的设计更加的游刃有余,当然,本篇想补充一个,编译预处理语句。

这是HDL中的一个不可或缺的分支,地位很高,无论是在仿真还是在设计中,灵活运行能极大方便你的设计与验证。

下面一起来看看。

编译预处理语句

编译预处理语句在大中型设计中比较常见,且今后也会进场遇到,它的应用能提高逻辑模块的可重用性,增强代码的可读性,它的特征是以符号:

`

开头。

例如最常见的:

`define CNT_LENGTH `include”pipelined_multiplier.v” `ifdef `else `endif

等等。

下面我们具体谈谈,结合例子,理解并实践。

条件编译

所谓的条件编译,就是上面的:

有如下几种形式:

(1)`ifdef 宏名(标识符) 程序段1 `else 程序段2 `endif (2)`ifdef宏名(标识符) 程序段1    `endif

这种语句十分好用,很多时候比generate if更好用,例如我们的设计有很多功能模块,我们固然要将这些功能模块组合到一起,像搭积木一样,实现一个大型设计。

这势必导致综合,实现等过程时间过程,如果我们仅仅需要关注某一些模块,或者让某一些模块参与编译,那么我们就可以使用条件编译语句。

屏蔽了某些不必要的模块,做成的版本叫做小版本,这在调试的时候很重要,FPGA的开发,大型设计的编译需要十多个甚至更多时间,那么我们的调试版本制作就可以根据需要取舍一些模块,调试完成后,可以恢复,这就可以利用条件编译完成。

条件编译的实现,首先定义一个条件编译标志:

`define TX `define RX `define SUM //…

在代码的主题部分,我们可以这样使用:

`ifdef TX //定义变量 //例化模块 //或编写此功能块的逻辑 `endif `ifdef RX //定义变量 //例化模块 //或编写此功能块的逻辑 `endif `ifdef SUM //定义变量 //例化模块 //或编写此功能块的逻辑 `endif

当然,也可以利用它在仿真中发挥作用:

`ifdef SIMULINK_EN integer cur_state_sw; always@(*) begin case(cur_state) IDLE : cur_state_sw = “IDLE”; INIT: cur_state_sw = “INIT”; TRIG: cur_state_sw = “TRIG”; default: cur_state_sw = “IDLE”; endcase end `endif

这个例子想说明的是,当预定义了

`define SIMULINK_EN

后,你就可以定义一些,专门用于仿真的东西,例如上例中的状态值,当运行仿真的时候,我们可以在仿真波形中以字母的形式现实状态机,这样就不用盯着当前状态是某个值,1.,2,3,…,一点也不直观。

//或者 `ifdef SIM parameter BEAM_LENGTH = 256; parameter CNT_COUNT = 128; //…. `else parameter BEAM_LENGTH = 256565; parameter CNT_COUNT = 128125; `endif

这个例子说明的是,当我们的实际参数值比较大时,仿真会浪费时间,且不易观察,我们可以使用小的数值来仿真,观察趋势等等。 而又不想改数字,该数字之后,后面容易遗忘,而使用:define定义一个宏,是最省事的,也是很专业的一种做法。

还有一些有趣的例子: 例如模块需不需要某些变量的,例如复位等:

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

对于条件编译也有一些变体,用法相反而已:

module tb; initial begin `ifndef MACRO1 $display (“This is MACRO1”); `elsif MACRO2 $display (“This is MACRO2”); `endif end endmodule

意思是如果你没定义某个宏,该语句就会参与编译。

文件包含

文件包含编译预处理指令也十分常用,特别在大型仿真平台搭建中,使用文件包含指令可以十分轻松调用其他模块的内容,而不需要让一个模块看起来十分臃肿。

在包含语句的使用中,不一定非要包含一个模块,还可以或常常包含一个文件,这个文件中定义了一些参数或者任意或函数等,供当前文件使用。

其等效关系如下: FPGA的设计艺术(24)强大的编译预处理指令

上图使用了

`include “file2.v”

那么a就和c等价。

`include “versatile_counter_defines.v” `define LFSR_LENGTH `CNT_LENGTH `include “lfsr_polynom.v”

后面大家可以在实践中去尝试,相信有一定代码量之后,也会常常看到这种设计。

猜你喜欢