vcs中RTL仿真的竞争

本文介绍如何解决vcs中RTL仿真的竞争。

起因

在仿真时,遇到过对一个信号打一拍,输出居然和该信号处在同一拍的奇怪现象。举例说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module test(clk,clr);
input clk;
input clr;
reg[2:0] cnt;
reg d;
reg clk2;
reg q;
always @(posedge clk ,negedge clr) begin
if(!clr)
cnt <= 3'h0;
else if(cnt < 4)
cnt <= cnt+1;
else
cnt <= 0;
end
always @(posedge clk ,negedge clr) begin
if(!clr)
d <= 1'b0;
else if(cnt == 2)
d <= ~d;
end
always @(posedge clk ,negedge clr) begin
if(!clr)
clk2 <= 1'b0;
else
clk2 <= ~clk2;
end
always @(posedge clk2 ,negedge clr) begin
if(!clr)
q <= 1'b0;
else
q <= d;
end
endmodule

关注28到32行,q应该是d的下一拍。然而波形显示并不是。

原因

造成这种现象的原因,基本上都是因为时钟域的问题,可以看到上面例子中,d并不在clk2时钟域,而是在clk时钟域,尽管clk和clk2是同相不同频。

解决办法

第一种解决办法,从源头上解决,把d同步到clk2时钟域,再进行打拍。

第二种解决办法,VCS仿真时,增加-deraceclockdata 选项。增加选项之后仿真波形会变成如下。

第三种解决办法,将clk2产生时,使用= 而不是<=。修改如上例子为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module test(clk,clr);
input clk;
input clr;
reg[2:0] cnt;
reg d;
reg clk2;
reg q;
always @(posedge clk ,negedge clr) begin
if(!clr)
cnt <= 3'h0;
else if(cnt < 4)
cnt <= cnt+1;
else
cnt <= 0;
end
always @(posedge clk ,negedge clr) begin
if(!clr)
d <= 1'b0;
else if(cnt == 2)
d <= ~d;
end
always @(posedge clk ,negedge clr) begin
if(!clr)
clk2 = 1'b0;
else
clk2 = ~clk2;
end
always @(posedge clk2 ,negedge clr) begin
if(!clr)
q <= 1'b0;
else
q <= d;
end
endmodule

仿真波形也会变成如下。

附录

附上VCS的原文

Resolving RTL Simulation Races in Verilog Designs

A race between data and clock signal occurs when both signals change at the same simulation time and both are input to the same sequential element (flip-flop). However, it is expected that the clock arrives before data and samples the previous settled value of data. When clock arrives after or at the same cycle as data, the new value of data is sampled which causes incorrect results.

VCS helps resolve these RTL simulation races in Verilog design. The following section illustrates how to resolve race conditions.

Recommended Approach to Resolve Race Conditions

It is recommended to use the Verilog ‑deraceclockdata option to enable the clock-data resolution for your entire design. For more information, see section “Using Clock-Data Resolution”.

Using Clock-Data Resolution

Using clock-data resolution ensures that the previous value of the data is always sampled.

This significantly improves the verification productivity. There is no simulation mismatch due to races on flops while migrating to a new release or modifying options that are provided to the VCS command line.

Use Model

To enable the clock-data resolution for your entire design, use the Verilog ‑deraceclockdata option.

% vcs ‑deraceclockdata

By default, the -deraceclockdata option samples memory up to 8 MB. You can use the -deraceclockdata=fullmem option to remove the restriction on the memory size.

Example

Consider the following test case:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module dff(q, d, clk, clr);
output q;
input d, clk, clr;
reg q;
 
always @(posedge clk ,negedge clr) begin
if(!clr)
q <= 1'b0;
else
q <= d;
end
endmodule
 
//=====================top module========================
module top(clk, d, clr, out);
input clk, d, clr;
output out;
wire clk2;
wire q1;
 
 
dff div2(clk2, ~clk2, clk, clr);
dff f1(q1, d, clk, clr);
dff f2(out, q1, clk2, clr);
endmodule
 
//=========================testbench======================
module tb;
reg clk;
reg clr;
reg d;

wire dout;
top t1(clk,d,clr,dout);
initial begin
clk = 1'b0;
d = 1'b0;
clr <= 1'b0;
 
fork
forever clk = #5 ~clk;
#25 d = 1'b1;
#45 d = 1'b0;
#9 clr <= 1'b1;
join_none
 
#70 $finish();
end
endmodule

This example has three flops. For f1 flop, the clock and the data changes at the same time in the blocking assignment region. For f2 flop, both clock and data are changing in the NBA region.

Compile and run the test case using the following command line:

% vcs -sverilog -deraceclockdata test.v

% simv

To compile the test case with FSDB dumping enabled, use the following command line:

% vcs -sverilog -deraceclockdata test.v -debug_access

-debug_region=cell+lib +vcs+fsdbon

Note:

You need to set the VERDI_HOME environment variable for FSDB dumping.

Import the design and load the generated FSDB file into the Verdi platform. The following waveform is generated:

As shown in the waveform, it is able to consistently sample the clock first using the -deraceclockdata option. Therefore, it picks up the previous value of the data.

Limitations

The feature has the following limitations:

• The feature is supported for inferred flops in Verilog only.

• Process blocks containing following constructs are ignored:

- Call to impure function

- Containing delays

- Having immediate assertions inside

- Dynamic variables

- System Task Calls other than $display and $monitor

• Flops modeled using both blocking assignment region and non-blocking assignment region (in same process) are not supported.

• UDPs with synchronous control are not supported.

From <https://solvnet.synopsys.com/dow_retrieve/P-2019.09/VCS_MX/vcs_mx_olh/USERGUIDE_HTML/simulate.006.20.htm>

我也尝试了下上述代码例子。得出如下波形。

不加-deraceclockdata选项时

添加-deraceclockdata选项时