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
相关推荐
星火开发设计3 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
Gorgous—l3 小时前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
Hello_Embed4 小时前
libmodbus 移植 STM32(基础篇)
笔记·stm32·单片机·学习·modbus
●VON5 小时前
Flutter for OpenHarmony 21天训练营 Day03 总结:从学习到输出,迈出原创第一步
学习·flutter·openharmony·布局·技术
香芋Yu5 小时前
【大模型教程——第四部分:大模型应用开发】第1章:提示工程与上下文学习 (Prompt Engineering & ICL)
学习·prompt
LYS_06185 小时前
寒假学习10(HAL库1+模数电10)
学习
runningshark5 小时前
【项目】示波器学习与制作
学习
€8115 小时前
Java入门级教程24——Vert.x的学习
java·开发语言·学习·thymeleaf·数据库操作·vert.x的路由处理机制·datadex实战
自可乐6 小时前
n8n全面学习教程:从入门到精通的自动化工作流引擎实践指南
运维·人工智能·学习·自动化