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


  • 相关阅读:
    Elixir 简介
    docker 基础
    函数式和面向对象
    react-native 简介及环境
    Ecto 总结
    使用 dep 配置 golang 开发环境
    docker 私有仓库简易搭建
    Elixir 单元测试
    基于资源的权限系统-API设计
    差商代微商的方法求解一阶常微分方程
  • 原文地址:https://www.cnblogs.com/asic/p/2053279.html
Copyright © 2020-2023  润新知