zoukankan      html  css  js  c++  java
  • 如何保证RTL设计与综合后网表的一致性

    http://hi.baidu.com/hieda/blog/item/1754402924bed7f999250afa.html

    文章简介:在超大规模数字集成电路的设计中,我们使用逻辑综合工具来完成从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设计与综合后的网表不一致的问题。
    避免这种问题的方法有二:

    1. 使用数据流的描述方法描述组合逻辑;
    2. 若用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设计与综合后网表的一致,应注意:

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

    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
    作者:王振国
    科广新(北京)信息技术公司


  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/asic/p/2053279.html
Copyright © 2011-2022 走看看