1.static 与 automatic 的“是与非”

写在前面:

  • 在module、program、interface、task和function之外声明的变量拥有静态的生命周期,即存在于整个仿真阶段。
  • 在module、interface和program内部声明,且在task、process或者function外部声明的变量也是static变量,且作用域在该块中。
  • 在module、interface和program中定义的task、function默认都是static类型。
  • 在过程块中(task、function、process)定义的变量均跟随它的作用域,即过程块的类型,如果过程块为static,则它们也默认为static,反之亦然。这些变量也可以由用户显式声明为automatic或者static。

针对以上内容我们进行简单的代码练习,以做到更深入的了解其中含义,话不多说,直接上号!!!

练习主代码: 

module top_tb;                        //定义module模块
parameter DLY = 2;                    //定义parameter参数,方便复用,且易于修改
reg [1:0] result_1, result_2;         //声明变量
reg 	  co_1,co_2;                  //声明变量
initial fork         
	begin   //p1
	#1;                               //延迟一个时钟单位
	add2x2(2'b01,result_1,co_1);      //调用add2x2方法
	end
	
	begin   //p2
	#DLY;                             //延迟2个时钟单位
	add2x2(2'b01,result_2,co_2);      //调用add2x2方法
	#(DLY*4);                         //延迟8个时钟单位
	end
join

//defaut static task
task add2x2(input[1:0] opt,output[1:0] result,output co);
reg [1:0] temp;                       //定义中间变量
begin
	temp=opt;                         //将方法输入值赋值中间变量temp
	#(DLY*2);                         //延时4个时间单位
	$display("static task: %t :temp is %0d",$time,temp);
	{co,result}=temp+2'b10;           //输出
end
endtask
endmodule

代码分析: 

仿真运行解析:

1.@0ns,编译完成,initial结构中使用fork...join块结构,内部的两个begin...end是并行运行的,但是每个begin...end是顺序执行。所以在0ns,语句被阻塞到断点1(进程1)和3(进程2);

2.@1000(由于时间精度是ps,时间单位是ns,此处1个时间单位显示1000ps),等到1000ps后,进程1执行断点2的方法,方法内部的赋值语句temp=opt同时执行,temp=2‘b01, 阻塞到断点7;

3.@2000由于DLY=2,在2000ns时,原本阻塞在断点3的进程2开始执行,进入方法内部,

赋值语句temp=opt同时执行,temp=2‘b10, 阻塞到断点7;

4.@5000,进程1在断点7等到执行信号,开始执行display和下边的断点8语句。

5.@6000,进程2在断点7等到执行信号,开始执行display和下边的断点8语句

 ??????????????????????????????????????????

上边的解析是否可以帮助你理清前5个时钟周期的运行顺序呢?在理解仿真运行的过程中,不知你是否会有以下疑问:

在1000ns时,进程1temp被赋值 2‘b01,在2000ps时,进程2temp被赋值 2‘b10, 那5000ps时进程1display 中temp打印的值究竟是多少?6000ps时进程2display 中temp打印的值究竟是多少?

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

仿真结果:

为什么会使这样呢?

这是因为在module模块中,如果没有特殊声明, 在task、process或者function外部声明的变量都是static变量,且作用域在该块中。在module、interface和program中定义的task、function默认都是static类型。那是不是可以认为在module中,如果没有特殊声明,内部的变量和方法,函数都是static,从仿真开始时被创建,在执行过程中不会被销毁,类似于全局变量,具有静态的声明周期,可以被多个进程和方法共享。(目前看应该是这样的),所以进程1与进程2调用同一个task时,后调用的进程会覆盖前边调用进程的值,就会出现进程1的temp=2‘b01被进程2的temp=2‘b10覆盖掉,最后5000ps和6000ps temp的输出结果都是2.

=============================static终止线=================================== 

那有什么方法可以使最后5000ps时temp的输出值为进程1的输入值1,6000ps时temp的输出值为进程2呢?不妨先分析一下,上边在5000ps和6000ps输出一样的结果,原因是两个进程公用了同一个储存空间,使得后边进来的值会一直将前边的值覆盖掉,那是不是给每个进程的值都有自己的进程空间,就会避免这样的情况发生,赶快尝试一下吧!

============================automatic起始线================================  

将静态方法修改为动态方法

仿真结果:

将task声明为automatic,得到预想中的答案,automatic task为每一个进程中的temp都开辟了临时的储存空间,但是它的生命周期只局限于从task开始执行到结束。 

可有曾想过,如果不将task定义为automatic,只将task内部的temp变量声明为automatic是不是最后得到的结果和将task声明为automatic一样呢?

各位小伙伴赶快动手试一下吧!!! 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

创芯人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值