SVA中的局部变量和子程序

局部变量

局部变量是动态存在于属性或者序列中的,对其他属性或者序列不可见,即不能在其他属性或者序列中引用,当其所在的属性或者序列执行完毕其生命周期也就宣告结束了。局部变量的使用方法是将局部变量接着子序列放置,两者用逗号隔开,并且置于同一个小括号中,如果自序列匹配,那么变量赋值语句即被执行,每次序列检查匹配结束时,会重新产生变量的一个备份。



【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3;
logic [3:0] num_src,num_des;

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end

initial begin
    sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;sig3 = 1'b0;
    num_src = 4'b0000;num_des = 4'b0000;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0001;
    #2 sig1 = 1'b1;sig2 = 1'b0;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0101;
    #2 sig1 = 1'b1;sig2 = 1'b0;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0110;
    #2 sig3 = 1'b1;num_des = 4'b0001 + 4'b0101 + 4'b0110;
    #2 sig3 = 1'b0;#6 $stop;
end

sequence s;
int lvar = 0;
    (sig1 ##1 sig2,lvar = lvar +num_src)[*3] ##1 ($rose(sig3) && (lvar == num_des));
endsequence // s
property p;
    @(posedge clk) $rose(sig0) |-> ##1 s;
endproperty // p
a : assert property(p) $info("@%0t | p : PASSED!",$time);
    else $info("@%0t | p : FAILED!",$time);
endmodule // top_tb
【仿真结果】

示例中,检测到sig0出现上升沿一个采样周期后,子序列“(sig1 ##1 sig2,lvar = lvar +num_src)”匹配了三次,并且在这三次发生的过程中,num_src的值在每次“sig1##1 sig2”匹配时都会累加到局部变量lvar中。三次匹配完成后的一个采样周期sig3拉高的同时比较lvar中的累加的值是否与此时num_des中的值相等,如果想等,则断言匹配成功,反之失败。在使用局部变量时要注意以下几点:

  • 在有形式参数的属性或者序列中,局部变量名不能与形参名相同;

  • 局部变量不能用于延迟范围中指示延迟,因为延迟范围需要在代码析构时就必须确定,而局部变量只有在调用时才存在;

  • 局部变量不能用于信号位宽的指定,因为信号位宽需要在代码析构时就必须确定,而局部变量只有在调用时才存在;

  • 局部变量仅限于在当前定义的序列或者属性中可见;


调用子程序

【注】本小节中将functiontask统称为子程序,仅为描述方便。

SVA除了可以检测一些属性序列外,还可以在断言中调用一些子程序,实现一些复杂的功能,也可以将序列或者属性中的局部变量作为参数传递给子程序,辅助断言对设计属性的描述。其使用格式与局部变量类似,都是用逗号将其与子序列分割,但是通过小括号将其与子序列组织在一起。



【示例】
`timescale 1 ns / 1 ps
module top_tb;
logic clk;
logic sig0,sig1,sig2,sig3;
logic [3:0] num_src,num_des;

initial begin
    clk = 1'b0;
    forever #1 clk = ~clk;
end

initial begin
    sig0 = 1'b0;sig1 = 1'b0;sig2 = 1'b0;sig3 = 1'b0;
    num_src = 4'b0000;num_des = 4'b0000;
    #2 sig0 = 1'b1;
    #2 sig0 = 1'b0;sig1 = 1'b1;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0001;
    #2 sig1 = 1'b1;sig2 = 1'b0;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0101;
    #2 sig1 = 1'b1;sig2 = 1'b0;#2 sig1 = 1'b0;sig2 = 1'b1;num_src = 4'b0110;
    #2 sig3 = 1'b1;num_des = 4'b0001 + 4'b0101 + 4'b0110;
    #2 sig3 = 1'b0;#6 $stop;
end

sequence s;
int lvar = 0;
    (sig1 ##1 sig2,lvar = lvar +num_src)[*3] ##1 ($rose(sig3) && (lvar == num_des),disp(lvar));
endsequence // s
property p;
    @(posedge clk) ($rose(sig0),disp(4'b0000)) |-> ##1 s;
endproperty // p
a : assert property(p) $info("@%0t | p : PASSED!",$time);
    else $info("@%0t | p : FAILED!",$time);
// task&nbs***bsp;function
task disp(input int lvar);
    $display("@%0t %m local var : %h happened!",$time,lvar);
endtask // disp
endmodule // top_tb
【仿真结果】

示例中,子程序的用法与局部变量类似,都是附加在相应的子序列之后,用逗号分隔。在$rose(sig0)匹配时,调用了子程序disp。在sequence s匹配的最后,也调用了子程序,同时将局部变量传递给了子程序disp,子程序在每次调用后都会对传入的变量值进行一定的处理。

SVA中,合理的使用局部变量和子程序可以实现更加复杂的功能描述,同时增加了断言检查的灵活性。但是一般不要将设计结构的实现放在SVA中的子程序中,因为断言一般仅用于检查,不用于具体的电路的实现,通常的综合工具不会将断言实现为具体的电路。


全部评论
了解SVA中的局部变量和子程序
点赞 回复 分享
发布于 2022-10-16 16:21 河南

相关推荐

不愿透露姓名的神秘牛友
07-08 14:08
点赞 评论 收藏
分享
06-15 02:05
已编辑
南昌航空大学 数据分析师
Eason三木:你如果想干技术岗,那几个发公众号合唱比赛的经历就去掉,优秀团员去掉,求职没用。然后CET4这种不是奖项,是技能,放到下面的专业技能里或者单独列一个英语能力。 另外好好改改你的排版,首行缩进完全没有必要,行间距好好调调,别让字和标题背景黏在一起,你下面说能做高质量PPT你得展现出来啊,你这简历排版我用PPT做的都能比你做的好。 然后自我评价,你如果要干数据工程师,抗压能力强最起码得有吧。
简历中的项目经历要怎么写
点赞 评论 收藏
分享
zzzzhz:兄弟你先猛猛投简历至少三百家,能约到面试就去面。最近可以速成智能小车,智慧家居烂大街的项目,不需要自己写,只需要把里面的代码讲解看明白就行。把其中涉及到的八股文都拿出来单独背一下,我去年找工作就一个智能小车智慧家居找了10k差不多。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务