从头到尾创建自己的仿真编译flow

本文档展示了如何使用自动化脚本来生成和运行Verilog测试平台,特别是针对dff设计的BASETestbench。脚本包括了对各种操作场景的检查,如默认重置值、写使能、禁止写入等,并通过自定义宏进行断言检查。此外,还提供了一个批量生成测试平台的Python脚本,以及一个用于Shell中批量运行仿真和编译的脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BASE Testbench长这样:

/
// This is a wrapper tb for a dff design
// VERSION:   v0.1
// Wrapper TB
// Below are the trial wrapper testbench, able to dump waveforms
/

`define CHECKER(CHKNAME, PROPERTY, ERROR_CODEBLOCK, ERROR_MSG, PASS_CODEBLOCK, PASS_INFO) \
  if (!(PROPERTY)) begin \
    $error("`CHKNAME`", ": ", ERROR_MSG); \
    ERROR_CODEBLOCK \
  end \
  else begin \
    PASS_CODEBLOCK \
    $display("`CHKNAME`", ": ", PASS_INFO); \
  end \
  CHKNAME: assert(PROPERTY);

module test;

  parameter PERIOD = 2;
  parameter width = 8;
  parameter reset_value = 0;
  reg       [width-1 : 0] data_in;
  reg       clk;
  reg       rst_n;
  reg       enable;
  wire      [width-1 : 0] data_out;
  
  // test variables
  reg       [width-1 : 0] expected_result;

  // Instance of DW03_reg_s_pl
  DW03_reg_s_pl #(width, reset_value)
  U0 (.d(data_in), .clk(clk), .reset_N(rst_n),
  .enable(enable), .q(data_out));

  always #(PERIOD/2) clk=~clk;

  initial begin
    // Dump waves
    $fsdbDumpfile("testname.fsdb");
    $fsdbDumpvars("+all");
  end

  initial begin
    #100 $finish;
  end

  initial begin
    $display($time, " <<<<<< Starting the Simulation >>>>>>");
    data_in = 0;
    rst_n = 1'b1;
    clk = 1;
    rst_n = 1'b0;
    enable = 0;
    expected_result = 0;

    #PERIOD;
    rst_n = 1;
    enable = 0;
    // RST_VAL_DEFAULT
    expected_result = reset_value;
    $display("Executing RST_VAL_DEFAULT check");
    `CHECKER( RST_VAL_DEFAULT,
              expected_result == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

    // WR_ENABLE
    reset_stimulus();
    $display("Executing WR_ENABLE check");
    #PERIOD;
    data_in = 'h10;
    enable = 1;
    expected_result = data_in;
    #PERIOD; 
    `CHECKER( WR_ENABLE_0,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

    reset_stimulus();
    data_in = 'h11;
    enable = 1;
    expected_result = data_in;
    #PERIOD; 
    `CHECKER( WR_ENABLE_1,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);


    // WR_DISABLE
    reset_stimulus();
    $display("Executing WR_DISABLE check");
    #PERIOD enable = 0;
    #PERIOD data_in = 'h11; // hold data_in half a clock wait for sample enable at rising edge of clk
    #PERIOD data_in = 'h15;
    expected_result = 'h11;
    #PERIOD; 
    `CHECKER( WR_DISABLE,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);


    // CONST_D_CONST_Q
    reset_stimulus();
    $display("Executing CONST_D_CONST_Q check");
    #PERIOD enable = 0;
    #PERIOD data_in = 'h0f;
    #PERIOD; 
    `CHECKER( CONST_D_CONST_Q_0,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

    #PERIOD enable = 1;
    #PERIOD data_in = 'h0f;
    expected_result = data_in;
    #PERIOD; 
    `CHECKER( CONST_D_CONST_Q_1,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);


    // BURST_TO_WRITE
    reset_stimulus();
    $display("Executing BURST_TO_WRITE check");
    #PERIOD enable = 1;
    #PERIOD data_in = 'ha;
    #PERIOD data_in = 'hb;
    #PERIOD data_in = 'hc;
    #PERIOD data_in = 'hd;
    #PERIOD data_in = 'he;
    expected_result = data_in;
    #PERIOD; 
    `CHECKER( BURST_TO_WRITE,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

    // RST_SYNC
    reset_stimulus();
    $display("Executing RST_SYNC check");
    #PERIOD enable = 1;
    #PERIOD data_in = 'ha;
    #(PERIOD/2) rst_n = 'h0;
    #(PERIOD/2) rst_n = 'h1;
    expected_result = data_in;
    #PERIOD; 
    `CHECKER( RST_SYNC,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

    // ENABLE_POS_SENC
    reset_stimulus();
    $display("Executing ENABLE_POS_SENC check");
    #PERIOD enable = 1;
    #PERIOD data_in = 'ha;
    #(PERIOD/2) enable = 'h0; data_in = 'hf;
    #(PERIOD/2) enable = 'h1;
    expected_result = 'ha;
    `CHECKER( ENABLE_POS_SENC,
              data_out == expected_result,
              ,
              ("error"),
              ,
              ("checked ok")
              )
    $display("expected_result = %0h, data_out = %0h", expected_result, data_out);

  end

  task display;
    $display("Enable:%0h, Input:%0h, Output:%0h, width = %0h",
    enable, data_in, data_out, width);
  endtask


  task reset_stimulus();
    #PERIOD enable = 0;
    #PERIOD data_in = 'h0;
    $display("Reset the stimulus: enable = %0h, data_in = %0h", enable, data_in);
  endtask



endmodule


批量生成tb的PY脚本

import os
import numpy as np

numbers = 32

for number in range(numbers):
	count = 1
	count_tb = 1
	count_rst_val = 1
	rst_val = 1
	if number > 1:
		#print(number)
		rst_val = np.random.randint(1, 2**number-1)
		#print(rst_val)
	file_name = 'tb_width_' + str(number) + '.sv'
	with open(file_name, mode='w') as f2:
		with open('testbench.sv') as f:
			while True:
				string = f.readline()
				if len(string) == 0:
					break
				if count_tb == 22:
					string = string[:-2] + f'{number};\n'
					print(string)
				if count == 25:
					string = string[:-3] + f'{number};\n'
				if count_rst_val == 26:
					print("wut")
					string = string[:-3] + f'{rst_val};\n'
					print(string)
				f2.write(string)
				count += 1
				count_tb += 1
				count_rst_val += 1

	f2.close()
	f.close()

在shell批量跑仿真和编译

#!/bin/sh
# set the variable width
WIDTH="10"

for ((WIDTH=0; WIDTH<=31;WIDTH++))
  do
    echo "WIDTH is: $WIDTH"
    vcs ../tb/tb_width_$WIDTH.sv ../design/dff.v -kdb -debug_access+all -debug_region+cell+encrypt \
        +v2k -sverilog -kdb \
        -l vcs.log \
        -timescale=1ns/1ps \
        -o simv \
        +vcs+vcdpluson \
        -cm line+cond+tgl+branch+assert \
        -cm_name test_$WIDTH 这一步是为了在simv.vdb地下生成单独的test data
    
    simv -l ./results/tb_width_$WIDTH.log

done 

回到shell merge URG:

urg -full64 -metric line+tgl+cond+fsm+assert+branch -warn none -dbname merged_cov.vdb -dir simv.vdb/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值