当前位置: 代码迷 >> 综合 >> VCS 视频教程 笔记 第四课
  详细解决方案

VCS 视频教程 笔记 第四课

热度:67   发布时间:2023-12-18 22:43:31.0

第四课

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 begina = 0; #10 a = 1;endinitial begin#10 if(a) $display("May not print"); //读写操作发生了竞争,每个仿真器的结果可能不一样end
endmodule

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

零时刻的竞争

initial beginreset = 0;clock = 0;forever #50 clock = ~clock;
endalways @(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/1nsmodule 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) beginif (!rst_l_i)q1 <= 1'b0;elseq1 <= d;endalways @(posedge clk_i, negedge rst_l_i) beginif(!rst_l_i)q <= 1'b0;elseq <= q1;end`endif//第二种实现方式`ifdef DFFSTYLE2always @(posedge clk_i, negedge rst_l_i) beginif (!rst_l_i)q1 = 1'b0;elseq1 = d;endalways @(posedge clk_i, negedge rst_l_i) beginif(!rst_l_i)q = 1'b0;elseq = q1;end`endifendmodule

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

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

  //第三种实现方式  `ifdef DFFSTYLE3  always @(posedge clk_i, negedge rst_l_i) beginif (!rst_l_i) beginq1 <= 1'b0;q <= 1'b0;endelse beginq1 <= d;q <= q1;endend`endif//第四种实现方式`ifdef DFFSTYLE4always @(posedge clk_i, negedge rst_l_i) beginif (!rst_l_i) beginq1 = 1'b0;q = 1'b0;endelse beginq1 = d;q = q1;endend`endif

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

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

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

 

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

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

 

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

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

  相关解决方案