当前位置: 首页 > news >正文

【Verilog】系统任务和编译指令

系统任务和编译指令

  • 一、系统任务
    • 1. 输出类任务: $display $write $strobe $monitor
    • 2. 仿真控制类: $stop $finish
    • 3. 仿真时间: $time $stime $realtime
    • 4. 命令行传参: $test\$plusargs $value\$plusargs
  • 二、编译指令
    • 1. 宏定义:`define
    • 2. 条件编译:`ifdef
    • 3. 文件包含:`include
    • 4. `default_nettype
    • 5. `resetall
    • 6. `celldefine

Verilog中的两个特殊概念:系统任务和编译指令。


一、系统任务


Verilog 为某些常用操作提供了标准的系统任务(也称系统函数), 这些操作包括屏幕显示 、线网值动态监视 、 暂停和结束仿真等。所有的系统任务都具有$<keyword>的形式。

系统任务主要用于‌仿真调试与控制‌,而非综合生成硬件电路。


1. 输出类任务: $display $write $strobe $monitor


$display 的使用方法和 C 语言中的 printf 函数非常类似,可以直接打印字符串,也可以在字符串中指定变量的格式对相关变量进行打印。

$display("This is a test."); 					//直接打印字符串
$display("This is a test number: %b.", num);	//打印变量 num 为二进制格式

如果没有指定变量的显示格式,变量值会根据在字符串的位置显示出来,相当于参与了字符串连接。例如:

$display("This is a test number: ", num, "!!!");

常用的输出格式:

在这里插入图片描述

在输出浮点数的时候,还可以指定精度:


module top;initial beginreal num = 123.456789;$display("Default precision: %f", num);  // 默认6位小数$display("2 decimal places: %.2f", num); // 2位小数$display("5 decimal places: %.5f", num); // 5位小数end
endmodule

此外,还可以使用转义字符显示特殊字符:

在这里插入图片描述


$wirte 使用方法与 $display 完全一样,只是前者会在每次显示信息完毕后不会自动换行,后者会自动换行。

当输出后不需要换行时,可以使用显示任务 $write


$strobe 的使用方法与 $display 一致,但打印信息的时间和 $display 有所差异。

当许多语句与 $display 任务在同一时间内执行时,这些语句和 $display 的执行顺序是不确定的,一般按照程序的顺序结构执行。

$strobe 则是在其他语句执行完毕之后,才执行显示任务。

示例1:

reg [3:0]  a ;initial begina = 1 ;#1 ;a <= a + 1 ;//第一次显示$display("$display excuting result: %d.", a);$strobe("$strobe excuting result: %d.", a);#1 ;$display();//第二次显示$display("$display excuting result: %d.", a);$strobe("$strobe excuting result: %d.", a);
end

执行结果如下:

在这里插入图片描述

执行第一次显示任务时,非阻塞赋值与 $display 同时执行,$display 显示赋值之前的变量值,而 $strobe 显示赋值之后的变量值。

示例2:

integer  i ;initial beginfor (i=0; i<4; i=i+1) begin$display("Run times of $display: %d.", i);$strobe("Run times of $strobe: %d.", i);end
end

显示结果如下:

在这里插入图片描述

$display 按照程序结构,执行显示操作 4 次。而此循环语句是在 0 时刻执行的,所以 $strobe 显示的变量值是循环结束时变量的结果,即 i=4 退出循环后 $strobe 才会执行。


$monitor 为监测任务,用于变量的持续监测。只要变量发生了变化,$monitor 就会打印显示出对应的信息。

reg [3:0]    cnt ;
initial begincnt = 3 ;forever begin# 5 ;if (cnt<7) cnt = cnt + 1 ;end
endinitial begin$monitor("Counter change to value %d at the time %t.", cnt, $time);
end

显示的内容如下:

在这里插入图片描述


2. 仿真控制类: $stop $finish


在这里插入图片描述

$finish 是结束本次仿,$stop 是暂停当前的仿真。仿真暂停后通过 Verilog 仿真工具或命令行还可以使仿真继续进行,而结束仿真后仿真无论如何也不能再进行

示例:

initial beginforever begin#100;if ($time >= 10000)  $finish(0) ;//if ($time >= 10000)  $finish(1) ;//if ($time >= 10000)  $finish(2) ;end
end

$finish(0):仿真退出时不打印任何信息。

$finish(1):仿真退出时打印仿真时间(单位是ps)和 $finish 所在的行信息

在这里插入图片描述

$finish(2):仿真退出时不仅打印仿真时间和行信息,还打印一些其他信息。

在这里插入图片描述


3. 仿真时间: $time $stime $realtime


在这里插入图片描述

$realtime 会按照当前的时间精度对仿真时间进行准确读取,而 $time$stime 会根据时间精度对当前时间进行四舍五入的读取。

示例:

initial begin#10;$display("$time output1: %t", $time);$display("$stime output1: %t", $stime);$display("$realtime output1: %t", $realtime);#3.2;$display("$time output2: %t", $time);$display("$stime output2: %t", $stime);$display("$realtime output2: %t", $realtime);#5.6;$display("$time output2: %t", $time);$display("$stime output2: %t", $stime);$display("$realtime output2: %t", $realtime);
end

结果如下:

在这里插入图片描述


4. 命令行传参: $test$plusargs $value$plusargs


仿真时可通过命令行传参的方式进行参数的传递:

在这里插入图片描述

使用 $test$plusargs( str ) 时,只需在仿真命令行中加入"+str "即可。

使用 $value$plusargs( str,var ) 时,需要在 str 内部指定传递参数时数值的类型。而在命令行传递参数时,数值不需要添加任何有关进制的说明,只保留相关进制的数值即可。命令行传递参数的格式需要参照 $value$plusargs 时 str 声明的格式。

示例:

initial beginif ($test$plusargs("DISPLAY_CTRL")) begin$display("Display simulation information!!!");end
endreg  [1:0]   display_sel ;initial beginif ($value$plusargs("INFO_SEL=%b", display_sel)) begin$display("Parameter transfer succeeds!!!");endelse begindisplay_sel = 2'b0 ;end
endinitial begin#1 ;if (display_sel == 2'b01)$display("You have selected Runoob!!!");else if (display_sel == 2'b10)$display("You have selected Verilog!!!");else if (display_sel == 2'b11)$display("You have selected Me!!!");else$display("What do you really what???");
end

在仿真的命令行中添加 +DISPLAY_CTRL +INFO_SEL=01 即可传递参数:

./simv \+DISPLAY_CTRL +INFO_SEL=01 \-l logs/run.log

输出结果如下:

在这里插入图片描述

因为在定义 INFO_SEL 的时候,已经指定其类型为二进制(INFO_SEL=%b),所有船体给它的 01 会被仿真工具认为是二进制,而不是其他类型。


二、编译指令


就像 C/C++ 程序需要编译成 .exe 或可执行文件才能运行一样,VCS 编译就是将 HDL “源代码” 编译成计算机 CPU 可以直接高效执行的“仿真程序”(simv),在编译的过程中会对源代码进行分析、检查和优化。

编译指令(Compiler Directives) 是一种特殊的预处理命令,以特定符号(Verilog中的是 `)开头。它们在代码编译前被处理,用于指导编译器如何解析、转换或配置源代码,从而影响编译结果和最终生成的仿真模型。

编译指令并不是Verilog语言的一部分,而是编译器的处理指令

Verilog 中常用的一些编译指令如下:

在这里插入图片描述


1. 宏定义:`define

在编译阶段,define 用于定义宏常量或者宏函数,或者说是用于文本替换

一旦 define 指令被编译,其在整个编译过程中都会有效,相当于是定义了一个 “全局变量”。

例如,在一个文件中定义宏常量:

`define DATA_DW 32

在另一个文件中可以直接使用 DATA_DW:

reg [`DATA_WIDTH-1:0] data

使用 define 定义函数(或者说带参数的宏)的示例如下:

`define MAX(a, b) ((a) > (b) ? (a) : (b))initial $display("Max: %d", `MAX(5, 9));

如果使用 define 定义的内容很多,可以使用换行符:

`define COUNTER_MODULE(name, width) \
module name ( \input wire clk, \input wire reset_n, \input wire enable, \output reg [width-1:0] count \
); \always @(posedge clk or negedge reset_n) begin \if (!reset_n) \count <= {width{1'b0}}; \else if (enable) \count <= count + 1'b1; \end \
endmodule//===================================================`COUNTER_MODULE(counter8, 8)     // 生成8位计数器
`COUNTER_MODULE(counter16, 16)   // 生成16位计数器

undef 用于取消之前定义的宏,释放宏名称以便重新定义。

使用 define 定义宏的时候是不能重复定义的,需通过 undef 指令取消原有定义之后才能重新定义。

`undef DATA_DW

2. 条件编译:`ifdef

条件编译指令允许根据预定义条件选择性地包含或排除代码段,实现一套代码支持多种配置的目标。

条件编译相关的命令包括:indef、ifndef、elsif、else、endif

`ifdef FPGA_TARGET`ifdef XILINX_FPGA// Xilinx FPGA特定代码parameter VENDOR = "XILINX";(* KEEP = "TRUE" *) wire keep_signal;`elsif ALTERA_FPGA// Intel/Altera FPGA特定代码parameter VENDOR = "INTEL";(* preserve *) wire keep_signal;`else// 其他FPGAparameter VENDOR = "GENERIC";`endif
`elsif ASIC_TARGET// ASIC特定代码parameter VENDOR = "ASIC";// 功耗优化代码
`else// 默认仿真代码parameter VENDOR = "SIMULATION";
`endif

3. 文件包含:`include

include 指令在编译时将指定文件的内容插入到当前位置,该指令通常用于将全局或公用的头文件包含在设计文件里。

文件路径既可以使用相对路径,也可以使用绝对路径。

`include "../../param.v"
`include "cpu_defines.v"

为了避免重复定义,include 命令中指定的头文件一般包含保护机制:

// 每个.vh文件都应该有保护机制
`ifndef PROJECT_DEFINES_VH`define PROJECT_DEFINES_VH// 使用严格的网络类型检查`default_nettype none// 常量定义`define WORD_SIZE 32`define CACHE_SIZE 1024// 宏函数定义`define CLOG2(x) $clog2(x)`endif // PROJECT_DEFINES_V

4. `default_nettype

该指令用于为隐式的线网变量指定为线网类型,即将没有被声明的连线定义为线网类型。

// 设置默认为wire类型(默认值)
`default_nettype wire// 禁用隐式网络声明(推荐)
`default_nettype nonemodule strict_module (input wire clk,input wire reset_n,output wire result
);// 所有信号必须显式声明wire internal_signal;  // 必须声明reg  state_reg;        // 必须声明assign internal_signal = clk & reset_n;assign result = internal_signal;
endmodule// 恢复默认行为
`default_nettype wire

5. `resetall

该编译器指令将所有的编译指令重新设置为默认值。

resetall 可以使得缺省连线类型为线网类型。

resetall 加到模块最后时,可以将当前的 timescale 取消,防止其进一步传递,只保证当前的 timescale 在局部有效,避免 timescale 的错误继承。


6. `celldefine

celldefineendcelldefine 用于标记标准单元库中的基本单元,他们包含模块的定义。例如一些与、或、非门,一些 PLL 单元,PAD 模型,以及一些 Analog IP 等。

`celldefine
module (input      clk,input      rst,output     clk_pll,output     flag);……
endmodule
`endcelldefine
http://www.dtcms.com/a/481580.html

相关文章:

  • 辅助分类器GAN(ACGAN)
  • 交流网站建设心得体会wordpress首页固定页面
  • 专门做有机食品的网站dedecms怎么部署网站
  • 大学生个体创业的网站建设百度搭建wordpress
  • 自己公司网站维护上海动易 网站
  • 摄影网站设计企业官网用什么系统
  • 网站开发工具最适合网站建设和网络优化
  • 东莞东坑网站设计中牟网站建设
  • 官方模板关键字生成的代码添加在网站的什么地方?郴州网站建设服务
  • 查看一个网站开发语言wap网站分享到微信
  • 网站备案流程教程今天的热点新闻
  • 网站站内链接福田欧曼前四后八
  • 网站建设具体方案免费企业邮箱排名
  • 温州建设小学的网站企业网站建设与实现的论文
  • 网站机房建设目的wordpress导航设置
  • 怎么构建网站wordpress 关闭伪静态
  • 做app推广上哪些网站做金融的看哪些网站
  • 机械设备做公司网站下载好了网站模板怎么开始做网站
  • 珠宝网站模板网络营销的概念与含义谷歌
  • 沧州网站建设联系电话做学徒哪个网站好
  • 著名的网站有哪些网页设计工资一般多少
  • 网站建设能挣钱免费的宣传平台有哪些
  • 外贸网站经典营销案例网站空间商是什么意思
  • 做教案比较好的网站国外友链买卖平台
  • 广东网站建设人员网址在线生成二维码
  • 东莞seo整站优化怎么做网站下载链接
  • 用路由器做简单的网站宁波正规seo推广
  • 有关商业网站的风格特征杭州seo公司
  • 做网站帮外国人淘宝深圳市龙岗区建设工程交易中心
  • 地产网站建设ghost和wordpress