绿皮书第三章ref

📅 2026/7/24 22:42:26
绿皮书第三章ref
任务、函数以及void函数任务和函数之间有很明显的区别其中最重要的一点是任务可以消耗时间而函数不能。verilog中的函数必须有返回值。子程序参数高级参数类型verilog中对参数处理方式很简单子程序开头把input和inout的值复制给本地变量在子程序退出时则复制output和inout的值。在SV中参数传递方式可以指定为引用而不是复制。ref1.input与output本质当你把一个变量传给input参数时仿真器会在内存中复制Copy一份一模一样的数据给子程序。子程序在里面怎么折腾这个“副本”外部的那个原变量都毫发无损。只有当子程序执行完返回时如果是output才会把最终结果再Copy回去。痛点如果你传递的是一个超大的数组比如 1024 位的包数据每次调用函数都要在内存里 Copy 一遍仿真器性能会瞬间暴跌。2.ref引用传递指针本质 ref不会复制任何数据。它传递的是变量在内存中的地址。效果子程序直接对外部的那个原始变量进行操作。没有任何内存复制开销速度极快。而且子程序内部对该变量的任何修改外部会实时看到不需要等到子程序结束。小问题1 保护数据不被篡改const refref传递的是地址子程序内部如果一不小心把这个传入的数据改了外部的数据也就被污染了。这在验证中非常危险。 所以如果不仅想提高仿真性能又不想子程序修改这个数组必须加上const修饰符。2task和function都可以用ref吗它们有什么区别task 可以消耗时间#10 posedge clk等时序控制可以使用reffunction不能消耗时间在0仿真时刻内返回 也可以使用ref注意如果在function中使用了ref 那么这个被引用的变量不能在其他地方被并发的进程fork join修改否则就违反了function不能消耗时间的原则。3 automatic 动态生命周期为什么在 SV中使用ref传递参数时子程序通常必须声明为automatic默认情况下verilog的子程序是静态的即内存空间是固定的。在SV验证环境中为了支持递归调用或并发调用多个transaction同时发送子程序必须是动态的。 ref参数要求其指向的变量生命周期也是动态分配的否则多处并发调用会指向同一个静态内存地址导致数据混乱。练习test_sub3.sv上面的代码会报错 因为 const ref 只读不能修改。注释掉 const ref 的函数和initial test3.编译。顺便说一下形参和实参的概念函数print_by_value(input big_data_t data);这里只是一个临时的占位符。它负责在函数内部规定好逻辑。 实参真正的数据当在块里声明了 并调用此时实参的值会被复制到中。运行结果test4.sv练习 1 打印出的是 0xaaaa_aaaa练习 2打印出的是 0x5555_5555易错点用名称绑定// 推荐写法清晰显式绝不会因为逗号数量数错而出错 do_config(.new_cfg(my_config_reg), .status(result));如果把output挪到最前面task automatic do_config(output status_e status, seed 10, ref bit [31:0] new_cfg);此时seed没有显示指定方向它会继承前一个参数status的output方向。可能因为无法把默认值赋给输出端口而触发编译警告。不要依赖隐式方向继承