首页 > 其他分享 >数字asic流程实验(EX)VCS+Verdi前仿真&后仿真

数字asic流程实验(EX)VCS+Verdi前仿真&后仿真

时间:2023-05-02 17:44:05浏览次数:39  
标签:仿真 cic .. asic VCS vcs Verdi

数字asic流程实验(EX)VCS+Verdi前仿真&后仿真

1. 前言

写数字asic流程实验系列博客已经过去一年多了,现在也算结束了纯小白的状态,稍微有了一些数字前端开发经验。在老的系列教程里面用的前仿后仿工具还是modelsim,实际上业界主流工具还是功能更强大的VCS和Verdi。两个也都是synopsys家的工具,VCS是编译器,Verdi是波形查看工具。为什么主流会是这两个工具我就不去复读了,网上有很多解释,而且确实功能强大,谁用过谁知道。我自己切换到VCS+Verdi上做完两次数字设计了,这里share一下一些开发经验。

2. 前仿真

还是使用cic_filter的那个case。先来一个小插曲,那份代码最后梳状器的部分的逻辑有点问题,存在竞争冒险,后仿真出来的波形有毛刺就是因为这个原因。如果直接用原来的代码的话虽然modelsim里面能把波形仿出来,VCS里面却是不行的,所以我插了一级寄存器来处理,修改后的代码为:

module cic_filter(
    input clk,
    input rst_n,
    input in,
    output [18:0] out
);
    reg [18:0]out_reg;
    wire clk_div;
    reg [18:0]sum1,sum2,sum3;
    wire [18:0]sum1_nxt,sum2_nxt,sum3_nxt;

    assign sum1_nxt = sum1 + in;
    assign sum2_nxt = sum2 + sum1;
    assign sum3_nxt = sum3 + sum2;

    always @(posedge clk or negedge rst_n) begin
        if (rst_n == 0) begin
            sum1 <= 19'b0;
            sum2 <= 19'b0;
            sum3 <= 19'b0;
        end
        else begin
            sum1 <= sum1_nxt;
            sum2 <= sum2_nxt;
            sum3 <= sum3_nxt;
        end
    end

    divider div(
        .clk(clk),
        .rst_n(rst_n),
        .clk_div(clk_div)
    );

    reg [18:0]sub1,sub2,sub3;
    reg [18:0]sub1_nxt,sub2_nxt,sub3_nxt;

     always @(posedge clk_div or negedge rst_n) begin
        if (rst_n == 0) begin
            sub1_nxt <= 19'b0;
            sub2_nxt <= 19'b0;
            sub3_nxt <= 19'b0;
        end
        else begin
            sub1_nxt <= sum3_nxt - sub1;
            sub2_nxt <= sub1_nxt - sub2;
            sub3_nxt <= sub2_nxt - sub3;
        end
    end

    always @(posedge clk_div or negedge rst_n) begin
        if (rst_n == 0) begin
            sub1 <= 19'b0;
            sub2 <= 19'b0;
            sub3 <= 19'b0;
        end
        else begin
            sub1 <= sum3_nxt;
            sub2 <= sub1_nxt;
            sub3 <= sub2_nxt;
        end
    end

    always @(posedge clk_div or negedge rst_n) begin
        if (rst_n == 0) begin
            out_reg <= 0;
        end
        else begin
            out_reg <= sub3_nxt;
        end
    end

    assign out = out_reg;

endmodule

VCS分成编译(compile)和仿真(simulation)两步,编译步骤会把verilog代码编译到可执行文件,仿真步骤会执行编译步骤输出的可执行文件。由于VCS的调用命令相对复杂,这里写了一个makefile的脚本:

.PHONY:vcs_com vcs_sim verdi

OUTPUT = cic_filter
TIMESCALE = 1ns/1ns

#start vcs compile
vcs_com:
	cd ../vcs && vcs -full64 +v2k -debug_pp -timescale=${TIMESCALE} -cpp g++ -cc gcc -LDFLAGS -no-pie -LDFLAGS -Wl,--no-as-needed -CFLAGS -fPIE -fsdb -f file_list.f -o ${OUTPUT} -l compile.log

#start vcs sim
vcs_sim:
	cd ../vcs && ./${OUTPUT} -l sim.log

#start verdi
verdi:
	cd ../verdi && verdi -f ../vcs/file_list.f -ssf ../vcs/tb_${OUTPUT}.fsdb

脚本里OUTPUT和TIMESCALE两个变量可以根据自己的情况来修改。为了简化输入,这里读取文件使用了file_list.f这个文件来标记所有设计文件的路径:

//Macro define
+define+FSDB

// Source
../src/cic_filter.v
../src/divider64.v

// Netlist
//../icc/outputs/cic_filter_post_layout.v

// Library
//../lib/verilog/smic18.v

// Testbench
../tb/tb_cic_filter.v

在前仿真时保留Source和Testbench下的内容即可,Netlist和Library下的内容无关,直接注释掉。

testbench也针对VCS和Verdi的工具需求做了一下修改,主要是Verdi要吃fsdb文件(记录了信号波形),所以要用Dump命令把信号抽取出来。最后还有一段吃sdf文件来跑后仿真的代码,在前仿真时可以把post_sim的宏定义给注释掉,另外因为VCS仿真的结束需要在testbench里面控制,在initial块中记得加入$finish命令,否则到了vcs_sim那一步会一直卡住:

`define period 78.125

module testbench;
    // input
    reg clk,rst_n,in;
    // output
    wire [18:0]out;

    // 设置时钟周期为156.25ns
    always #`period clk <= ~clk;

    // 初始化
    initial begin
        rst_n <= 1'b0;
        clk <= 1'b0;
        #500;
        rst_n <= 1'b1;
        #(10*12800*`period);
        $finish;
    end

    integer i;
    
    // 定义存储器mem
    reg mem[0:3000000];
    
    // 将1k1000mv.txt文件读入mem
    initial $readmemb("../src/1k1000mv.txt",mem);

    // 将mem中数据次序输出到in
    always @(posedge clk or negedge rst_n) begin
        if(rst_n == 0) begin
            i = 0;
            in <= 0;
        end
        else begin
            in <= mem[i];
            i = i + 1;
        end
    end

    // 调用cic滤波器
    cic_filter cic(
        .clk(clk),
        .rst_n(rst_n),
        .in(in),
        .out(out)
    );

    `ifdef FSDB
    initial begin
    	$fsdbDumpfile("tb_cic_filter.fsdb");
    	$fsdbDumpvars;
        $fsdbDumpMDA();
    end
    `endif

    //`define post_sim

    `ifdef post_sim
    // sdf
    initial begin
        $sdf_annotate("../icc/outputs/cic_filter_post_layout.sdf", cic);
    end
    `endif
endmodule

我的路径处理上,将makefile放到了新创建的和src以及tb(testbench专门摆到这个里面来)平级的prj目录里,再平级创建一个vcs文件夹和一个verdi文件夹分别作为vcs和verdi的执行目录。运行整个脚本需要到达prj目录下,执行三步shell命令

make vcs_com
make vcs_sim
make verdi

执行每步命令后都可以看一下工具的输出,如果有报错就处理一下然后再重复步骤即可。Verdi内部可以读取代码,并直接选中要观察的变量,右键Add to waveform加到波形监视窗口。也可以在Instance中选中要观察的Instance,右键Add to waveform将其所有端口信号加到波形监视窗口。

至此前仿真结束。

3. 后仿真

后仿真的步骤很简单,首先修改一下file_list.f,改成吃网表和单元库:

//Macro define
+define+FSDB

// Source
//../src/cic_filter.v
//../src/divider64.v

// Netlist
../icc/outputs/cic_filter_post_layout.v

// Library
../lib/verilog/smic18.v

// Testbench
../tb/tb_cic_filter.v

其次取消testbench中对post_sim宏定义的注释,使得仿真时能够吃到sdf文件来反标延时信息。然后还是那三步shell命令即可:

`define period 78.125

module testbench;
    // input
    reg clk,rst_n,in;
    // output
    wire [18:0]out;

    // 设置时钟周期为156.25ns
    always #`period clk <= ~clk;

    // 初始化
    initial begin
        rst_n <= 1'b0;
        clk <= 1'b0;
        #500;
        rst_n <= 1'b1;
        #(10*12800*`period);
        $finish;
    end

    integer i;
    
    // 定义存储器mem
    reg mem[0:3000000];
    
    // 将1k1000mv.txt文件读入mem
    initial $readmemb("../src/1k1000mv.txt",mem);

    // 将mem中数据次序输出到in
    always @(posedge clk or negedge rst_n) begin
        if(rst_n == 0) begin
            i = 0;
            in <= 0;
        end
        else begin
            in <= mem[i];
            i = i + 1;
        end
    end

    // 调用cic滤波器
    cic_filter cic(
        .clk(clk),
        .rst_n(rst_n),
        .in(in),
        .out(out)
    );

    `ifdef FSDB
    initial begin
    	$fsdbDumpfile("tb_cic_filter.fsdb");
    	$fsdbDumpvars;
        $fsdbDumpMDA();
    end
    `endif

    `define post_sim

    `ifdef post_sim
    // sdf
    initial begin
        $sdf_annotate("../icc/outputs/cic_filter_post_layout.sdf", cic);
    end
    `endif
endmodule

实验文件我就不再打包上传了,所需的代码/脚本上面都已经有了。

标签:仿真,cic,..,asic,VCS,vcs,Verdi
From: https://www.cnblogs.com/sasasatori/p/17367983.html

相关文章

  • OFDM图像传输系统matlab仿真,以图片作为数据源进行发送,接收端还原图片,对比MPSK,MQAM
    1.算法仿真效果matlab2022a仿真结果如下:        2.算法涉及理论知识概要        移动视频图像传输,广泛用于公安指挥车、交通事故勘探车、消防武警现场指挥车和海关、油田、矿山、水利、电力、金融、海事,以及其它的紧急、应急指挥系统,主要作用是将......
  • m基于matlab的AODV,leach自组网网络平台仿真,对比吞吐量,端到端时延,丢包率,剩余节点
    1.算法仿真效果matlab2022a仿真结果如下:     2.算法涉及理论知识概要       AODV是一种应用于无线网状网络的路由协议。它源节点需要发送数据时才进行路由发现。当没有数据发送请求时并不执行。在路由发现过程中首先检查路由表中是否存在从源节点到目的......
  • 电动机的简单仿真
    Multisim做电子电路仿真,是很不错的.其实,在电气设计方面,也很顺手的.电气设计中,少不了对电动机的驱动,而最常用的便是异步鼠笼式式电动机.虽然可以使用相量法计算,但委实繁琐,而直接进行仿真,则可以减少不少麻烦,并降低出错的概率.所以,在Multisim中画出电动机的等效电路,就可......
  • comsol电磁仿真入门
    引子:    一、Maxwell方程 高斯定律(磁)运用于单纯磁场。高斯定律(电)运用于单纯电场。安培定律与法拉第定律描述电磁感应的,安培定律是电生磁,法拉第定律是磁生电。 二、电磁理论中的势 其中,B:磁通量;E:电场;H:磁场。......
  • 基于MSER的车牌提取和字符分割仿真
    1.算法仿真效果matlab2022a仿真结果如下:      2.算法涉及理论知识概要     自然场景下的文本检测是自然场景图像信息提取的基础,在车牌识别、实时翻译、图像检索等领域具有广泛的应用价值及研究意义。基于连通区域的方法是自然场景文本检测中最为常见的......
  • m分别使用meanshift和camshift两种算法实现人员跟踪并输出人员移动曲线matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要       meanshift算法其实通过名字就可以看到该算法的核心,mean(均值),shift(偏移),简单的说,也就是有一个点,它的周围有很多个点 我们计算点 移动到每个点 所需要的偏移量之和,求平均,就得到......
  • 【通信仿真】基于matlab模拟自相干算法仿真
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • AXI_LITE仿真调试
    在SDK中使用xil_DCacheDisable(); 导出内存中的数据   所得的BIN文件可以用WINHEX打开 matlab代码 bin2bmpclear;clc;close;p_fid=fopen('../data/out.bin','r');a=fread(p_fid);col=1280;row=1024;IM=reshape(a,col,row);b=uint8(IM)';......
  • 【密码】量子密钥分发密钥率仿真附MATLAB代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 【机械仿真】基于matlab模拟自动摆钟
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......