Zebu学习笔记(2)- 设计移植

Zebu的设计理念是尽量减轻移植的复杂度,所以整个工程的设计也是和Verification平台一样有相应的testbench链接我们的Design(DUT)和外设(测试环境),如果我们的Verification平台已经有相应的testbench,那么我们可以直接复用这部分代码,否则我们要根据我们的实际需求建立一个Testbench用于描述Design和外设链接关系。

如果我们的DUT和测试环境是紧密耦合的,那么我们需要定义一个新的顶层,然后将Zebu模块和时钟以及Design进行例化和链接,如果DUT和测试环境是分离的,那么我们需要定义一个新的测试环境,新的测试环境中包含必要的Transactor,clock generator和连接关系。我们一般也是采用后面一种方式,这样系统结构较为清晰。

DUT only environment.png

时钟定义

Zebu中的时钟是通过时钟原语进行定义的,这个原语可以在RTL的任何地方例化,一个设计中至少有1个时钟,至多不超过16个时钟,比如我们可以通过如下的方式定义一个时钟:

zceiClockPort ClockPort (.cclock(clk));

其中cclock表示时钟是一个可控时钟,时钟的具体参数可以在designFeatures文件中进行定义。

实际上Zebu还支持通过一些Delay语句直接产生时钟和复位信号,比如:

# 定义支持delay的RTL模块
clock_delay [-module {list_of_rtl_clock_module}]
// create a clock
always #5 clk=~clk;
// genearte reset signal
initial begin 
    resetn = 0; 
    #mydelay; 
    resetn = 1;
end

另外一种时钟产生的方式是通过clockDelayPort原语产生,这种定义方式可以设置时钟的占空比和相位信息以及复位信号的波形。

clockDelayPort ClockPort (.clock(clk), .reset(rstn));

Memory 定义

Zebu通过memory generator生成Design中需要用到的类SRAM memory,这些memory可以用于Design和Testbench,用户可以通过Verilog语句或者tcl脚本生成相应的Memory,Zebu默认会自动根据memory的大小选择不同的Memory实现方式,一般情况下Memory大小的临界值都是用默认值就好。

运行期间读取信号和Force信号

Zebu的一个很大的优势是在运行期间可以获取Design内部的信号,并且支持对内部的信号进行Force操作,只要信号是时序信号(高低电平就没啥Force的必要了)没有被优化,我们就可以通过动态探针对这些信号进行观测,如下的命令可以保证我们感兴趣的模块内部信号在运行期间可以被观测。

probe_signals -type dynamic -rtlname <net_declaration>

通过上述方式制定的信号在编译期间不会被系统优化掉。

在运行期间我们还可以通过如下的方式改变Design内部信号的值

zforce [options]
zinject [options]

zforcezinject也是VCS utf支持的命令,我们可以通过如下的命令获取相应的帮助信息

vcs -help utf+zforce 
vcs -help utf+zinject

对于Verilog task的支持

Verilog task一般用于在仿真过程中产生相应的输入和输出激励,Zebu对这些Task也有局部的支持,用户可以在DUT, ZEMI-3和ZEMI-4 Transactors使用这些Task,具体支持的task列表比较长,这里就不赘述了。

个人认为比较有用的就是Log信息的输出,断言和readmemb, readmemh, memset等操作。

比如我们可以通过如下的语句改变memory的内容或者输出一个错误信息

initial $readmemh("mem1_init_content.txt",top.dut.mem1);
always @(error_detected)
   if(error_detected)
       $display("[ERROR] Error #%0d detected",error_code);

相关文章

发表新评论