VCS 视频教程 笔记 第四课

第四课

Debugging simulation mismatches

if (data == 3)是判断语句,而误写成 if(data = 3)就会先把值赋给data,再判断data是否为3,因此判断语句永远为真。

用(3 == data)可以避免误操作,只要少一个等号就会报错。

  • 本章学习内容
  1. 使用+race选项对竞争冒险现象生成报告 e.g.对一个数据同时进行读和写
  2. 使用$vcdplusdeltacycleon(并不是特别常用)定位产生竞争冒险的代码
  3. 使用vcddiff和vcat对vpd文件进行比较(其实生成的文件并不方便查看,更多的是直接用两个波形文件进行对比)

 

  • Causes of simulation mismatches
  1. 不同的仿真工具仿出来的结果不一样
  2. 不同版本的仿真器结果不一样
  3. RTL级和门级电路仿真结果不一样——代码不完善或者综合过程中出现了问题

 

  • Races

下面是竞争的一个例子:

module race;
    reg a;
    initial begin
      a = 0; #10 a = 1;
    end

    initial begin
      #10 if(a) $display("May not print"); //读写操作发生了竞争,每个仿真器的结果可能不一样
    end
endmodule

解决方法:1.人为错开读取的时间 2.使用非阻塞语句 

零时刻的竞争

initial begin
    reset = 0;
    clock = 0;
    forever #50 clock = ~clock;
end

always @(negedge reset) begin
    $display ("May or may not display at time zero.");

出现了两个问题:1.零时刻reset从不定态变化到0,是否算下降沿?2.如果算下降沿,那么零时刻的下降沿是否在always语句的判断范围之内?

解决方法:1.将下降沿的时间错开 2.初始值赋为1,则零时刻就不会有下降沿

 

  • Coding Rules of Thumb
  1. 同步模块当中只含有非阻塞语句
  2. 组合逻辑电路和初始化语句只含有阻塞语句,用always语句描述组合逻辑语句的时候尽量用always@(*)
  3. 不要有多驱动源,一个变量只在一个always模块里面赋值,或只在一个assign里面赋值;只有在SoC顶层的双向口才会出现多驱动源。

Use vcdiff to show differences in simulation;use vcat to display VCD file values in readable format.

也可以用+race选项显示竞争冒险事件:

vcs -R +race test.v

 

  • 实例

gvim中 :set nu 命令可以显示行号

一共有两种方式实现两级DFF:

//dff_tb.v 两级DFF

`timescale 1ns/1ns

module dff_exp(
    input wire clk_i,
    input wire rst_l_i,
    input wire d,
    output reg q
    );

    reg q1;

    //第一种实现方式  
    `ifdef DFFSTYLE1  
    always @(posedge clk_i, negedge rst_l_i) begin
        if (!rst_l_i)
          q1 <= 1'b0;
        else
          q1 <= d;
    end

    always @(posedge clk_i, negedge rst_l_i) begin
        if(!rst_l_i)
          q <= 1'b0;
        else
          q <= q1;
    end
    `endif

    //第二种实现方式
   `ifdef DFFSTYLE2
    always @(posedge clk_i, negedge rst_l_i) begin
        if (!rst_l_i)
          q1 = 1'b0;
        else
          q1 = d;
    end

    always @(posedge clk_i, negedge rst_l_i) begin
        if(!rst_l_i)
          q = 1'b0;
        else
          q = q1;
    end
    `endif

endmodule

这两种方式仿真的结果是有区别的(第二种会出现错误),但是综合出来的结果是一样的。

接下来进行第三第四种实现方式的仿真:

  //第三种实现方式  
    `ifdef DFFSTYLE3  

    always @(posedge clk_i, negedge rst_l_i) begin
        if (!rst_l_i) begin
          q1 <= 1'b0;
          q <= 1'b0;
        end
        else begin
          q1 <= d;
          q <= q1;
        end
    end

    `endif

    //第四种实现方式
   `ifdef DFFSTYLE4

    always @(posedge clk_i, negedge rst_l_i) begin
        if (!rst_l_i) begin
          q1 = 1'b0;
          q = 1'b0;
        end
        else begin
          q1 = d;
          q = q1;
        end
    end

    `endif

第三个电路的仿真结果是正确的:

VCS 视频教程 笔记 第四课_第1张图片

第四个电路的仿真结果是错误的:

VCS 视频教程 笔记 第四课_第2张图片

第三种写法综合结果是正确的,第四种则出现了错误(只有一个DFF)。

 

第五种第六种分别是在第三种第四种的基础上,对两个赋值的顺序进行调换。例如从q1<=d;q<=q1变成q<=q1;q1

第五种第六种仿真结果都是正确的(虽然第六个使用的是阻塞语句),并且两种综合结果也都是正确的。

 

总结:代码中很小的差别可能会造成仿真和综合极大的不同。

mismatch要注意两点:仿真结果是否不同,综合结果是否不同。

你可能感兴趣的:(VCS)