• 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。

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

    练习主代码: 

    1. module top_tb; //定义module模块
    2. parameter DLY = 2; //定义parameter参数,方便复用,且易于修改
    3. reg [1:0] result_1, result_2; //声明变量
    4. reg co_1,co_2; //声明变量
    5. initial fork
    6. begin //p1
    7. #1; //延迟一个时钟单位
    8. add2x2(2'b01,result_1,co_1); //调用add2x2方法
    9. end
    10. begin //p2
    11. #DLY; //延迟2个时钟单位
    12. add2x2(2'b01,result_2,co_2); //调用add2x2方法
    13. #(DLY*4); //延迟8个时钟单位
    14. end
    15. join
    16. //defaut static task
    17. task add2x2(input[1:0] opt,output[1:0] result,output co);
    18. reg [1:0] temp; //定义中间变量
    19. begin
    20. temp=opt; //将方法输入值赋值中间变量temp
    21. #(DLY*2); //延时4个时间单位
    22. $display("static task: %t :temp is %0d",$time,temp);
    23. {co,result}=temp+2'b10; //输出
    24. end
    25. endtask
    26. 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一样呢?

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

     

  • 相关阅读:
    学习 Rust 的第十二天:如何使用向量
    报错解决:libcudart.so和libprotobuf.so链接库未找到
    六、vpp 流表+负载均衡
    【Python爬虫三天从0到1】Day1:爬虫核心
    Mac上.bashrc转.zshrc时,设置PATH环境变量注意事项
    【JS】常用正则表达式
    【操作系统】进程间的通信——管道
    一种使用Java的快速将Web中表格转换成Excel的方法
    Day112.尚医通:手机验证码登录功能
    LeetCode233数字1的个数-容易理解的组合数学方法
  • 原文地址:https://blog.csdn.net/weixin_45680021/article/details/126375662