testbench的框架编写

1.testbench的主要模块构成

(1)头文件

#include <iostream>

#include <stdlib.h>

verilator附带的两个头文件,访问verilator的内容,把波形写入vcd文件:

#include <verilated.h>

#include <verilated_vcd_c.h>

包含我们的Verilated ALU模块的顶级类:

#include "Valu.h”

Valu___024unit.h”包含typedef枚举的Verilated版本:

#include "Valu___024unit.h”

(2)参数定义

仿真的最长时间:

#define MAX_SIM_TIME 300

开始验证的起始时间(需要在复位完成之后):

#define VERIF_START_TIME 7

表示仿真的时间(注意不是真实的时间):

vluint64_t sim_time = 0;

表示上升沿的计数器: vluint64_t posedge_cnt = 0;

(3)main 函数 int main(int argc, char argv, char** env)** {

用于产生随机数:

Verilated::commandArgs(argc, argv);

调用Valu.h中的内容:

*Valu dut = new Valu;

导出VCD波形需要加此语句:

Verilated::traceEverOn(true);

调用verilated_vcd_c.h里面的内容:

*VerilatedVcdC m_trace = new VerilatedVcdC;

dut->trace(m_trace, 5); 打开vcd:

m_trace->open("waveform.vcd");

main函数中设定主循环:

只有当**(sim_time < MAX_SIM_TIME)** 才进入循环。

主循环中执行的主要内容:

(1)通过异或的方式生成时钟信号:

dut->clk ^= 1;

(2)计算当前循环的输出结果:

dut->eval();

(3)时钟上升沿计数器赋值:

if (dut->clk == 1)

{ posedge_cnt++;

}

(4)复位信号的产生:

采用函数的形式产生:

函数:dut_reset(dut, sim_time);

复位函数:将例化的dut指针传递给函数,以及sim_time 指针传递给函数

void dut_reset (Valu *dut, vluint64_t &sim_time)
{     
    dut->rst = 0; 
    if(sim_time >= 3 && sim_time < 6)
    { 
        dut->rst = 1; 
        dut->a_in = 0;     
        dut->b_in = 0;     
        dut->op_in = 0; 
        dut->in_valid = 0; 
    } 
}

(5)把sim_time传递给m_trace

**m_trace->dump(sim_time);**

(6)该时间内完成所有任务之后,sim_time自加

sim_time++;

(7)对输入信号施加激励,于此同时,验证输出结果的正确性。采用switch case 的语句进行:

switch (posedge_cnt){
    case 10:
        dut->in_valid = 1;
        dut->a_in = 5;
        dut->b_in = 3;
        dut->op_in = Valu___024unit::operation_t::add;
        break;
     case 12:
        if (dut->out != 8)
            std::cout << "Addition failed @ " << sim_time << std::endl;
            break;

     case 20:
         dut->in_valid = 1;
         dut->a_in = 5;
         dut->b_in = 3;
         dut->op_in = Valu___024unit::operation_t::sub;
         break;

     case 22:
        if (dut->out != 2)
            std::cout << "Subtraction failed @ " << sim_time << std::endl;
            break;

(8)in_valid信号随机生成函数

通过随机函数生成:set_rnd_out_valid(dut, sim_time);

void set_rnd_out_valid(Valu *dut, vluint64_t &sim_time){ if (sim_time >= VERIF_START_TIME) { dut->in_valid = rand() % 2; }

(9)out_valid信号检查函数

通过函数检查正确性:check_out_valid(dut, sim_time);



void check_out_valid(Valu *dut, vluint64_t &sim_time){
static unsigned char in_valid = 0; //in valid from current cycle
static unsigned char in_valid_d = 0; //delayed in_valid
static unsigned char out_valid_exp = 0; //expected out_valid value
if (sim_time >= VERIF_START_TIME) {
    out_valid_exp = in_valid_d;
    in_valid_d = in_valid;
    in_valid = dut->in_valid;
    if (out_valid_exp != dut->out_valid) {
        std::cout << "ERROR: out_valid mismatch, "
            << "exp: " << (int)(out_valid_exp)
            << " recv: " << (int)(dut->out_valid)
            << " simtime: " << sim_time << std::endl;
    }
}

通过比对理想值和真实值从而检测出正确性

结束循环!!!

结束循环之后,在main函数中:

关闭:m_trace:

m_trace->close();

删除: dut : delete dut;

成功退出: exit(EXIT_SUCCESS)

代码源文件:

// Norbertas Kremeris 2021
#include <stdlib.h>
#include <iostream>
#include <cstdlib>
#include <verilated.h>
#include <verilated_vcd_c.h>
#include "Valu.h"
#include "Valu___024unit.h"

#define MAX_SIM_TIME 300
#define VERIF_START_TIME 7
vluint64_t sim_time = 0;
vluint64_t posedge_cnt = 0;

void dut_reset (Valu *dut, vluint64_t &sim_time){
    dut->rst = 0;
    if(sim_time >= 3 && sim_time < 6){
        dut->rst = 1;
        dut->a_in = 0;
        dut->b_in = 0;
        dut->op_in = 0;
    }
}

void check_out_valid(Valu *dut, vluint64_t &sim_time){
    static unsigned char in_valid = 0; //in valid from current cycle
    static unsigned char in_valid_d = 0; //delayed in_valid
    static unsigned char out_valid_exp = 0; //expected out_valid value

    if (sim_time >= VERIF_START_TIME) {
        out_valid_exp = in_valid_d;
        in_valid_d = in_valid;
        in_valid = dut->in_valid;
        if (out_valid_exp != dut->out_valid) {
            std::cout << "ERROR: out_valid mismatch, "
                << "exp: " << (int)(out_valid_exp)
                << " recv: " << (int)(dut->out_valid)
                << " simtime: " << sim_time << std::endl;
        }
    }
}

void set_rnd_out_valid(Valu *dut, vluint64_t &sim_time){
    if (sim_time >= VERIF_START_TIME) {
        dut->in_valid = rand() % 2;
    }
}

int main(int argc, char** argv, char** env) {
    srand (time(NULL));
    Verilated::commandArgs(argc, argv);
    Valu *dut = new Valu;

    Verilated::traceEverOn(true);
    VerilatedVcdC *m_trace = new VerilatedVcdC;
    dut->trace(m_trace, 5);
    m_trace->open("waveform.vcd");
    
    while (sim_time < MAX_SIM_TIME) {
        dut_reset(dut, sim_time);

        dut->clk ^= 1;
        dut->eval();

        if (dut->clk == 1){
            dut->in_valid = 0;
            posedge_cnt++;
            switch (posedge_cnt){
                case 10:
                        dut->in_valid = 1;
                        dut->a_in = 5;
                        dut->b_in = 3;
                        dut->op_in = Valu___024unit::operation_t::add;
                        break;
                case 20:
                         dut->in_valid = 1;
                         dut->a_in = 5;
                         dut->b_in = 3;
                         dut->op_in = Valu___024unit::operation_t::sub;
                         break;
            }
            check_out_valid(dut, sim_time);
       }
       m_trace->dump(sim_time);
       sim_time++;
    }
    m_trace->close();
    delete dut;
    exit(EXIT_SUCCESS);
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
testbench(测试台框架)是用于验证设计功能的一种方式,在FPGA或ASIC设计中非常常见。testbench文件的编写方法如下: 1. 定义module:首先,在testbench文件中定义一个module,该module将作为顶层实例来实例化要测试的设计模块。 2. 为输入信号添加时钟:为设计模块的输入信号添加时钟信号。这个时钟信号可以是固定的时钟频率,也可以是根据需要来控制的时钟。 3. 为输入信号添加数据:为设计模块的输入信号添加数据,以便测试设计的各种情况。通常需要为输入信号定义一组数据,以覆盖不同的测试用例。 4. 实例化设计模块:在module定义中实例化设计模块,并将输入信号连接到testbench模块的输出信号。 5. 配置仿真环境:设置仿真环境的一些参数,如仿真时间,仿真精度等。 6. 模拟输入:使用initial块或always块在仿真过程中为输入信号提供数据。可以使用任务或函数来生成数据。 7. 模拟输出:使用initial块或always块来检查设计模块的输出信号。可以使用assert语句来验证输出是否符合预期。 8. 运行仿真:在仿真环境中运行仿真,检查设计模块的输出是否与预期一致。 9. 分析仿真结果:根据仿真结果来评估设计的功能和性能。 10. 优化设计:根据仿真结果,进行必要的调整和改进,以优化设计的性能和功能。 以上是testbench仿真文件编写的一般方法。根据具体的设计需求和测试要求,可以进行相应的调整和改进。编写良好的testbench可以确保设计的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevin_wuminghao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值