《CPLD FPGA设计与应用基础教程》课件第五章_第1页
《CPLD FPGA设计与应用基础教程》课件第五章_第2页
《CPLD FPGA设计与应用基础教程》课件第五章_第3页
《CPLD FPGA设计与应用基础教程》课件第五章_第4页
《CPLD FPGA设计与应用基础教程》课件第五章_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第五章

任务及函数LOREMIPSUMDOLOR目录CONCENT5.1任务5.2函数5.3系统任务和系统函数5.4命名事件5.5层次路径名5.6共享任务和函数5.1任务GRADUATIONTHESIS5.1任务任务类似于一段程序,它只能在模块内部的行为所调用,因而不能使用连续赋值语句来调用任务。任务没有返回值,而是直接通过output或inout端口输出。任务可以包含时序控制和时延等时序信息,也可以包含各种事件控制逻辑,同时也可以调用其他任务或函数,并且可以有各种端口参数。5.1任务5.1.1任务声明任务以关键字task开始,以关键字endtask结束。其基本语法如下:tasktask_name;portdeclaration;taskdeclaration;localvariabledeclaration;beginprocedural_statement;endendtaskportdecalaration是可选的,可以有输入(input)、输出(output)和双向(inout)的端口声明,也可以缺省。通过输入端口或者双向端口来传递参数并交由任务处理;处理完毕的数据通过输出端口或者双向端口交由调用它的模块进行处理。端口并不像模块的端口那样传递真实的电信号,而是传递数据。5.1任务

【例5-1】采用任务实现对两个16位宽的操作数的与、或、异或逻辑,其示意图如图5-1所示。taskbitwise_oper;input[15:0]a;input[15:0]b;output[15:0]ab_and,ab_or,ab_xor;begin#10ab_and=a&b;ab_or=a|b;ab_xor=a^b;endendtask5.1任务5.1.2任务调用

任务调用和其他高级编程语言中的函数调用很类似,但它只能在过程语句中调用。也就是说,它只能在always语句块和initial语句块中被调用,因此任务的output和inout参数必须为reg型。任务可以调用其他任务,任务可以嵌套调用自己,甚至可以被自己调用的任务再调用。任务调用的基本语法格式是:task_name(expression1,expression2,…,expressionN);系统调用任务后,任务计算的结果通过output和inout端口实现数据传递给系统中调用该任务的代码。调用的参数和任务中的端口声明的顺序必须一一对应。5.2函数GRADUATIONTHESIS5.2函数函数定义函数和任务很类似,也可以用来描述共同代码段。但函数与任务不同的是,函数只能返回一个值,并且不能包含任何时延信息,也不能调用其他任务。另外,函数必须至少要有一个输入,不允许有output和inout。函数可以调用其他的函数。因为函数里面不带有触发器,所以一般可用于综合成具体的电路逻辑。5.2函数5.2.1函数声明函数以关键字function开始,以关键字endfunction结束。函数的作用是实现组合逻辑,因此函数里不能有任何时延控制逻辑。函数返回值默认为标量reg型。如果需要指明特定的数据类型和位宽,需要显式声明。函数声明的基本格式如下:function[rangeortype]function_name;inputdeclaration;otherdecalaration;beginstatement;endendfunction5.2函数5.2.2函数调用函数调用和任务调用相同,均需指明函数名和输入参数名,其基本格式如下:function_name(expression1,expression2,…,expressionN);函数内部声明的寄存器是静态的,当函数返回的时候,数值仍然维持不变。当函数执行完毕时,返回值会出现在调用函数的位置。5.2函数假设设计一个内存协议,需要调用奇偶校验函数,其VerilogHDL代码如下:moduleparity;………….reg[31:0]addr;regparity;always@(addr)begin//invokethefunctioncalc_paritytwiceparity=calc_parity(addr);$display(“Paritycalculated=%b”,calc_parity(addr));end……………//defineFunctioncalc_parityfunctioncalc_parity;input[31:0]address;begin//returnthexorofalladdressbits.calc_parity=^address;endendfunction……………..endmodule5.3系统务和系统函数GRADUATIONTHESIS5.3系统任务和系统函数VerilogHDL不仅可以用户定义任务和函数,而且还有预先定义好的内建的系统任务和系统函数,用户可以直接以关键字的形式直接调用。根据用途不同,系统任务和系统函数大致可以分为几类:显示任务仿真控制任务随机建模任务文件输入输出任务时间标度任务PLA建模任务变换函数概率分布函数字符格式化命令行参变量5.3系统任务和系统函数5.3.1显示任务VerilogHDL提供了三种类型的显示任务,分别是:显示和写任务、连续监控任务以及选通的监控任务。其关键字分别是$display,$write,$monitor以及$strobe。其根本语法格式如下:task_name(format_specification1,argument_list1,format_specification2,argument_list2,…format_specificationN,argument_listN);如:$display($time,“:a=%b,b=%h,c=%o,d=%d”,a,b,c,d);表示一旦调用$display任务,则把此刻的a、b、c和d的值分别显示出来,并显示当时的时刻。5.3系统任务和系统函数四类显示任务的区别如下:显示任务类型任务描述$display用于行为级描述中。当该任务被调用时,把指定信息及行结束字符打印到标准输出设备$write和$display的作用相同,只是在该任务被调用时,只把指定信息打印到标准输出设备,不输出行结束字符$monitor一旦任务中的任意一个变量发生变化时就把指定信息打印到标准输出设备。需要注意的是,$monitor任务不能用来监控时间变量或返回时间值的函数。$monitor信息必须是在每次仿真时间阶段结束的时候才会打印,这样每个变量在每次仿真时间阶段结束时都会显示其最终值。$strobe用于行为级描述中。$display信息必须是在每次仿真时间阶段结束的时候才会打印,这样每个变量在每次仿真时间阶段结束时都会显示其最终值。表5‑1显示任务具体区别和描述5.3系统任务和系统函数【例5-3】各类显示任务的应用举例说明integerwatchdog;

initialbeginwatchdog=500;$display(“Implementthedisplaytask,watchdogvalueis%d”,watchdog);$strobe(“Implementthestrobletask,watchdogvalueis%d”,watchdog);

watchdog=1000;$display(“Implementthedisplaytaskagain,watchdogvalueis%d”,watchdog);$write(“Implementthewritetask,watchodvalueis”);$write(“%d\n”,watchdog);end仿真结果显示为:Implementthedisplaytask,watchdogvalueis500Implementthedisplaytaskagain,watchdogvalueis1000Implementthewritetask,watchdogvalueis1000Implementthestrobletask,watchdogvalueis10005.3系统任务和系统函数5.3.2仿真控制任务在正常状态下,VerilogHDL提供了两类系统任务来结束仿真。其关键字分别是$finish和$stop。$finish系统任务被调用时,意味着仿真器退出仿真环境,并把控制权交还给操作系统。$stop系统任务被调用时,只是把仿真挂起,不会退出仿真环境。其基本格式为关键字加“;”。如:$finish;$stop;。5.3.3文件输入输出任务仿真数据不仅需要实时显示,也需要随时保存以便在未来的某个时间内查阅。或者,当要给的仿真激励需要大量数据时,如果在Testbench里面直接显式写入数据,不仅浪费时间,而且可读性差,代码可重复利用率低,容易出错。采用文件输入输出任务可以很好的解决此问题。和C语言一样,VerilogHDL的文件输入输出任务包含如下子任务:文件打开($fopen)、文件关闭($fclose)、写入文件($fdisplay、$fwrite、$fmonitor、$fstrobe、$fflush)以及从文件中读取数据($readmemh、$readmemb等)。各文件输入输出任务的描述如表5-2所示。5.3系统任务和系统函数任务类型关键字描述文件打开$fopen打开一个文件文件关闭$fclose关闭一个文件写入文件$fdisplay和显示任务一样,只是输出到文件中$fwrite$fmonitor$fstrobe$fflush把输出缓冲内的资料输出到指定文件中读取文件$readmemb从文件中读取二进制存储数据并将数据加载到存储器中$readmemh从文件中读取十六进制存储数据并将数据加载到存储器中$fread从文件中读取二进制数据到存储器中$fgetc从文件中每次读取一个字符$fgets从文件中每次读取一行$ungetc把一个字符插入文件中$frewind重新回到文件的开始处$fseek移动到偏移量指定的位置$ftell返回以文件开始处为基础的偏移量

$fscanf从文件中读取格式化数据

$ferror在执行完一个读取任务后,帮助判断出错的原因5.3系统任务和系统函数文件模式具体说明r,rb打开文件并从文件的头开始读。如果文件不存在则报错w,wb打开文件并从文件的头开始写。如果文件不存在则创建新文件a,ab打开文件并从文件的末尾开始写。如果文件不存在则创建文件r+,r+b,rb+打开文件并从文件的头开始读写。如果文件不存在则报错w+,w+b,wb+打开文件并从文件的头开始读写。如果文件不存在则创建文件a+,a+b,ab+打开文件并从文件的末尾开始读写。如果文件不存在则创建文件表5‑3文件模式说明表5.3系统任务和系统函数变换函数格式功能描述$rtoi(realvalue)将小数位截断将实数型转换为整型数据$itor(integervalue)将整型数据转换为实数型$realtobits(realvalue)将实数型转换为64位的实型向量表达式$bitstoreal(bitvalue)将位模式转换为实数$signed(value)将数据转换为有符号数$unsigned(value)将数据转换为无符号数表5‑4变换函数功能描述5.3系统任务和系统函数5.3.4概率分布函数VerilogHDL用于测试仿真时,需要随机产生激励,因此概率分布函数可以很好地应用于此场合。其基本格式如下:$random(seed);Seed是种子变量,是可选的。根据种子变量的值返回一个32位的有符号的整型随机数。种子变量必须是reg型、整型或时间类型变量,不同的种子将生成不同的随机数。如果没有指定种子变量,则根据默认种子变量来生成随机数。需要注意的是,生成的数字序列是一个伪随机序列,也就是说,对于一个初始的种子值会生成相同的数字序列。如:{$random}%101;会生成一个在0到100之间取值的随机数。{$random}把$random函数返回的有符号数转换为无符号数。5.3系统任务和系统函数5.3.5仿真时间函数在前面的章节中,经常会看到$time这类系统函数用于返回系统仿真时间。在VerilogHDL语法中,有三种不同的系统函数用于返回仿真时间。函数类型功能描述$time按照所在模块的时间单位和精度,返回64位的整型仿真时间$stime返回32位的仿真时间$realtime返回实型仿真时间表5‑5仿真时间函数功能描述5.4命名事件GRADUATIONTHESIS5.4命名事件命名事件:erilogHDL定义了一种新的数据类型叫做命名事件。采用关键字“event”来声明,其基本格式如下:eventevent_name;命名事件没有值或者时延,它可以透过事件触发状态或者边沿敏感事件控制来触发。通常用来描述行为级模型中通信和同步事件。当需要触发某个命名事件时,其基本格式如下:->event_name;命名事件既可以在模块内使用,也可以在任务内使用,还可以在语句块内使用。5.4命名事件【例5-4】命名事件举例eventStartClock,StopClock;

alwaysforkbegin:ClockGeneratorClock=0;@StartClockforever#HALFPERIODClock=~Clock;end@StopClockdisableClockGenerator;join

initialbegin:stimulus…->StartClock;…->StopClock;…->StartClock;…->StopClock;end5.5层次路径名GRADUATIONTHESIS5.5层次路径名VerilogHDL语言利用自上而下的设计方法论,采用模块化划分和设计。而模块又可以由任务、函数以及具体的程序组成。因此整个模块层次如图所示。

modulesub_modulefunctiontaskblock图5‑2模块层次示意图5.5层次路径名如果系统需要对任何层次的任何变量进行自由的数据访问和更新,则需要采用层次路径名来进行标识。层次路径名都是从顶层模块开始,通过“.”隔开的名称组成。如:

moduletop_A;

wirewire_s;…

functionfunc_A……

endfunction

tasktask_B;…

regreg_C;

begin:blk

integerRtoI;reg_c=RtoI?1’b1:1’b0;…

end

endtask

sub_modsub_B(…);endmodule

modulesub_mod;

regsub_a;…

initialtop_A.task_B.blk.RtoI=1’b1;//层次路径名…endmodule5.6共享任务和函数GRADUATIONTHESIS5.6共享任务和函数部分的任务和函数都是设计为通用型,以便为不同的模块来调用。VerilogHDL有两种方式来实现任务和函数共享。一种方式是把任务和函数全部写在一个文本文件中,格式不限,如.h文件、.v文件都行,然后利用关键字“`include”来调用该文本文件中的具体任务和函数来实现。另外一种方式是直接在模块内定义所有的任务和函数,然后采用层次路径名的方式来实现。【例5-5】采用关键字“`include”实现共享任务和函数举例1、设计一个task_function_share.h的文件,专门放置需要共享的任务和函数//文件:task_function_share.hfunctionfunc_A(input[31:0]addr_a;)fun_A=^addr_a;endfunction

tasktask_B(input[63:0]a,b,output[63:0]sum_c);sum_c=a+b;endtask5.6共享任务和函数2、模块调用任务和函数modulemem_bus(input[31:0]address;input[63:0]dataA,dataB,output[63:0]data);

`include“task_function_share.h”;//把共享任务和函数包含进来

always@(*)if(func_A)task_B(dataA,dataB,data);elsedata=64’b0;Endmodule需要注意的是:`include必须出现在模块声明内,且在被调用之前。5.6共享任务和函数【例5-6】采用层次路径名的方式实现共享任务和函数举例1、设计一个模块,专门放置需要共享的任务和函数moduletask_function_share;functionfunc_A(input[31:0]addr_a;)fun_A=^addr_a;endfunction

tasktask_B(input[63:0]a,b,output[63:0]sum_c);sum_c=a+b;endtask

endmodule5.6共享任务和函数2、模块调用任务和函数modulemem_bus(input[31:0]address;input[63:0]dataA,dataB,output[63:0]data);

always@(*)if(task_function_share.func_A)task_function_share.task_B(dataA,dataB,data);elsedata=64’b0;endmodule5.7实例:带可预置数据的8位自增/减计数器设计GRADUATIONTHESIS5.7实例:带可预置数据的8位自增/减计数器设计修改3.9节实例,采用函数调用的方式来设计带可预置数据的8位自增/减计数器。其代码如下:`timescale1ns/100ps//指定时间单位和精度modulecounter_function#(parameterCOUNT_WIDTH=8)(//定义位宽参数inputsysclk,inputreset,inputset,inputld,inputup,inputdown,input[COUNT_WIDTH-1:0]data,outputreg[COUNT_WIDTH-1:0]count);always@(posedgesysclkornegedgereset)//异步复位 begin if(!reset) count<=8'H00; elseif(set)//同步置位 count<=8'hFF;5.7实例:带可预置数据的8位自增/减计数器设计else count<=count_op(up,down,ld);//函数调用end//计数器函数设计function[COUNT_WIDTH-1:0]count_op(inputup,down,ld);

count_op=up?(count_op+8'h1): (down?(count_op-8'h1): (ld?data: 8'h0));endfunctionendmodule5.7实例:带可预置数据的8位自增/减计数器设计综合后的电路图如下:图5‑3采用SynplifyPro综合后的逻辑电路图5.7实例:带可预置数据的8位自增/减计数器设计对上述逻辑进行仿真,仿真代码如下:`timescale1ns/100psmodulecounter_function_tb;regsysclk;regreset;regset;regld;regup;regdown;reg[7:0]data;wire[7:0]count;

initialdata=8'hAA;

initialbegin5.7

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论