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
相关推荐
im_AMBER5 小时前
Leetcode 77 数组中的最大数对和 | 统计坏数对的数目
笔记·学习·算法·leetcode
代码游侠5 小时前
学习笔记——Linux 进程管理笔记
linux·运维·笔记·学习·算法
解局易否结局5 小时前
GitCode口袋工具开发学习
学习·gitcode
逐辰十七5 小时前
freertos学习笔记12--个人自用-第18章 资源管理(Resource Management)
笔记·学习
点云SLAM5 小时前
Redundant 英文单词学习
人工智能·学习·英文单词学习·雅思备考·redundant·冗余的·多余的 、重复的
phantom_1115 小时前
BeeAI 框架学习记录
学习·ai
wheelmouse77885 小时前
Maven构建配置学习笔记
笔记·学习·maven
DevangLic5 小时前
【怎么在手机上访问部署在电脑上的网页,不在一个局域网】
服务器·学习
Haooog5 小时前
微服务保护学习
java·学习·微服务·sentinel