Verilog带参数的`define用法

宏除了可以进行简单的文本替换,还可以像函数和任务一样传递指定多个参数分别对文本进行对应的替换

示例1:

`define Disp(pa,pb,pc)  \
	initial \
		begin \
		   #1200; \
		   $display("%d  \n",(pa+pb+pc)); \
		   $display(`" data_ ``pa+ data_ ``pb + data_ ``pc =%d`",(pa+pb+pc)); \
		end

module  cdc_single_tb;

  reg          src_clk;
  reg          src_in;
  reg          dest_clk;
  wire         dest_out;

initial 
 begin
  src_clk=0;
  src_in=0;
  dest_clk=0;
  
  #100 src_in=1;
  #50 src_in=0;
  #50 src_in=1;
  
  #10000 src_in=0;
  #100 src_in=1;
  #100 src_in=0;
  
#100000 $stop;
  
 end

`Disp(1,2,3)

always #5 src_clk=~src_clk;
always #3 dest_clk=~dest_clk;

xpm_cdc_single  #(
  // Module parameters
  4,0, 0,1, 0
  )   inst_single (
  // Module ports
  .         src_clk(src_clk )   ,
  .        src_in(src_in),
  .        dest_clk(dest_clk),
  .       dest_out(dest_out)
);

endmodule 

仿真结果如下:

#           6  
#
#  data_ pa+ data_ pb + data_ pc =          6

        示例表示,当宏定义中宏文本内容比较多时,写在一行阅读起来比较麻烦。此时可以使用“\”进行换行。其次,宏名可以带有任意多个“形参”,各个参数之间通过“,”或者若干个空格进行分割(此处空格不会作为被替换的文本进行替换)。这里还需要注意宏替换时存在优先匹配的情况,示例中虽然宏文本中“d3=”为一个连续的字符串,但是替换时首先对匹配的“d3”进行替换,而不是“d3=”.

        既然宏定义时可以指定参数,那么这些参数是不是也可以指定默认值呢?在实际的应用过程中,也可以为宏定义指定的参数指定默认值,但是在使用时需要特别注意,不能随意使用(当然任何语法都不能随意使用)。

示例二:

`define disp_str(s1,s2="Default",s3) \
	initial begin \
		$display("Start",s1,s2,s3,"End!"); \
		end
	
module  cdc_single_tb;

  reg          src_clk;
  reg          src_in;
  reg          dest_clk;
  wire         dest_out;

initial 
 begin
  src_clk=0;
  src_in=0;
  dest_clk=0;
  
  #100 src_in=1;
  #50 src_in=0;
  #50 src_in=1;
  
  #10000 src_in=0;
  #100 src_in=1;
  #100 src_in=0;
  
#100000 $stop;
  
 end

`disp_str("Before",,"After")
`disp_str("Before","Haha","After")
`disp_str(,,"After")
`disp_str("Before",,"After")
`disp_str(,,)
//`disp_str(,,,)
//`disp_str(,)

always #5 src_clk=~src_clk;
always #3 dest_clk=~dest_clk;

xpm_cdc_single  #(
  // Module parameters
  4,0, 0,1, 0
)   inst_single (
  // Module ports
  .         src_clk(src_clk )   ,
  .        src_in(src_in),
  .        dest_clk(dest_clk),
  .       dest_out(dest_out)
);

endmodule 

仿真结果如下:

# StartBeforeDefaultAfterEnd!
# StartBeforeHahaAfterEnd!
# Start DefaultAfterEnd!
# StartBeforeDefaultAfterEnd!
# Start Default End!

从仿真结果可以观测到:

        `disp_str("Before",,"After"),宏的第二个参数并没有给出,此时替换时将采用的是宏定义时指定的默认参数,并且各个字符串之间并没有空格出现;

        `disp_str("Before","Haha","After"),宏的第二个参数显式给出,此时替换时将采用显式给出的参数进行替换而不是宏定义时指定的默认参数;

        `disp_str(,,"After"),宏的第一个参数和第二个参数都没有显式给出,但是通过都好保留了参数的位置,其中第一个参数没有指定默认参数,所以进行替换后仅用一个空格空出了该参数的位置,第二个参数因为有指定的默认值,所以在实参没有指定时,宏定义将使用指定的默认参数进行替换,如果第二个参数没有指定默认值,那么此时第二个参数的位置也会有一个空格空出该参数的位置;

        `disp_str(" Before",,"After"  ),双引号中第一个参数的首字母前增加一个空格,那么这个空格将会成为第一个参数的一部分替换到宏文本中.最后一个参数双引号外增加了多个空格,因为空格出现在字符串以外,所以不属于替换字符串的一部分,不会替换到宏文本中.

        `disp_str(,,),三个参数均没有进行设置,因为第二个参数存在默认值,所以第二个参数将会使用默认值替换宏文本,宏文本被对应参数替换后,第一个和第三个参数所在位置将会有一个空格空出该参数的位置;

        `disp_str(,,,),虽然没有指定参数,但是实际留下参数的位置个数与宏定义中指定参数个数不同,多于宏定义指定的三个参数,编译错误;

      `disp_str(,)与`disp_str(,,,) 错误类似,这里只是参数个数少于指定的参数个数(这里因为三个参数仅指定了一个默认参数,如果三个参数都有默认值编译不会错误,后文将示例).所以,参数可以不指定,但是空余的位置还是需要与定义时匹配; 

宏除了像函数和任务那样存在参数列表外,还可以像函数和任务那样进行相互调用。 

`define FI first
`define TW "`FI two"
`define S1(x) "first two x"
`define S2(x) `"first two x`"
`define  ADD(a,b) a+b

module tb;

integer sum;
initial
begin
	$display("`FI");
	$display(`TW);
	$display(`S1(third));
	$display(`S2(third));
	$display(`S2(`S2(forth)));  //illegal
	sum=`ADD(`ADD(1,2),`ADD(3,4));
	$display("the sum id %h ",sum);

end
endmodule

仿真结果如下:

第10行字符串中的宏定义不会被替换掉;

第11行虽然宏文本中有宏`FI调用,但是处于字符串中的宏调用不会被调用;

第12行字符串中的内容不会被宏名后的参数替换;

第13行“`”对原字符串进行了处理,所以宏名后的参数可以替换文本中的内容;

第14行字符串中的宏调用不能进行,其调用实现过程如下:

综上所述,可以得到以下几点关于宏的使用的通用规律:

Ø  如果对应的宏参数指定了默认值,那么该参数在宏调用时可以不指定实参.如果所有的参数都指定了默认参数,那么在宏调用时可以仅保留括号不传递任何参数;

Ø  如果存在部分宏参数没有指定默认值,那么在调用宏时不能省略所有的实参,但是可以使用“,”空留出各个参数的位置;

Ø  如果宏参数中最后一个参数指定了默认值,那么如果期望使用该参数默认值时,在调用宏时可以不保留该参数的位置,即不使用逗号专门空留对应位置;

Ø  宏定义的宏名不能与编译命令名字相同,例如define的宏名不能是define等;

Ø  宏名可以作为一般的信号名,与宏名不冲突,例如定义的宏名为“VAR_V”,那么可以在使用该宏的代码中定义“reg VAR_V”变量,该变量与宏“VAR_V”不冲突,其实主要是使用宏时,在宏名前指定了“`”,将宏名与其他信号变量进行了区分;

Ø  可以重复定义宏,但是仅有最后一次定义的宏有效,也就是说前几次其实都被最后一次定义覆盖了;

Ø  如果宏调用出现在字符串文本中,那么该宏调用将不能进行; 
 

在进行一些文本打印时,有时文本中部分内容需要包含双引号字符,但是文本本身就是以双引号作为限定的,即字符串会将第一个"到下一个"之间的内容作为字符串文本,如果在文本字符串中本身包含",那么会认为当前字符文本结束,问题就来了,这种情况如何实现文本中的双引号的输出呢?

【示例】

【仿真结果】

示例中可以看到,通过在需要插入引号的地方使用转义符“\”,既可以实现字符串中引号的嵌入.那么如果试图将宏文本中插入的双引号中的内容进行宏参数替换,可以按照如下示例方法进行.

【示例】

【仿真结果】

        其中首尾的`"确保了双引号中的内容也可以被宏参数进行文本替换,`\`"确保了其中的双引号可以被有效输出,同时该双引号中的内容也可以被宏参数替换. 


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/13301.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#中用程序代码修改了datagridview中的数据,保存时只对光标当前行有保存解决办法

C#中DataGridView绑定了DataTable后,通过代码修改DataGridView中的数据,总有一行(被修改过并被用户选中的行集合中索引为0的行)不能被UpDate回数据库的问题和解决办法 长江黄鹤 2017-06-26 | 300阅读 | 1转藏 转藏全屏朗读分…

真题详解(UML部署图)-软件设计(五十二)

真题详解(地址索引)-软件设计(五十一)https://blog.csdn.net/ke1ying/article/details/130211684 瀑布模式:适应 开发大型项目,且需求明确。 演化模式:适应 对软件需求缺乏准确认知。 螺旋模式&#xff…

【linux】yum “应用商店” 的基本用法

好多工具 yum软件包查看软件包安装软件卸载软件 yum 通俗的讲,这就似我们手机上的应用商店,只不过是在linux下的。 我们可以用yum来下载东西。 软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序。 但是这样…

19 calloc 和 realloc 虚拟内存分配的调试

前言 前面提到了 malloc 虚拟内存分配相关的内容 malloc 虚拟内存分配的调试(1) malloc 虚拟内存分配的调试(2) 这里提 calloc 和 realloc, 这两个函数 虽然没有 malloc 使用频率那么高 但是 还是有很大的知名度的, 本文这里 我们来看一下 calloc 此函数传入两个参数, 第…

Obsidian中如何创作思维导图Mind-map

使用插件 obsidian-mind-map 1.直接在社区下载安装 设置快捷键或者在左侧竖形打开命令面板搜索关键字“mind”, 或者为了便于使用,设置快捷键,在设置-第三方插件中-选择快捷键 然后按下你想设置的快捷键就可以 我这里设置成了CtrlAltM ,M是…

虚拟数字人的3种驱动方式

虚拟数字人是由计算机程序所构建的具有人类特征的虚拟实体,目前的虚拟数字人经过了三代的更迭,划分每一代更迭的标准则是虚拟数字人的驱动方式。 一、虚拟数字人1.0:动画&CG驱动 虚拟数字人1.0就是目前我们所熟知的,比如&am…

LiveCharts2 初步认识

文章目录 1 LiveCharts2 是什么?2 LiveCharts2 可以做什么?3 简单使用LiveCharts2 ,实现动态曲线图 1 LiveCharts2 是什么? GitHub:https://github.com/beto-rodriguez/LiveCharts2 官网: https://lvchar…

C++ STL学习之【反向迭代器】

✨个人主页: 夜 默 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 A year from now you may wish you had started today. 明年今日,你会希望此时此刻的自己已经开始行动了。 文章目录 🌇前言&a…

分布式锁-Redisson

分布式锁 1、分布式锁1.1 本地锁的局限性1.1.1 测试代码1.1.2 使用ab工具测试(单节点)1.1.3 本地锁问题演示(集群情况) 1.2 分布式锁实现的解决方案1.3 使用Redis实现分布式锁(了解即可)1.3.1 编写代码1.3.2 压测 1.4 使用Redisson解决分布式锁1.4.1 实现代码1.4.1 压测1.4.2 可…

2 常见模块库(2)

2.5 复用器与分路器模块 Mux是一种用于将多个信号组合成一个信号的模块。Mux模块的名称来源于多路复用器(Multiplexer)。 使用Mux可以将多个输入信号组合成一个向量或矩阵,以便在模型中传递和处理。Mux模块可以接受任意数量的输入信号&#x…

什么是伪原创?SEO伪原创该怎么做

伪原创是指在原有的文章或内容基础上进行修改或调整,以产生看起来是全新内容的文章,但实际上并没有创造新的价值。多数情况下,伪原创的目的是为了在文章相对原创的情况下,提高搜索引擎的排名。 一、高质量伪原创 做好伪原创&#…

C语言从入门到精通第8天(分支结构if、else、switch的使用)

分支结构if、else、switch的使用 if语句if...else语句if...else嵌套if...else if...else语句switch语句 if语句 语法: if(表达式){ 语句; } 如果表达式为真,则执行{}里面的语句。如果为假,则不执行。示例代码: int m…

翻译国外文章-整篇文章的翻译

chatgpt翻译是专业的吗 ChatGPT是一种AI语言模型,它可以用来执行各种自然语言处理任务,包括翻译。然而,ChatGPT的翻译结果并不是专业的翻译,因为该模型并不是专为翻译任务训练的。 虽然ChatGPT的翻译质量相对较高,但…

全景视角下的世界探索——三维全景地图

引言:随着数字技术和虚拟现实技术的发展,三维全景地图已成为一种新型地图展示方式,深受人们的关注和喜爱。三维全景地图以其真实逼真、互动性强、展示效果好等特点,正在越来越多的领域得到应用。 三维全景地图的特点 1.真实逼真 …

考研计算机组成原理总结(7)

一.虚拟存储器 1.基本知识 主存和辅存共同构成了虚拟存储器,二者在硬件和系统软件的共同管理下工作。对于应用程序员而言,虚拟存储器是透明的。虚拟存储器具有主存的速度和辅存的容量。 2.基本概念 虚拟存储器将主存或辅存的地址空间统一编址&#x…

Excel中的表格批量生成word表格

场景:测试用例excel转word 我们在项目中,默认情况下是用我们的excel用例模版输出测试用例。但是有的项目中,会要求在word版本的测试计划或者测试报告中,写明测试用例。而我们的测试用例,有的项目有上千条,…

ChatGPT常见问题,Access denied的解决办法

今天,突然想登录一登录ChatGPT,提示 Access denied, You do not have access to chat.openai.com 怎么办? “Access denied You do not have access to chat.openai.com. The site owner may have set restrictions that prevent you from ac…

基于html+css的图片展示15

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

1026. 节点与其祖先之间的最大差值(4-19日

题目:给定二叉树的根节点 root,找出存在于 不同 节点 A 和 B 之间的最大值 V,其中 V |A.val - B.val|,且 A 是 B 的祖先。 (如果 A 的任何子节点之一为 B,或者 A 的任何子节点是 B 的祖先,那么…

2023年网络安全比赛--Windows渗透测试中职组(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 1.通过本地PC中渗透测试平台Kali对服务器场景20221219win进行系统服务及版本扫描渗透测试,并将该操作显示结果中1433端口对应的服务版本信息作为Flag值(例如3.1.4500)提交; 2.通过本地PC中渗透测试平台Kali对服务器场景202212…