如何保证RTL设计与综合后网表的一致性
2013-04-05
王振国
标签: RTL

文章简介:在超大规模数字集成电路的设计中,我们使用逻辑综合工具来完成从RTL设计到门级网表的转化。我们希望它综合出的门级网表与我们的RTL设计在逻辑和时序上完全一致。但是某些书写风格和设计思路却会造成两者不一致的情况,降低我们的工作效率。本文列举了三种RTL设计与综合后网表不一致的情况,并给出了解决方法.我们以Design Compiler为例,来说明设计RTL时应该注意的问题。在仿真和调试时,我们使用了NC-Verilog和Debussy。

1.不完整的敏感量列表

在下面的例子中,有一个always语句,它描述了一个或门,其中它的敏感量列表包含IN1和IN2。

/////////////////////////////////////////////////////////////////////////////

module OR_GATE_A (OUT_A, IN1, IN2);

output OUT_A;

input IN1, IN2;

reg OUT_A;

always @(IN1 or IN2)

OUT_A = IN1 | IN2;

endmodule

/////////////////////////////////////////////////////////////////////////////

再看下面的例子,敏感量列表只包含IN1。

/////////////////////////////////////////////////////////////////////////////

module OR_GATE_B (OUT_B, IN1, IN2);

output OUT_B;

input IN1, IN2;

reg OUT_B;

always @(IN1)

OUT_B = IN1 | IN2;

endmodule

/////////////////////////////////////////////////////////////////////////////

这两个例子有什么不同呢?我们看下面的波形:

对比两个module的输出,可以看出:它们的输入相同,但是输出在22时刻却不同,这是因为OR_GATE_B的敏感量列表只包含IN1,导致在22时刻虽然IN2发生了变化,却不能触发OUT_B重新求值。

我们看逻辑综合后的情况。

这两个module的逻辑综合的结果完全相同,均包含完整的敏感量列表。因此,对于OR_GATE_B,它会有RTL设计与综合后的网表不一致的问题。

避免这种问题的方法有二:

  • 使用数据流的描述方法描述组合逻辑;
  • 若用always语句描述组合逻辑,必须检查敏感量列表是否完整;

显然,采用第一种方法更简单一些。

2.时序延迟(timing delay)

我们在进行建模时,常常含有时间延迟。而时间延迟是不可综合的对象,因此,如果建模时不注意时间延迟的"必要的准确性",便会造成时序上的不一致,进而造成逻辑结果上的不一致。我们看下面的例子。

例子:一个二级延迟线

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module mis_timing (

A ,

DATA_RDY,

VE_CLK,

VE_RSTJ,

OUT,

OUT_RDY

);

parameter A_WIDTH = 3;

input [A_WIDTH-1:0]A;

input DATA_RDY;

input VE_RSTJ;

input VE_CLK;

output OUT;

output OUT_RDY;

reg OUT_RDY;

reg DATA_RDY_DLY1;

reg DATA_RDY_DLY2;

reg [A_WIDTH-1:0]OUT ;

parameter UDLY = 1;

//---time for one clock cycle

parameter CLOCK_CYCLE=6.5 ;

always@(posedge VE_CLK or negedge VE_RSTJ) //the data addr

if (!VE_RSTJ)

OUT <= #UDLY 'd0 ;

else OUT <= #(UDLY+CLOCK_CYCLE) A;

//---- output ready ------------------

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

OUT_RDY <= #UDLY 'd0 ;

else OUT_RDY <= #(UDLY+CLOCK_CYCLE) DATA_RDY;

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在这个行为级描述中,我们使用了一个超过一个时钟周期的延迟。

我们使用下面的仿真文件进行仿真:

/////////////////////////////////////////////////////////////////////////////////////////////////////

module ts;

parameter A_WIDTH = 3;

reg [A_WIDTH-1:0]A;

reg DATA_RDY;

reg VE_CLK;

reg VE_RSTJ;

mis_timing mis_timing

(.A (A ),

.DATA_RDY(DATA_RDY ),

.VE_CLK (VE_CLK ),

.VE_RSTJ (VE_RSTJ ),

.OUT ( ),

.OUT_RDY ( )

);

//----------- input data----------------------

initial begin

#2 A=0;

#10 A=0; DATA_RDY=0;

#6 A=3'h5; DATA_RDY=1;

#6.5 A=3'h5; DATA_RDY=0;

end

//-------------clock and RST signal -------------

initial begin

#1 VE_CLK=1'b0;

forever #3.2 VE_CLK= ~VE_CLK;

end

initial begin

#1 VE_RSTJ =1'b1;

#10 VE_RSTJ =1'b0;

#7 VE_RSTJ =1'b1;

end

//---------- waveform dump---------------

initial begin

$fsdbDumpfile("delay_line.fsdb");

$fsdbDumpvars(0,ts );

end

//-------------finish-----------------------------

initial begin

#100 $finish;

end

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

我们看它的波形效果:

使用逻辑综合工具后,得到门级网表文件如下:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module mis_timing ( A, DATA_RDY, VE_CLK, VE_RSTJ, OUT, OUT_RDY, TEST_SI, TEST_SO, test_se );

input [2:0] A;

output [2:0] OUT;

input DATA_RDY, VE_CLK, VE_RSTJ, TEST_SI, test_se;

output OUT_RDY, TEST_SO;

wire n7, n8, n9;

BUFX8 I3 ( .A(n7), .Y(OUT[1]) );

BUFX8 I4 ( .A(n8), .Y(OUT[0]) );

BUFX8 I5 ( .A(TEST_SO), .Y(OUT[2]) );

BUFX8 I6 ( .A(n9), .Y(OUT_RDY) );

SDFFRHQX2 OUT_RDY_reg ( .SI(TEST_SI), .SE(test_se), .D(DATA_RDY), .CK(

VE_CLK), .RN(VE_RSTJ), .Q(n9) );

SDFFRHQX2 \OUT_reg[0] ( .SI(n9), .SE(test_se), .D(A[0]), .CK(VE_CLK),

.RN(VE_RSTJ), .Q(n8) );

SDFFRHQX2 \OUT_reg[1] ( .SI(n8), .SE(test_se), .D(A[1]), .CK(VE_CLK),

.RN(VE_RSTJ), .Q(n7) );

SDFFRHQX2 \OUT_reg[2] ( .SI(n7), .SE(test_se), .D(A[2]), .CK(VE_CLK),

.RN(VE_RSTJ), .Q(TEST_SO) );

endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

研究这个网表文件,我们发现从输入到输出只有一级延迟,显然这与RTL设计不符,因此产生了不匹配。

注:我们在逻辑综合时加上了扫描链,所以有TEST_SI, TEST_SO, test_se这三个信号。

我们看综合后的仿真波形:

比较两个波形,可以直观的看出这种不匹配现象。为了避免这种情况的发生,我们必须改正原来的RTL设计。

//改正RTL

//////////////////////////////////////////////////////////////////////////////////////////////////////////

module mis_timing (

A ,

DATA_RDY,

VE_CLK,

VE_RSTJ,

OUT,

OUT_RDY

);

parameter A_WIDTH = 3;

input [A_WIDTH-1:0]A;

input DATA_RDY;

input VE_RSTJ;

input VE_CLK;

output OUT;

output OUT_RDY;

reg OUT_RDY;

reg DATA_RDY_DLY1;

reg [A_WIDTH-1:0]OUT ;

parameter UDLY = 1;

//---time for one clock cycle

parameter CLOCK_CYCLE=6.5 ;

always@(posedge VE_CLK or negedge VE_RSTJ) //the data addr

if (!VE_RSTJ)

OUT <= #UDLY 'd0 ;

else if (DATA_RDY )

OUT <= #(UDLY) A;

//---- output ready ------------------

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

DATA_RDY_DLY1 <= #UDLY 'd0 ;

else DATA_RDY_DLY1 <= #UDLY DATA_RDY;

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

OUT_RDY <= #UDLY 'd0 ;

else OUT_RDY <= #UDLY DATA_RDY_DLY1 ;

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

我们总结避免这种不匹配的方法:

除非一个逻辑运算在一个时钟周期内无法完成(或者你要仿真一条延迟太长的连线),在设计可综合的RTL代码时,一般不要用超过一个周期的时间延迟。

3.多周期路径(multi-cycle path)引起的问题

在含有时钟的电路中,某些较复杂的组合逻辑运算无法在一个周期内完成,而是需要多个周期来完成,我们称这条逻辑路径为多周期路径(Multi-cycle Path)。

我们看下面的例子:

我们来实现一个17/6的无符号整数除法,被除数为A,除数为B;DATA_RDY为一个脉冲信号,当它为高时对应的A,B为有效值。

我们设计RTL code如下:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module multi_cycle (

A ,

B ,

DATA_RDY,

VE_CLK,

VE_RSTJ,

OUT,

OUT_RDY

);

parameter A_WIDTH = 17;

parameter B_WIDTH = 6;

input [A_WIDTH-1:0]A;

input [B_WIDTH-1:0]B;

input DATA_RDY;

input VE_RSTJ;

input VE_CLK;

output OUT;

output OUT_RDY;

reg OUT_RDY;

reg [A_WIDTH-1:0]OUT ;

parameter UDLY = 1;

wire [(A_WIDTH-1):0] DATA_TMP= A / B ;

always@(posedge VE_CLK or negedge VE_RSTJ) if (!VE_RSTJ)

OUT = #UDLY 'd0 ;

else if (DATA_RDY)

OUT = #UDLY DATA_TMP;

//---- output ready ------------------

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

OUT_RDY <= #UDLY 'd0 ;

else OUT_RDY <= #UDLY DATA_RDY ;

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

我们用以下的仿真文件来完成仿真:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module ts;

parameter A_WIDTH = 17;

parameter B_WIDTH = 6;

reg [A_WIDTH-1:0]A;

reg [B_WIDTH-1:0]B;

reg DATA_RDY;

reg RDY_DLY;

reg VE_CLK;

reg VE_RSTJ;

multi_cycle multi_cycle

(

.A (A ),

.B (B ),

.DATA_RDY(DATA_RDY ),

.VE_CLK (VE_CLK ),

.VE_RSTJ (VE_RSTJ ),

.OUT ( ),

.OUT_RDY ( )

);

//----------- input data----------------------

initial

begin

#2 A=0; B=0;

#10 A=0; B=0; DATA_RDY=0;

#6 A=17'h15505; B=7'h55; DATA_RDY=1;

#6.5 A=17'h15505; B=7'h55; DATA_RDY=0;

end

//-------------clock and RST signal -------------

initial begin

#1 VE_CLK=1'b0;

forever #3.2 VE_CLK= ~VE_CLK;

end

initial begin

#1 VE_RSTJ =1'b1;

#10 VE_RSTJ =1'b0;

#7 VE_RSTJ =1'b1;

end

//------- waveform dump: I use debussy as debug tool----

initial begin

$fsdbDumpfile("multi_cycle.fsdb");

$fsdbDumpvars(0,ts );

end

//-------------finish-----------------------------

initial begin

#100 $finish;

end

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

我们看它的波形:

//逻辑综合

我们来完成它的逻辑综合:使用的单元库为UMC的UMC018AG_AASW。

逻辑综合时,我们设定时钟周期为6.5ns;

逻辑综合完成后,得到时序报告文件,下面是它的一部分:

****************************************

Report : timing

-path full

-delay max

-max_paths 3

Design : multi_cycle

Version: 2002.05

Date : Wed Dec 29 16:15:22 2004

****************************************

Operating Conditions: slow Library: UMC018AG_AASW

Wire Load Model Mode: top

Startpoint: B[2] (input port clocked by VE_CLK)

Endpoint: OUT_reg[0] (rising edge-triggered flip-flop clocked by VE_CLK)

Path Group: VE_CLK

Path Type: max

Des/Clust/Port Wire Load Model Library

------------------------------------------------

multi_cycle UMC18_Conservative UMC018AG_AASW

Point Incr Path

--------------------------------------------------------------------------

clock VE_CLK (rise edge) 0.00 0.00

clock network delay (ideal) 0.00 0.00

input external delay 1.00 1.00 r

B[2] (in) 0.05 1.05 r

div_30/b[2] (multi_cycle_DW_div_uns_17_6_1_test_1) 0.00 1.05 r

div_30/U228/Y (BUFX20) 0.17 1.22 r

......

OUT_reg[0]/D (SDFFRXL) 0.00 13.24 f

data arrival time 13.24

clock VE_CLK (rise edge) 7.00 7.00

clock network delay (ideal) 0.00 7.00

clock uncertainty -0.50 6.50

OUT_reg[0]/CK (SDFFRXL) 0.00 6.50 r

library setup time -0.41 6.09

data required time 6.09

--------------------------------------------------------------------------

data required time 6.09

data arrival time -13.24

--------------------------------------------------------------------------

slack (VIOLATED) -7.15

可以看出,这个除法在13ns内才能完成,在这里时钟周期为6.4ns,因此这个除法含有多周期路径。这个路径需要的周期数为3个。

我们来分析这条多周期路径造成的后果:

也就是下属语句:

else if (DATA_RDY)

OUT = #UDLY DATA_TMP;

因为DATA_TMP的计算需要3个时钟周期,所以我们如果在DATA_RDY有效时对DATA_TMP采样,只能得到它的中间值,这自然是一个错误的值。为避免不匹配我们需要延迟两个周期后对DATA_TMP采样。

//改写RTL code

因此我们的文件改写为:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

module multi_cycle (

A ,

B ,

DATA_RDY,

VE_CLK,

VE_RSTJ,

OUT,

OUT_RDY

);

parameter A_WIDTH = 17;

parameter B_WIDTH = 6;

input [A_WIDTH-1:0]A;

input [B_WIDTH-1:0]B;

input DATA_RDY;

input VE_RSTJ;

input VE_CLK;

output OUT;

output OUT_RDY;

reg OUT_RDY;

reg DATA_RDY_DLY1;

reg DATA_RDY_DLY2;

reg [A_WIDTH-1:0]OUT ;

parameter UDLY = 1;

wire [(A_WIDTH-1):0] SUM_TMP= A / B ;

always@(posedge VE_CLK or negedge VE_RSTJ) //the data addr

if (!VE_RSTJ)

OUT <= #UDLY 'd0 ;

else if (DATA_RDY_DLY2)

OUT <= #UDLY SUM_TMP;

//---- output ready ------------------

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

DATA_RDY_DLY1 <= #UDLY 'd0 ;

else DATA_RDY_DLY1 <= #UDLY DATA_RDY;

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

DATA_RDY_DLY2 <= #UDLY 'd0 ;

else DATA_RDY_DLY2 <= #UDLY DATA_RDY_DLY1;

always@(posedge VE_CLK or negedge VE_RSTJ)

if (!VE_RSTJ)

OUT_RDY <= #UDLY 'd0 ;

else OUT_RDY <= #UDLY DATA_RDY_DLY2 ;

endmodule

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//重新综合---

得到逻辑网表文件(.net)和延迟文件(.sdf)

///综合后的仿真波形:

//总结:避免此种不匹配的方法:

当我们的RTL设计中含有运算复杂,延迟较大的路径时,我们应该根据我们的时钟和使用的单元库,评估它会不会是多周期路径。如果是多周期路径,要看看它是否会造成逻辑和时序错误,然后对RTL代码做必要的修改。

4.总结

在进行RTL设计时,为了保证RTL设计与综合后网表的一致,应注意:

  • 结合所选用的逻辑综合工具的特点,使用合适的书写方式;
  • 了解所使用的标准库单元的速度;
  • 明确硬件电路时钟的频率,并估计一些复杂运算在一个周期内能否完成;

5.参考文献

1)Don Mills, Clifford E. Cummings, RTL Coding Styles That Yield Simulation and Synthesis Mismatches,SNUG1999。

2)Samir Palnitkar, VERILOG HDL, A Guide to DIGITAL Design and Synthesis, Sunsoft Press

作者:王振国

科广新(北京)信息技术公司

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号