modelsim仿真不出波形_VCS与Verdi的联合仿真

一、Verdi用途与优势  Verdi主要用于生成fsdb模型,同VCS使用的vcd文件相比,verdi使用的fsdb相当于vcd文件经过霍夫编码压缩之后的精简版,可用于查看fsdb波形并追踪RTL代码。

虽说verdi、modelsim都是用来调试波形, modelsim与verdi相比,最大的缺点是波形不会全dump,wave窗口拉不全的话需要重新跑,而verdi边运行边查看。具体做法是,在使用tcl指令,在运行仿真时,设置仿真时间,每次run完毕之后,在nWave窗口中file——>自动加载(shift+L快捷键),异常方便!

modelsim仿真不出波形_VCS与Verdi的联合仿真_第1张图片

二、FSDB波形 

Verdi只能查看fsdb格式的波形,而VCS可以生成供DVE查看的vpd格式的波形,如果想要输出fsdb格式的波形,需要额外在testbench中添加fsdb指令,或者通过脚本进行设置。FSDB全称为(Fast Signal Data Base):快速信号数据库,fsdb文件是Verdi使用的一种专用数据格式,fsdb通过verilog的PLI接口实现,如:
fsdbDumpfile("f0.fsdb"); //指定生成的fsdb文件的文件名fsdbDumpars(0,top);  //指定dump的变量
三、开发环境与配置 

使用Verdi前需要对开发环境进行配置,使得系统在调用Verdi时找到其路径,在使用verdi时找到其库文件与路径,所以要注意三个变量和三条指令的使用:Verdi_HOME/NOVAS_HOME 仿真器默认,为设置PATH做准备 PATH 让系统能够找到verdi,如果不设置PATH,在调用Veidi时系统无法识别。

LD_LIBRARY_PATH 为了使得Verdi在运行过程中找到需要的库文件,对Library的位置在开发环境中进行配置,可通过: 

echo $LD_LIBRARY_PATH | sed  ‘s/:/\n/g’
进行查看,库文件中包含.so(共享对象文件,shared object),pli.a(静态库)等库文件,还需要*.tab(表格文件)来获取对应信息、索引等。

modelsim仿真不出波形_VCS与Verdi的联合仿真_第2张图片

echo 用于获取环境变量,获取并打印,打印环境变量指令为:
echo $PATH | sed ‘s/\ :/\n/g’

modelsim仿真不出波形_VCS与Verdi的联合仿真_第3张图片

which 查询当前路径是否设置成功,若设置成功会显示一个软件路径,查看verdi路径:which verdi

0b46a714ab914a000cf1672df3fdcee3.png

uname 查询当前系统信息,如硬件平台否为:x86_64

fb783e62e6b8414526a4ed5a005c634d.png

四、VCS+Verdi 如何dump波形

在dump波形时会用到那些命令,解决的是生成fsdb波形的问题,为了生成.fsbd格式的文件,可以使用verilog波形函数,也可以使用ucli/tcl接口: 

(一)使用Verilog系统函数 作为小白,我觉得这种方式很友好,通过Verilog的PLI接口实现,在tb中添加两个函数:
initial begin$fsdbDumfile(“uart.fsdb”);     //指定生成的fsdb文件的文件名$fsdbDumpars(0,uart_byte_tx_tb); //指定dump的层次,0表示存储所有的wave,tb为起始层end 

223e604924b49a3c2cf39717986d6585.png

(二)、使用ucli/tcl接口 

使用ucli/tcl接口时无需在tb中调用与fsdbDumpvars()函数,仅需在脚本中进行设置即可。在运行仿真时,打开ucli接口,通过Tcl脚本对fsdb进行设置,设置fsdb文件的文件名,设置fsdb文件的集成类型和起始文件: 

global env  

# tcl脚本引用环境变量,Makefile中通过export定义  

fsdbDumpfile "$env(demo_name).fsdb"

# 设置波形文件名,受环境变量env(demo_name)控制  

# demo_name在makefile中使用exportdemo_name=demo_fifo 

fsdbDumpvars 0 "tb_top"                

# 设置波形的顶层和层次,表示将tb_top作为顶层,Dump所有层次

run

+fsdb+autoflush 

+fsdb+f+autoflush:用于开启一边仿真以一边Dump波形的功能,在不开启该功能时,运行完仿真之后,未退出命令行,直接在新终端中启动Verdi调用波性文件的话是一个用文件,没有波形,这是因为只有在结束仿真之后,波形才会Dump为静态文件供verdi调用,没有出现波形的原因是此时的.fsdb只是一个空文件,波形还未Dump,如下图所示:

modelsim仿真不出波形_VCS与Verdi的联合仿真_第4张图片

此时可以在仿真的命令行中键入:fsdbDumpflush,启动波形Dump,在另一个终端中启动verdi加载波形,波形正常加载:

modelsim仿真不出波形_VCS与Verdi的联合仿真_第5张图片

verdi优于modelsim也正是因此,通过tcl语言的控制,每次设置run时间,不断的加载仿真波形,十分方便!  VCS编译环节 无论采用调用系统函数还是调用tcl脚本,编译时两种操作相同,都是为了生成一个二进制可执行文件,其重点是VCS与Verdi的库进行连接:
-LDFLAGS#表示下面要加载(load)的标志,将要传递VCS的Linker链接库,与接下来的两条指令配合使用。-rdynamic#加载动态库,提示需要加载动态库,如*库文件名录下的.so文件-P $(Verdi_HOME)/share/PLI/VCS/LINUX64/novas.tab#加载表格文件  $(Verdi_HOME)/share/PLI/VCS/LINUX64/pli.a#加载静态库

五、Makefile脚本设计 

要用到的基本指令为:编译、仿真、verdi加载fsdb波形、清除文件 所以在脚本中设计伪指令:

.PHONY: com sim run_verdi clean

运行编译时会生成一个二进制可执行文件供仿真使用,该文件默认名为:simv,可通过脚本设置:

OUTPUT = uart     #也可以自己设置名字 运行编译,设计编译指令,设置编译开关:

modelsim仿真不出波形_VCS与Verdi的联合仿真_第6张图片

vcs表示运行编译,+v2k表示支持verilog2001标准,-timesacle=1ns/1ns用于设置仿真时间精度,-debug_all用于设置debug开关,-f dile_list.f用于设置编译文件,-o (OUTPUT)用于设置输出二进制可执行文件的文件名,-full64表示VCS为64位版本。

verdi加载fsdb文件显示波形:

d719201c51b45ad95f2d2649cd9fe701.png

-f file_list.f制定要加载的.v文件,-ssf $(OUTPUT).fsdb 表示打开verdi时默认自动加载.fsdb仿真文件,-nologo表示不显示欢迎界面。

六、两种fsdb文件生成方式的比较 基于系统函数

优点:熟悉verilog代码,接受较快

缺点

    1.需要重新编译系统,浪费时间(不使用valuevalueplusargs时);                    2.Verilog是低级语言,对于文本处理比较困难,不支持正则表达式 

基于ucli/tcl接口:

优点:

1.不需要重新编译仿真顶层;

2.使用高级语言接口,容易完成复杂处理,例如传递变量,例如使用正则表达式;

3.交互式接口,控制灵活,仿真过程可修改dump信息,如dumpon/dumpoff 

七、Verdi快捷键

modelsim仿真不出波形_VCS与Verdi的联合仿真_第7张图片

  • save和restore 存储当前查看波形的工程 将当前所有信号存成一个*.rc文件 重新打开波形界面时,restore信号 nwave:file -> Save Signal/Restore Signal
  • 快速熟悉一个设计:通过nTRACE界面查看设计结构:

熟悉设计的IO Driver【D】(Input) 哪些信号驱动了当前信号,可以在nWAVE界面中进行查看。Load【L】 当前信号驱动了哪些信号,可以在nWAVE界面中进行查看。

操作演示 :最后分享一下我所用的工程,是一个UART发送的测试,其工程代码为:
module uart_byte_tx(  Clk,  Rst_n,  data_byte,  send_en,  baud_set,    Rs232_Tx,  Tx_Done,  uart_state);  input Clk;  input Rst_n;  input [7:0]data_byte;  input send_en;  input [2:0]baud_set;    output reg Rs232_Tx;  output reg Tx_Done;  output reg uart_state;    reg bps_clk;  //波特率时钟    reg [15:0]div_cnt;//分频计数器    reg [15:0]bps_DR;//分频计数最大值    reg [3:0]bps_cnt;//波特率时钟计数器    reg [7:0]r_data_byte;    localparam START_BIT = 1'b0;  localparam STOP_BIT = 1'b1;    always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    uart_state <= 1'b0;  else if(send_en)    uart_state <= 1'b1;  else if(bps_cnt == 4'd11)    uart_state <= 1'b0;  else    uart_state <= uart_state;    always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    r_data_byte <= 8'd0;  else if(send_en)    r_data_byte <= data_byte;  else    r_data_byte <= r_data_byte;    always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    bps_DR <= 16'd5207;  else begin    case(baud_set)      0:bps_DR <= 16'd5207;      1:bps_DR <= 16'd2603;      2:bps_DR <= 16'd1301;      3:bps_DR <= 16'd867;      4:bps_DR <= 16'd433;      default:bps_DR <= 16'd5207;          endcase  end      //counter  always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    div_cnt <= 16'd0;  else if(uart_state)begin    if(div_cnt == bps_DR)      div_cnt <= 16'd0;    else      div_cnt <= div_cnt + 1'b1;  end  else    div_cnt <= 16'd0;    // bps_clk gen  always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    bps_clk <= 1'b0;  else if(div_cnt == 16'd1)    bps_clk <= 1'b1;  else    bps_clk <= 1'b0;    //bps counter  always@(posedge Clk or negedge Rst_n)  if(!Rst_n)      bps_cnt <= 4'd0;  else if(bps_cnt == 4'd11)    bps_cnt <= 4'd0;  else if(bps_clk)    bps_cnt <= bps_cnt + 1'b1;  else    bps_cnt <= bps_cnt;      always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    Tx_Done <= 1'b0;  else if(bps_cnt == 4'd11)    Tx_Done <= 1'b1;  else    Tx_Done <= 1'b0;      always@(posedge Clk or negedge Rst_n)  if(!Rst_n)    Rs232_Tx <= 1'b1;  else begin    case(bps_cnt)      0:Rs232_Tx <= 1'b1;      1:Rs232_Tx <= START_BIT;      2:Rs232_Tx <= r_data_byte[0];      3:Rs232_Tx <= r_data_byte[1];      4:Rs232_Tx <= r_data_byte[2];      5:Rs232_Tx <= r_data_byte[3];      6:Rs232_Tx <= r_data_byte[4];      7:Rs232_Tx <= r_data_byte[5];      8:Rs232_Tx <= r_data_byte[6];      9:Rs232_Tx <= r_data_byte[7];      10:Rs232_Tx <= STOP_BIT;      default:Rs232_Tx <= 1'b1;    endcase  end  endmodule
testbench为:
`define clk_period 20module uart_byte_tx_tb;  reg Clk;  reg Rst_n;  reg [7:0]data_byte;  reg send_en;  reg [2:0]baud_set;    wire Rs232_Tx;  wire Tx_Done;  wire uart_state;    uart_byte_tx uart_byte_tx(    .Clk(Clk),    .Rst_n(Rst_n),    .data_byte(data_byte),    .send_en(send_en),    .baud_set(baud_set),        .Rs232_Tx(Rs232_Tx),    .Tx_Done(Tx_Done),    .uart_state(uart_state)  );    initial Clk = 1;  always#(`clk_period/2)Clk = ~Clk;    initial begin    Rst_n = 1'b0;    data_byte = 8'd0;    send_en = 1'd0;    baud_set = 3'd4;    #(`clk_period*20 + 1 )    Rst_n = 1'b1;    #(`clk_period*50);    data_byte = 8'haa;    send_en = 1'd1;    #`clk_period;    send_en = 1'd0;        @(posedge Tx_Done)        #(`clk_period*5000);    data_byte = 8'h55;    send_en = 1'd1;    #`clk_period;    send_en = 1'd0;    @(posedge Tx_Done)    #(`clk_period*5000);    $finish;    end // initial begin: fsdb_generate // $fsdbDumpfile("uart.fsdb"); // $fsdbDumpvars(0,uart_byte_tx_tb); // end endmodule
Makefile脚本为:
.PHONY: com sim run_verdi cleanOUTPUT =uartexport demo_name=$(OUTPUT)#ALL_DEFINE = + define + BAUD_9600#compile command VCS =vcs     +v2k  -timescale=1ns/1ns                    \     -debug_all                                          \     -LDFLAGS                                            \     -rdynamic                                          \     -P $(Verdi_HOME)/share/PLI/VCS/LINUX64/novas.tab    \      $(Verdi_HOME)/share/PLI/VCS/LINUX64/pli.a          \      -full64                                            \      +vcs_lic+wait                                      \      -f file_list.f                                    \      -o ${OUTPUT}                                      \      -l compile.log          VERDI=verdi -f file_list.f   \      -ssf $(OUTPUT).fsdb    \      -nologo                \      -l v.log             #sim commandSIM = ./$(OUTPUT)                              \      -ucli -i ../scripts/dump_fsdb_vcs.tcl    \      +fsdb+autoflush                          \      -l sim.log    #start compilecom:  $(VCS)#start simulationsim:  $(SIM)#run verdirun_verdi:  $(VERDI) &#cleanclean:  rm -rf  ./verdiLog  ./dff ./csrc *.daidir *log *.vpd *.vdb simv* *.key *race.out* *.rc *.fsdb *.vpd *.log *.conf *.dat *.conf uart
tcl 指令为:
global envfsdbDumpfile "$env(demo_name).fsdb"fsdbDumpvars 0 "uart_byte_tx_tb"run 10000ns

好啦,本次更新到此结束,最后衷心的感谢相量子大哥公众号数字ICer的大哥,一位大哥提供了装好了虚拟机,另一位大哥在使用过程中提供了诸多使用技巧,感谢大家的关注,我可能要停更一段时间了,如果有什么问题,欢迎后台交流,共同学习进步!

加油!

你可能感兴趣的:(modelsim仿真不出波形,verdi显示状态机名字)