集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 6425|回复: 10

Verilog的结构语句、系统任务...

[复制链接]
CHAN 发表于 2010-6-28 00:18:42 | 显示全部楼层 |阅读模式
Verilog的结构语句、系统任务...
前言
在本讲中我们将学习Verilog语法中两种结构语句以及如何定义和使用任务与函数,还有几个常用系统任务的用法。 除了函数之外,这些语句在C 语言中从来都没有定义过。特别需要注意的是,函数虽然在C语言中有过定义,但与Verilog的函数定义则完全不同。 我们一定要注意这些语句所代表的物理意义。有意识地把结构语句、任务、函数与虚拟测试信号的生成或硬件电路结构联系来。只有通过物理意义的深入理解,才能在设计中准确地应用。

结构说明语句
Verilog语言中的任何过程模块都从属于以下四种结构的说明语句。
1) initial说明语句
2) always说明语句
3) task说明语句
4) function说明语句
一个程序模块可以有多个initial和always 过程块。每个initial和always说明语句在仿真的一开始同时立即开始执行。initial语句只执行一次。而always语句则是不断地重复活动着,直到仿真过程结束。但always语句后跟着的过程块是否运行,则要看它的触发条件是否满足,如满足则运行过程块一次,再次满足则再运行一次,直至仿真过程结束。
在一个模块中,使用initial和always语句的次数是不受限制的,它们都是同时开始运行的。task和function语句可以在程序模块中的一处或多处调用。其具体使用方法以后再详细地加以介绍。在初级篇里,我们只对initial和always语句深入加以介绍。
initial语句
initial语句的格式如下:
initial
begin
  语句1;
  语句2;
  ......
  语句n;
end
举例说明:
[例1]:
initial
begin
    areg=0; //初始化寄存器areg
    for(index=0;index    memory[index]=0;//初始化一个memory
  end
在这个例子中用initial语句在仿真开始时对各变量进行初始化,注意这个初始化过程不需要任何时间。
[例2]:
initial
begin
    inputs = 'b000000; //初始时刻为0
    #10 inputs = 'b011001;
    #10 inputs = 'b011011;
    #10 inputs = 'b011000;
    #10 inputs = 'b001000;
  end
从这个例子中,我们可以看到initial语句的另一用途,即用initial语句来生成激励波形作为电路的测试仿真信号。注意:一个模块中可以有多个initial块,它们都是并行运行的。initial块常用于测试文件和虚拟模块的编写,用来产生仿真测试信号和设置信号记录等仿真环境。

always语句
always语句在仿真过程中是不断活动着的。但always语句后跟着的过程块是否执行,则要看它的触发条件是否满足,如满足则运行过程块一次,如不断满足则不断地循环执行。
其声明格式如下:
always<时序控制><语句>
always语句由于其不断活动的特性,只有和一定的时序控制结合在一起才有用。如果一个always语句没有时序控制,则这个always语句将会发成一个仿真死锁。见下例:
[例1]:alwaysareg = ~areg;
这个always语句将会生成一个0延迟的无限循环跳变过程,这时会发生仿真死锁。
但如果加上时序控制,则这个always语句将变为一条非常有用的描述语句。见下例:
[例2]:always #half_periodareg = ~areg;
这个例子生成了一个周期为:period(=2*half_period) 的无限延续的信号波形,常用这种方法来描述时钟信号,作为激励信号来测试所设计的电路。
[例3]:reg[7:0] counter;
reg tick;
  always @(posedge areg)
  begin
  tick = ~tick;
  counter = counter + 1;
  end
这个例子中,每当areg信号的上升沿出现时把tick信号反相,并且把counter增加1。这种时间控制是always语句最常用的。
always 的时间控制可以是沿触发也可以是电平触发的,可以单个信号也可以多个信号,中间需要用关键字 or 连接,如:
always @(posedge clock or posedge reset)
begin      
  ......
end
always @( a or b or c )  
begin        
  ......        
end
沿触发的always块常常描述时序行为,如有限状态机,如果符合可综合风格要求,则可通过综合工具自动地将其转换为表示寄存器组和门级组合逻辑的结构,而该结构应具有时序所要求的行为;而电平触发的always块常常用来描述组合逻辑的行为,如果符合可综合风格要求,可通过综合工具自动将其转换为表示组合逻辑的门级逻辑结构或带锁存器的组合逻辑结构,而该结构应具有所要求的行为。一个模块中可以有多个always块,它们都是并行运行着的。如果这些always块是可以综合的,则表示的是都某种结构;如果不可综合,它们表示的则是电路结构的行为,因此多个always块并没有前后之分。

task和function说明语句
task和function说明语句分别用来定义任务和函数。利用任务和函数可以把一个很大的程序模块分解成许多较小的任务和函数便于理解和调试。输入、输出和总线信号的值可以传入、传出任务和函数。任务和函数往往还是大的程序模块中在不同地点多次用到的相同的程序段。学会使用task和function语句可以简化程序的结构,使程序明白易懂,是编写较大型模块的基本功。
task和function说明语句的不同
任务和函数有些不同,主要的不同有以下四点:
1) 函数只能与主模块共用同一个仿真时间单位,而任务可以定义自己的仿真时间单位。
2) 函数不能启动任务,而任务能启动其它任务和函数。
3) 函数至少要有一个输入变量,而任务可以没有或有多个任何类型的变量。
4) 函数返回一个值,而任务则不返回值。
函数的目的是通过返回一个值来响应输入信号的值。任务却能支持多种目的,能计算多个结果值,这些结果值只能通过被调用的任务的输出或总线端口送出。Verilog HDL模块使用函数时是把它当作表达式中的操作符,这个操作的结果值就是这个函数的返回值。下面让我们用例子来说明:
例如,定义一任务或函数对一个16位的字进行操作让高字节与低字节互换,把它变为另一个字(假定这个任务或函数名为: switch_bytes)。
任务返回的新字是通过输出端口的变量,因此16位字字节互换任务的调用源码是这样的:
switch_bytes(old_word,new_word);
任务switch_bytes把输入old_word的字的高、低字节互换放入new_word端口输出。
而函数返回的新字是通过函数本身的返回值,因此16位字字节互换函数的调用源码为:
new_word = switch_bytes(old_word);
FFT 发表于 2010-6-28 01:25:48 | 显示全部楼层
呵呵,楼主有心了!
CCIE 发表于 2010-6-28 02:53:18 | 显示全部楼层
搂住的文章好!
usd 发表于 2010-6-28 03:26:19 | 显示全部楼层
bucuo....
inter 发表于 2010-6-28 04:39:38 | 显示全部楼层
期待楼主能再更深更广地讲解TASK和FUNCTION。
HDL 发表于 2010-6-28 04:54:54 | 显示全部楼层
辛苦了~谢谢
CTT 发表于 2010-6-28 05:57:19 | 显示全部楼层
谢谢楼主,好资料!
interig 发表于 2010-6-28 07:22:58 | 显示全部楼层
讲得不错!!!
inter 发表于 2010-6-28 08:26:39 | 显示全部楼层
有启发,实践性的东西,支持。。。。。。。。
tim 发表于 2010-6-28 10:05:02 | 显示全部楼层
谢谢楼主的好帖子
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-4-19 16:42 , Processed in 0.075937 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表