ZeBu Transactors

ZeBu Transactors实际是一些协议相关的外围器件的统称,可以方便的在SOC验证环境中调用,它支持一些常见的协议,比如:PCI Express 3.0, AMBA, USB, MIPI CSI-2, MIPI DSI, I2C, I2S, 以太网,视频接口和JTAG.

这些transactors包含可综合总线模型(Synthesizable Bus Functional Models, BFMs),这些模型可以直接下载到FPGA硬件,这样可以得到更高的性能并保证和仿真系统的同步。

Transactors本身包含C/C++的接口,可以快速建立仿真环境,用户也可以自己定制自己的可综合的transator。

ZEMI-3接口

ZEMI-3是一个标准的协同仿真接口,它与SystemVerilog编译的BFM模型可以通信,也就是说可以通过C/C++与System Verilog的testbench交换数据,形式上类似于DPI-C.

ZEMI-3的特点:

  • 根据System Verilog的行为级模型自动产生BFM
  • 自动检测最有效的数据传输方式
  • 代码易于管理
  • 相比于SCE-MI更为有效率

ZEMI-3中硬件与软件的交互是基于DPI机制的,它也是SystemVerilog标准的一部分,transactor的硬件描述通过SystemVerilog行为级模型描述。以下是一个基本的结构框图:

transactor_architecture.PNG

SystemVerilog DPI

通过SystemVerilog DPI我们可以实现通过函数调用进行硬件系统和软件系统的数据交换,这种数据交换是双向的。

Import functions: 这些是C语言中可供SystemVerilog调用的函数,在ZEMI框架里面代表这硬件模块调用软件testbench。

Export Functions: 可供C调用的System Verilog函数,ZEMI框架中代表软件模型调用硬件模型。

Export Tasks: 可供C调用的System Verilog任务。

函数和任务的区别:函数是立即返回的,不会消耗仿真时间,任务是可以消耗仿真时间的。

在ZEMI-3的硬件模型中,我们可以采用行为级代码(可以用非综合代码),这样代码可以简化比如:

  • always块和其它块中可以包含Events
  • Clock, edges和其它一些事件可以混合在一个wait中
  • 信号可以在多个process中写入
  • 允许非绑定循环

ZEMI-4

Native System Verilog Transactor Infrastructure允许你建立一个工业级别的仿真环境。一个仿真环境通常包含BFM, DUT,时钟和复位产生逻辑,这些模块统一封装在仿真的顶层,一般仿真顶层可以分为两个部分:

  • 可综合的部分,一般会有一个自己的顶层,这个顶层直接连接到模拟器
  • 仿真模型,一般是不可综合的Hardware Verification Language(HVL)描述,也有自己的单独顶层,运行于仿真器

testbench_architecture.PNG

Transactor就是位于模拟器(emulator)和仿真器(Simulator)之间的一个部分,可以实现HDL和HVL的双向通信。这部分的实现也有两种不同的形式:

  1. 基于类构造方式实现
  2. 基于uvm_config_db机制实现

类的构造方式实现

transactor中包含硬件的BFM接口和软件的BFM接口两个部分,二者必须保持一致才能有效的工作,具体的实现方式可以通过基于SystemVerilog的参数传递方式进行类的构造实现。

interface Xtgor(input clk, input rst _)

apb_monitor apb_mon_h;

task set_mon_handle (apb_monitor apb_mon_n)
    apb_mon_h = apb_mon_n;
endtask

endinterface
/********************************************/
class apb_monitor;
    virtual Xtor xtor_mh;
    function new(virtual Xtor xtor_n);
        this.xtor_mh = xtor_n;
        xtor_mh.set_mon_handle(this);
    endfunction
endclass
/********************************************/
module HDL_Top;

Xtor xtor_inst(...);

endmodule
/********************************************/
modult TB_Top;

apb_monitor apbm;
apb_driver apbd;

initial begin
    apbm = new(HDL_Top.Xtor);
    apbd = new(HDL_Top.Xtor);
end

endmodule

uvm_config_db机制

interface apb_monitor_bfm(<port_list>);

apb_monitor m_mon;

    function void configure (input apb_monitor hvl_scope);
        m_mon = hvl_scope;
    endfunction
endinterface
/********************************************/
class apb_monitor extends uvm_monitor;
local virtual apb_monitor_bfm m_bfm;

function void connect_phase(uvm_phase phase);
    if (!uvm_config_db#(virtual apb_monitor_bfm)::
        get(this, "", "mon_bfm", m_bfm)) begin
            `uvm_fatal("APB/MSTR/MON", "No ...")
    end
endfunction

task run_phase(uvm_phase phase);
    m_bfm.configure(this);
endtask
endclass: apb_monitor
/********************************************/
module rtl_top;
    ...
    apb_monitor_bfm apb_mon0(<port_list>);
endmodule
/********************************************/
module tb_top;
initial begin
    uvm_config_db#(virtual apb_monitor_bfm)::
        set(null, "uvm_test_top.env.apb0.*",
            "mon_bfm", rtl_top.apb_mon0);
endmodule

C/C++ Co-Simulation

#include <iostream>
#include <unistd.h>
#include <stdexcept>
#include <exception>
#include <libZebu.hh>
#include "counterDriver.hh"
using namespace ZEBU;
using namespace std;
int main (int argc, char *argv[]) {
    Board* board = NULL;
    try {
        // open the ZeBu board
        board = Board::open("../zcui.work/zebu.work");
        // initialize the transactor
        CounterDriver *cnt = new CounterDriver;
        cnt->init (board, "hw_top.counterDriver_0");
        // initialize the ZeBu board
        board->init(NULL);
        // stimulate the design using transactions
        cnt->load(10);
        cnt->run(100);
        cnt->idle(20);
        cnt->run(5);
        printf("Got %d\n", cnt->read() );
    }
    catch(exception &xcep) {
        cerr << "ERROR : " << xcep.what() << endl;
    }
    // close the ZeBu board
    board->close();
    return 0;
}

UART的例子

首先来看看基本的结构:

uart_transactor_architecture.PNG

详细结构

uart_detail.PNG

ZeBu UART transactor包含以下几部分:

  • 应用模式,运行于PC可以实现对DUT UART接口的读写操作
  • 服务器模式,基于TCP socket,支持远程访问
  • 交互式终端接口,直接调用一个xterm终端,可以直接实现UART接口的调用
  • 支持5-8位的数据比特
  • 1-2个停止位
  • 奇偶校验
  • RTS/CTS的流控和全双工模式

可以看出,整个UART和实际的UART基本上没有差异。


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

发表新评论