SVA学习之路(1)— SystemVerilog Assertion简介与实战

SVA学习之路(1)--- SystemVerilog Assertion简介与实战

一、前言

在数字电路设计验证中,传统的验证方法往往需要编写大量的测试向量和复杂的测试环境。然而,随着设计复杂度的增加,这些方法变得越来越低效。SystemVerilog Assertion(SVA)作为一种声明式验证方法,正成为硬件验证工程师的必备技能。

SVA允许你在设计中直接嵌入属性描述,实时监控设计行为,及早发现错误,大大提高验证效率和设计质量。

SVA是SystemVerilog语言的一部分,专门用于描述设计行为的时序属性。它不改变设计功能,而是作为"监控器"嵌入到设计中,检查设计是否按照预期行为运行。

二、立即断言(Immediate Assertions)

立即断言在当前仿真时刻立即检查条件是否成立,不依赖时钟,类似于if语句中的条件检查,语法简单,适合检查组合逻辑或单周期信号。​

编写代码文件tb.sv如下所示

systemverilog 复制代码
module tb;
    reg a,b;

    initial begin
        a = 0; b = 0;

        #10ns; a = 1;
        assert(a&b);

        #10ns; b = 1;
        assert(a&b);
        
        #10ns; a = 0;
        assert(a&b);
    end

    initial begin
        $timeformat(-9, 2, "ns", 10);
        $fsdbDumpfile("test.fsdb");
        $fsdbDumpvars(0, tb);
        $fsdbDumpSVA(0, tb);
        #100ns;
        $finish(2);
    end

endmodule

编写运行makefile文件如下所示:

bash 复制代码
all: comp sim

comp:
	vcs -full64 -kdb -sverilog -debug_access+all -timescale=1ns/1ps tb.sv

sim:
	./simv

verdi:
	verdi tb.sv -ssf test.fsdb &

运行日志如下,可以看到打印了两次失败

使用verdi查看如下所示,在波形上可以看到两次失败的示意箭头

三、并发断言(Concurrent Assertions)

并发断言是基于时钟边沿检测时序逻辑的行为。它在仿真过程中持续检测监控信号的时序关系。

区别即时断言和并发断言的关键词是"property",编写代码文件tb.sv如下所示

systemverilog 复制代码
module tb;
    reg a,b;
    reg clk;

    assert property(
        @(posedge clk) a&b==1'b1
    );

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

    initial begin
        a = 0; b = 0;
        #10ns; a = 1;
        #10ns; b = 1;
        #10ns; a = 0;
    end

    initial begin
        $timeformat(-9, 2, "ns", 10);
        $fsdbDumpfile("test.fsdb");
        $fsdbDumpvars(0, tb);
        $fsdbDumpSVA(0, tb);
        #100ns;
        $finish(2);
    end

endmodule

运行日志如下,可以看到打印了多次失败

使用verdi查看如下所示,在波形上可以看到多次失败的示意箭头

如果想要查看成功的示意箭头,添加运行时选项如下所示:

powershell 复制代码
	./simv +fsdb+sva_success

重新查看波形如下所示,可以看到成功的示意箭头

四、时钟检测

编写如下代码检测时钟信号clk,频率为10MHz,占空比为50%。

verilog 复制代码
module tb;
    reg clk;
    reg rst_n;

    // Clock genrate
    initial begin
        clk = 1'b0;
        forever begin
            #50 clk = 1'b1;
            #50 clk = 1'b0;
        end
    end

    // Reset genrate
    initial begin
        rst_n <= 1'b0;
        repeat(10) @(posedge clk);
        rst_n <= 1'b1;
    end

    // ==================== SVA ====================
    // Check 10MHz, period for 100ns
    property clk_period_check;
        realtime rise_time, current_period;
        @(posedge clk)
        disable iff (!rst_n)
        (1, rise_time = $realtime)
        ##1 (clk === 1'b0, current_period = $realtime - rise_time)
        ##0 (current_period) inside {[99900ps:100100ps]};
    endproperty
    
    // Check 50% duty
    property clk_duty_cycle_check;
        realtime rise_time, duty_time;
        @(posedge clk)
        disable iff (!rst_n)
        (1, rise_time = $realtime) |->
        @(negedge clk) (clk === 1'b1, duty_time = $realtime - rise_time)
        ##0 (duty_time) inside {[49900ps:50100ps]};
    endproperty
    
    check_clk_period : assert property (clk_period_check) 
        else $error("Clock period error! Expected 100ns");

    check_clk_duty_cycle : assert property (clk_duty_cycle_check)
        else $error("High level duty cycle error! Expected 50ns");

    initial begin
        $timeformat(-9, 2, "ns", 10);
        $fsdbDumpfile("test.fsdb");
        $fsdbDumpvars(0, tb);
        $fsdbDumpSVA(0, tb);
        #100us;
        $finish(2);
    end

endmodule
相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习