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

verilog-HDL基础

函数与任务

   将Verilog HDL模块中重复使用的代码段定义为子程序,既能够使描述代码具有更好的可阅读性、可维护性和可移植性,又能够减少出错的概率。

   Verilog HDL支持两种形式的子程序:函数(functions)和任务(tasks)。函数和任务既可以由系统定义,也可以由用户定义。

   函数是具有独立运算功能的单元电路,每次调用根据输入重新计算输出结果。   在Verilog HDL中,函数定义以关键词function开始,以关键词endfunction结束。

 函数定义的语法格式为function [位宽] 函数名;输入端口声明;语句1;语句2;...endfunction

  在Verilog HDL中,对函数的调用是通过函数名完成的。函数名在函数体中代表一个变量,函数调用的返回值是通过函数名传递给调用语句。

函数调用的语法格式为 <线网/变量名> = <函数名>            ( 线网/变量1 ,..., 线网/变量n )

module dec3_8(d,y);input [2:0] d;output reg [7:0] y;always @(d)begin y[3:0] = func_dec2_4(~d[2],d[1:0]); y[7:4] = func_dec2_4( d[2],d[1:0]);end  

2线-4线 译码函数

 function [3:0] func_dec2_4;   // 函数定义      input en;input [1:0] a;if (en)case (a)2'b00:  func_dec2_4 = 4'b0001;2'b01:  func_dec2_4 = 4'b0010;2'b10:  func_dec2_4 = 4'b0100;2'b11:  func_dec2_4 = 4'b1000;default:  func_dec2_4 = 4'b0000;endcaseelsefunc_dec2_4 = 4'b0000;endfunction
endmodule

任务

在Verilog HDL中,任务定义以关键词task开始,以关键词endtask结束。

任务定义的语法格式为task 任务名;输入/输出端口声明;语句1;...语句n;endtask
任务调用的语法格式为任务名 (线网/变量1,...,线网/变量n);

在定义Verilog任务时,需要注意以下几点:  (1) 在task定义语句的首行不列出端口名称;  (2) 任务的端口数量没有限制,也可以没有端口;    (3) 在task定义中不能包含过程语句。

  与函数不同,任务允许有多个输出,并且允许有延迟、时间或事件控制,因此,任务比函数应用更为广泛。

   用4位偶校验器实现16位校验的思路是:将输入的16位数据分为四组,每组4位,用4位偶校验器进行校验,然后将4组的校验结果再进行校验,得到16位校验结果。

实现16位偶校验的Verilog参考代码如下:

  task even_parity_4b;input [3:0] I;output EP4bout;EP4bout = ^I;endtask
endmodule
module even_parity_16b(D,EPout);input [15:0] D;output EPout;assign EPout = ^D;
endmodule

编译指令

  Verilog HDL支持编译指令,对模块进行编译时先对编译指令进行处理,然后再对代码进行编译。

  (1) 宏定义指令:`define,`undef;(2) 条件编译指令:`ifdef,`else,`endif;(3) 文件包含指令:`include;(4) 时间尺度指令:`timescale;(5) `default_nettype;(6) `resetall;(7) `line;(8) `unconnect_drive,`nounconnected-drive;(9) `celldefine,`endcelldefine。

   宏定义指令是文本宏替换指令,用指定的标识符代表字符串,以增加代码的可阅读性和可维护性。 宏定义指令应用的语法格式为: `define 标识符(宏名) 字符串(宏内容)

 应用宏定义指令时,需要注意以下三点: (1)“`define”是编辑指令,不是HDL语句,所以不需要在行末加分号。(2) “`define”用于定义全局符号量,既可以在模块内定义,也可以在模块外定义,对同时编译的模块均有效。(3)宏定义指令的作用范围是从编译器遇到该指令开始直到编译结束,或者遇到指令“`undef”后失效。(4)“`define”定义的全局符号量,引用时必须在标识符前加反引号“`”,表示该标识符为宏名。

   条件编译指令“`ifdef”用于对代码进行选择性编译。当定义的条件满足时对部分代码段进行编译,不满足时不编译,或者对其它代码段进行编译。 条件编译指令有两种基本应用形式。具体的语法格式为:`ifdef 宏名     代码段 `endif 或者 `ifdef 宏名    代码段1 `else         代码段2 `endif

wire a,b;
wire y;
`define OPMODE
`ifdef OPMODE        // 如果定义了“OPMODE”assign y = a & b ;  // 应用数据流实现
`else                    // 否则and U_and (y,a,b);  // 应用基元实现
`endif

  文件包含指令“`include”用于将指定文件的代码复制到当前文件中,一起进行编译。

文件包含指令应用的语法格式为 `include  “<被包含的文件名>”

 使用文件包含指令应注意以下三点: (1)一条“`include”指令只能包含一个文件。有多个文件需要包含时,需要用多条“`include”进行描述; (2)被包含的文件需要写出完整的文件名信息,包括文件类型名; (3)被包含的文件名中可以含有文件的绝对路径或者相对路径,但建议只包含文件名,不含有文件路径,以增强代码的可移植性。

   时间尺度指令“`timescale”用来定义模块仿真的时间单位和时间精度

   在“`timescale”指令中,用“数字+单位”来定义时间单位和时间精度,其中数字必须为整数,并且有效数字为1、10和100,单位用s、ms、us、ns、ps或者fs表示。时间单位和参量值如表2-16所示。

编写 testbench

   如果需要对设计好的模块进行仿真分析,以验证其功能的正确性,那么需要为模块编写测试平台文件(testbench),为被测模块施加激励信号,例化被测模块,调用仿真软件计算被测模块的输出,并输出仿真结果供设计者进行分析。   

测试平台文件testbench有两个不同于可综合模块的特点:(1) testbech既没有输入,也没有输出,而是将被测模块的输入定义为内部寄存器变量,将被测模块的输出定义为内部线网信号;(2) testbech用于仿真分析,不需要综合,因此可以使用Verilog HDL定义的所有语句来编写代码,而不像设计功能模块一样,只能应用可综合的语句进行描述。

  在数字系统测试中,testbench与被测模块分开进行设计。仿真时,testbench调用仿真软件,传递输入激励并接收输出的线网信号。

 测试平台文件testbench的基本结构为:

`timescale 仿真时间单位/仿真精度
module module_vlg_tst();// testbench没有输入输出端口reg 变量名1,...,变量名n;      // 将被测模块的输入作为变量进行定义wire 线网名1,...,线网名m;     // 将被测模块的输出作为线网进行定义应用过程语句initial/always描述激励信号波形;例化被测模块,传递输入激励并接收输出;调用系统任务(或函数)显示信号波形;
endmodule

  Verilog HDL预定义了许多系统任务与函数,用户可以在testbench中直接应用系统任务和函数实现一些特定的功能。这些任务和函数均以“$”开头,如$display、$time和$monitor等,以区分用户定义的任务和函数。

  系统任务$display和$write用于在控制台上显示字符信息。$display和$write的区别在于$display在显示完信息后会自动换行,而$write不会。

调用系统任务$display和$write的语法格式为  $display(“格式控制字符串”,输出参数列表);  $write(“格式控制字符串”,输出参数列表);

 系统任务$monitor用来监测和显示任何指定的线网/变量或者表达式的值。调用系统任务$monitor的语法格式为   $monitor(“格式控制字符串”,参数1, …,参数n);

系统函数$time用于返回当前的仿真时间。$monitor ($time,"rxd=%b  txd=%b",rxd,txd);

$timeformat任务调用的语法格式如下: $timeformat (时间单位数,时间精度,后缀,最小宽度);

  系统任务$finish用于结束当前仿真。执行$finish任务时,结束当前仿真并退出。

4选一数据选择器:

 module MUX4to1(d0,d1,d2,d3,a,y);input d0,d1,d2,d3;input [1:0] a;output reg y;// 功能描述always @(d0,d1,d2,d3,a)case (a)2'b00: y = d0;2'b01: y = d1;2'b10: y = d2;2'b11: y = d3;default: y = d0;endcase
endmodule


http://www.mrgr.cn/news/67343.html

相关文章:

  • 【架构-37】Spark和Flink
  • kill-start系统进程的研究
  • 打造完整 Transformer 编码器:逐步实现高效深度学习模块
  • 智慧商城项目-VUE2
  • nVisual标签打印模块的部署与使用
  • 【论文分享】基于多源大数据的高密度城市健康资源可达性与公平性评价
  • 超实惠的租借服务器训练深度学习方法
  • Renesas R7FA8D1BH (Cortex®-M85) 存储空间介绍
  • C语言 | Leetcode C语言题解之第543题二叉树的直径
  • SIwave:释放信号网络分析仪的强大功能
  • 使用AMD GPU进行图像分类的ResNet模型
  • ArcGIS006:ArcMap常用操作151-200例动图演示
  • 龙芯交叉编译openssl
  • Scala的包及其导入
  • Renesas R7FA8D1BH (Cortex®-M85) Flash的功能介绍
  • 【LeetCode】【算法】155. 最小栈
  • 11.6日志
  • RTMP推流H264和AAC
  • 计算机网络综合题
  • 【c++语言程序设计】字符串与浅层复制(深拷贝与浅拷贝)
  • jenkins流水线pipeline
  • 使用Rust实现http/https正向代理
  • UE5.4 PCG 创建圆形植被聚落
  • GORM优化器和索引提示
  • C语言 | Leetcode C语言题解之第542题01矩阵
  • 速盾:高防cdn遭受攻击会瘫痪吗?