异步FIFO-3

本文详细介绍了如何使用Questa进行覆盖率收集操作,包括编译、仿真、查看覆盖率、合并覆盖率以及生成HTML报告。同时,文中还阐述了如何实现功能覆盖率,如时钟测试(写快读慢、写慢读快)、异常测试(写满、读空)以及读写带复位的测试方法。
摘要由CSDN通过智能技术生成

1.覆盖率收集操作(Questa)

http://t.csdn.cn/cxRIM
https://github.com/pzressinno/My
原代码基于vcs+verdi,用于questa时需要部分修改

不要添加tb.v
留下fifo_if.sv
tb.sv原代码存在报错

# UVM_WARNING @ 0: reporter [BDTYP] Cannot create a component of type 'read_fast_test' because it is not registered with the factory.
# UVM_FATAL @ 0: reporter [INVTST] Requested test from command line +UVM_TESTNAME=read_fast_test not found.

在tb中添加

import asyn_fifo_test_pkg::*;

1.1编译

1.new-project
1.逐一添加rtl、sv文件,compile后将除了pkg以外的remove
2.选中所有的.v文件,编译设置

点开【Coverage】即覆盖率一栏,点击选中需要的项目,然后点击【OK】即可

3.调整编译顺序,让设计代码先编译,让底层代码先编译,在空白处点击右键,选择【Compile】->【Compile Order…】
点击【Auto Generate】,让其自动识别
4.最后对其全部编译

1.2仿真

1.使用命令编译

vsim -i -novopt -classdebug -solvefaildebug -coverage -coverstore ./mti_covdb -testname as_fifo_random -sv_seed random 
+UVM_TESTNAME=read_fast_test work.asyn_fifo_tb

-novopt:编译时不作优化
-solvefaildebug=,使能随机化失败调试,如果value不给值,则使能基本调试功能
-coverage: 会在仿真时产生代码覆盖率数据
-coverstore ./mti_covdb: 在当前的mti_covdb文件夹下生成一个覆盖率数据文件(.data)
-testname as_fifo_random: 本次仿真的名称,后续生成的覆盖率数据文件名为{testname}_{Sv_Seed}
-sv_seed random,用于指定仿真时的随机种子
+UVM_TESTNAME=read_fast_test:TESTNAME参数,我们会在tb.sv文件中用到,作为传入参数选择不同的测试用例

编译完成后如下所示,并获得随机化的种子 2195086157,这样我们得到的覆盖率数据文件为as_fifo_random_2195086157.data

2.使用run -all命令让其跑完整个测试
然后会弹出询问是否结束测试,我们选择【否】,因为选择是会退出软件
3.使用break
4.再使用quit -sim命令结束仿真
结束仿真才能得到覆盖率数据文件

1.3查看覆盖率

1.已经关闭了仿真,所以没有当前的覆盖率了,我们再次运行仿真,仿真完成后我们不关闭
即编译-run -all-break(不quit)

2.把覆盖率文件.data转换为.ucdb,命令行执行

coverage save mti_covdb/as_fifo_random_2195086157.ucdb

coverage save 文件夹/覆盖率文件名.ucdb

3.直接用仿真器即可打开这个UCDB覆盖率数据库,点击【File】->【Open…】

1.4合并覆盖率

1.多跑几次仿真(不同种子)或者使用不同的测试用例跑仿真,每一次仿真都会得到一个覆盖率文件,最后可以将这些覆盖率都合并
命令行执行

vcover merge -out ucdb1/merged1.ucdb mti_covdb/*.ucdb

输出的merge文件所在文件夹/merge文件名.ucdb 需要被merge的所有文件所在文件夹/*.ucdb

2.可以查看merge中单个覆盖率文件的,点击【View】->【Verification Management】->【Browser】打开【Browser】窗口
然后再其窗口中右击选择【Add File…】,将【merged】添加进来可以看到其下的每个覆盖率文件

1.5生成html文件

1.点击【Tools】->【Coverage Report】->【HTML…】
2.勾选需要的选项

然后就会在浏览器打开如下所示的HTML文件了

3.也可以使用命令行指令

vcover report -html -htmldir covhtmlreport -source -assert -directive -cvg -code bcefst -threshL 50 -threshH 90 merged1.ucdb

vcover report -html -htmldir covhtmlreport -source -assert -directive -cvg -code bcefst -threshL 50 -threshH 90 merge文件名.ucdb

1.6分析覆盖率文件

参考http://t.csdn.cn/r8Ehr

设置忽略的选项

e.g若ctrl_regs_inst中的cmd_data_reg信号的Toggle覆盖率低
重新回到QuestaSim软件,打开【Analysis】窗口,选中【ctrl_regs_inst】打开
然后将关注点转为【Toggle】
可以看到,【cmd_data_reg】的5-31位都是没有覆盖到的,而且实际的设计上【cmd_data_reg】的6-31位就是没有使用的,我们可在覆盖率分析时将其忽略,如下所示,选中6-31位,右键选中【Exclude with Comment…】将其忽略掉
然后输入提交信息【reasonable for register value boundary limit】表示该忽略是合理的
接下来我们再次生成一次网页,可以看到覆盖率是上升了的


2.如何实现功能覆盖率

2.1时钟测试

在tb中初始化时钟

	// Configurable wclk
	initial begin
        wclk = 0;
        #10
        //if(uvm_config_db#(real)::get(uvm_root::get(),"uvm_test_top","wclk_half_period",wclk_half_period))  //In test config
        if(uvm_config_db#(int)::get(uvm_root::get(),"uvm_test_top.m_env.m_wf_agent.m_sequencer","wclk_half_period",wclk_half_period))
            `uvm_info("WCLK",$sformatf("Configure the wclk_half_period = [%0d]",wclk_half_period),UVM_NONE)
        else begin
            `uvm_info("WCLK","Can't configure wclk with config_db correctly,will use default value:10",UVM_MEDIUM)
            wclk_half_period = 10;
        end
        forever begin 
            #wclk_half_period wclk = ~wclk;
        end
    end

	// Configurable rclk
	initial begin
        rclk = 0;
        #10
        if(uvm_config_db#(int)::get(uvm_root::get(),"uvm_test_top.m_env.m_rf_agent.m_sequencer","rclk_half_period",rclk_half_period))
            `uvm_info("RCLK",$sformatf("Configure the rclk_half_period = [%0d]",rclk_half_period),UVM_NONE)
        else begin
            `uvm_info("RCLK","Can't configure rclk with config_db correctly,will use default value:10",UVM_MEDIUM)
            rclk_half_period = 10;
        end
        forever begin 
            #rclk_half_period rclk = ~rclk;
        end
    end

如果在test config中对时钟周期wclk_half_period设置,则get该设置,没有设置则读写时钟都为#10翻转一次

2.1.1写快读慢

class write_fast_test extends asyn_fifo_test_base;

task write_fast_test::run_phase(uvm_phase phase);
    write_fast_vseq vseq = write_fast_vseq::type_id::create("vseq");
    vseq.start(null);
class write_fast_vseq extends asyn_fifo_vseq_base;
    int wclk_half_period = 10;
    int factor = 7;    
 
 task write_fast_vseq::body();
    write_seq        wr_seq;
    read_seq         rd_seq;
    wrstn_config_seq wrstn_cfg_seq;
    rrstn_config_seq rrstn_cfg_seq;
    wclk_config_seq  wclk_cfg_seq;
    rclk_config_seq  rclk_cfg_seq;
    fork
        `uvm_do_on(wrstn_cfg_seq,wf_sqr)			//产生1个写复位信号传给写sequencer
        `uvm_do_on(rrstn_cfg_seq,rf_sqr)
        //产生一个随机的写时钟周期,并约束wclk_half_period =10,rclk_half_period =7*10=70,即写快读慢
        `uvm_do_on_with(wclk_cfg_seq,wf_sqr,{wclk_half_period == local::wclk_half_period;})
        `uvm_do_on_with(rclk_cfg_seq,rf_sqr,{rclk_half_period == local::wclk_half_period*factor; })
    join_none
    
//重复5次产生写seq,50秒后重复5次读操作
    repeat(5)
        `uvm_do_on(wr_seq,wf_sqr)
    #50
    repeat(5)
        `uvm_do_on(rd_seq,rf_sqr)
    #100    
    fork
             repeat(100)
            `uvm_do_on_with(wr_seq,wf_sqr,{pkt_idles == 0;})
        repeat(100)
            `uvm_do_on(rd_seq,rf_sqr)
    join    
    #500;
endtask : body

在wrstn_config_seq 实现复位

task wrstn_config_seq::body();
    super.body();
        if(wrst_en)
				begin 
					@(negedge cfg.m_wf_cfg.FIFO.wclk);
					cfg.m_wf_cfg.FIFO.wrst_n = 0; 
					repeat(resetn) 
						@(negedge cfg.m_wf_cfg.FIFO.wclk);
					cfg.m_wf_cfg.FIFO.wrst_n = 1; 
                end
        else begin
				cfg.m_wf_cfg.FIFO.wrst_n = 0;
				repeat(5)
					@(posedge cfg.m_wf_cfg.FIFO.wclk);
				cfg.m_wf_cfg.FIFO.wrst_n = 1;
             end
endtask : body

在wclk_config_seq 随机时钟周期并传给tb,rclk_config_seq 相同

class wclk_config_seq extends uvm_sequence;
    rand int wclk_half_period;
    
task wclk_config_seq::body();
    uvm_config_db#(int)::set(m_sequencer,"","wclk_half_period",wclk_half_period);
    `uvm_info("WCLK",$sformatf("Configure the wclk half period = [%0d]",wclk_half_period),UVM_MEDIUM)
endtask : body

在write_seq

class write_seq extends uvm_sequence #(fifo_seq_item);

task write_seq::body();
    fifo_seq_item req;
    `uvm_do_with(req,{cmd == 1;pkt_idles == local::pkt_idles;})		//cmd在driver中决定write '1' or read '0'  

2.1.2读快写慢

2.2异常测试

2.2.1写满

深度为16,连续写20个数据进去,从第16个数之后wfull拉高

2.2.2读空

连续读20个数据,从第16个数之后rempty拉高

2.3 读写带复位

class wr_with_reset_test extends asyn_fifo_test_base;

task wr_with_reset_test::run_phase(uvm_phase phase);
    wr_with_reset_vseq vseq = wr_with_reset_vseq::type_id::create("vseq");
    vseq.start(null);
endtask : run_phase
class wr_with_reset_vseq extends asyn_fifo_vseq_base;

task wr_with_reset_vseq::body();
    write_seq        wr_seq;		
    read_seq         rd_seq;		
    wrstn_config_seq wrstn_cfg_seq;
    rrstn_config_seq rrstn_cfg_seq;
    
    wrstn_seq        wrstn_seq;
    rrstn_seq        rrstn_seq;

    fork
        `uvm_do_on(wrstn_cfg_seq,wf_sqr)
        `uvm_do_on(rrstn_cfg_seq,rf_sqr)
    join_none
    
    // Continuously write 20 datas
    repeat(20)
        `uvm_do_on(wr_seq,wf_sqr)
    
    env_cfg.wait_for_wclk(5);
    
    // Continuously read  20 datas
    repeat(20)
        `uvm_do_on(rd_seq,rf_sqr)
    env_cfg.wait_for_rclk(5);

    fork
        repeat(50)
            `uvm_do_on(wr_seq,wf_sqr)
        repeat(50)
            `uvm_do_on(rd_seq,rf_sqr)
        begin #200 `uvm_do_on_with(wrstn_cfg_seq,wf_sqr,{resetn == 5;wrst_en == 1;}) end
        begin #200 `uvm_do_on_with(rrstn_cfg_seq,rf_sqr,{resetn == 5;rrst_en == 1;}) end
    join    

在wrstn_config_seq 实现复位
重复20次产生写seq,后重复20次读操作
在重复读写50次操作开始后间隔#200在在wrstn_config_seq 实现写复位和读复位

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值