create_generated_clock invert preinvert shift_edge是否符合设计真实状态很重要【示例1】

10 篇文章 0 订阅

时钟定义反映设计意图还是设计状态

设计意图应该与设计状态一致,但在实现的RTL代码中,二者却不一定一致。时钟约束的描述这时应该反映设计状态,而不是文档中设计意图,这样,时序检查才有机会发现问题,然后反馈给设计人员。要做到这一点,需要对时钟生成的RTL进行分析,真实地描述出来。这就是本文的出发点。

RTL代码

module div(
    clk, rstn, clkout,
    cnter,din, dout
);
    input clk, rstn, din;
    input [2:0] cnter;
    output reg clkout;
    output reg dout;

    reg normal_div2, normal_div4, normal_div8;
    reg cnt_div, upcnt_div;
    reg up_cnt_div;
    reg inverted_div2, inverted_div4, inverted_div8;
    reg [8:0] dnom_tmp;      //use normal_divx as clock 
    reg [8:0] dinv_tmp;      //use normal_divx as clock 
    reg [8:0] dcnt_tmp;      //use clk_cnt as clock
    reg [8:0] dup_tmp;       //use clk_cnt as clock
    reg [2:0] counter, upcounter;

//normal div 
    always @(posedge clk or negedge rstn)
    if(!rstn)
        normal_div2 <= 1'b0; 
    else
        normal_div2 <= ~normal_div2; 

    always @(posedge normal_div2 or negedge rstn)
    if(!rstn)
        normal_div4 <= 1'b0; 
    else
        normal_div4 <= ~normal_div4; 

    always @(posedge normal_div4 or negedge rstn)
    if(!rstn)
        normal_div8 <= 1'b0; 
    else
        normal_div8 <= ~normal_div8; 

// inverted  div
    always @(posedge clk or negedge rstn)
    if(!rstn)
        inverted_div2 <= 1'b1; 
    else
        inverted_div2 <= ~inverted_div2; 

    always @(posedge inverted_div2 or negedge rstn)
    if(!rstn)
        inverted_div4 <= 1'b1; 
    else
        inverted_div4 <= ~inverted_div4; 

    always @(posedge inverted_div4 or negedge rstn)
    if(!rstn)
        inverted_div8 <= 1'b1; 
    else
        inverted_div8 <= ~inverted_div8; 

//counter div
    always @(posedge clk or negedge rstn)
    if(!rstn)
        cnt_div <= 1'b0;
    else if (counter== 0)
        cnt_div <= ~cnt_div ;  // cnter = 1,3,7

    always @(posedge clk or negedge rstn)
    if(!rstn)
        counter <= 3'h7;
    else if(counter==0)
        counter <= cnter;
    else
        counter <= counter - 1;
//up counter div
    always @(posedge clk or negedge rstn)
    if(!rstn)
        upcounter <= 3'h0;
    else if(upcounter==cnter)
        upcounter <= 3'h0;
    else
        upcounter <= upcounter + 1;

    always @(posedge clk or negedge rstn)
    if(!rstn)
        upcnt_div <= 1'b0;
    else if (upcounter== cnter)
        upcnt_div <= ~upcnt_div ;  // cnter = 1,3,7


// use clock here
    always@(posedge clk or negedge rstn)
    if(!rstn)
        dnom_tmp[0] <= 1'b0;
    else
        dnom_tmp[0] <= din;

    always@(posedge normal_div2 or negedge rstn)
    if(!rstn)
        dnom_tmp[2] <= 1'b0;
    else
        dnom_tmp[2] <= din;

    always@(posedge normal_div4 or negedge rstn)
    if(!rstn)
        dnom_tmp[4] <= 1'b0;
    else
        dnom_tmp[4] <= din;

    always@(posedge normal_div8 or negedge rstn)
    if(!rstn)
        dnom_tmp[8] <= 1'b0;
    else
        dnom_tmp[8] <= din;

//inverted clock
    always@(posedge inverted_div2 or negedge rstn)
    if(!rstn)
        dinv_tmp[2] <= 1'b0;
    else
        dinv_tmp[2] <= din;

    always@(posedge inverted_div4 or negedge rstn)
    if(!rstn)
        dinv_tmp[4] <= 1'b0;
    else
        dinv_tmp[4] <= din;

    always@(posedge inverted_div8 or negedge rstn)
    if(!rstn)
        dinv_tmp[8] <= 1'b0;
    else
        dinv_tmp[8] <= din;

// counter
    always@(posedge cnt_div or negedge rstn)
    if(!rstn)
        dcnt_tmp[1] <= 1'b0;
    else
        dcnt_tmp[1] <= din;

    wire dout_tmp;
    assign dout_tmp = ^{dnom_tmp[2],dnom_tmp[4],dnom_tmp[8]} | ^{dinv_tmp[2],dinv_tmp[4],dinv_tmp[8]} | dcnt_tmp[1] | dup_tmp[1] ;

// upcounter
    always@(posedge upcnt_div or negedge rstn)
    if(!rstn)
        dup_tmp[1] <= 1'b0;
    else
        dup_tmp[1] <= din;

//phase shifted 90 degree
    always@(negedge clk or negedge rstn)
    if(!rstn)
        clkout <= 1'b0;
    else 
        clkout <= ~clkout;

    always@(edge clkout or negedge rstn)
    if(!rstn)
        dout <= 1'b0;
    else
        dout <= dout_tmp;

endmodule

二分频的约束分析

代码中的时钟比较多,但我们一段一段地分析。先看3个二分频。
仿真可以直观看出,

在这里插入图片描述normal_div2是普通二分频
inverted_div2是 二分频的反相
clkout则是90度相移的二分频

第一轮约束

create_clock -name clk [get_ports clk] -period 20
create_generated_clock -name nom_clk_div2 [get_pins normal_div2_reg/Q] -divide_by 2 -master clk -source [get_ports clk]
create_generated_clock -name inv_clk_div2 [get_pins inverted_div2_reg/Q] -invert -divide_by 2 -master clk -source [get_ports clk]
create_generated_clock -name sht_clk_div2 [get_pins clkout_reg/Q] -divide_by 2 -master clk -source [get_ports clk] -preinvert

第一轮综合

set_app_var search_path "../ref ../ref/db ../rtl ./"

set_app_var target_library "sc_max.db"
set_app_var link_library "* sc_max.db dw_foundation.sldb"

set cache_write dc_sw_cache
set cache_read $cache_write
set alib_library_analysis_path dc_dw_cache
set synthetic_library {dw_foundation.sldb}
define_design_lib DEFAULT -path ./analyzed

set hdlin_enable_rtldrc_info true;
read_verilog ../rtl/div.v
current_design div 
link

source div.sdc

compile

write -format ddc -hierarchy -output results/div.ddc
write -format verilog -hierarchy -output results/div.vg

report_clocks
Clock Period Waveform Attrs Sources
clk 20.00 {0 10} {clk}
inv_clk_div2 40.00 {20 40} G {inverted_div2_reg/Q}
nom_clk_div2 40.00 {0 20} G {normal_div2_reg/Q}
sht_clk_div2 40.00 {0 20} G {clkout_reg/Q}

前三个对,但是sht_clk_div2,那么 -preinvert不起作用吗?根据文档,creates a generated clock based on the inverted clock signal
only when the source clock on the master pin has a non-unate sense, or the generated clock will not be inverted just as this option has not been specified。所以不起作用符合工具说明。

修改约束

create_generated_clock -name sht_clk_div2 [get_pins clkout_reg/Q] -edges {2 4 6} -master clk -source [get_ports clk]

第二轮综合

clk 20.00 {0 10} {clk}
inv_clk_div2 40.00 {20 40} G {inverted_div2_reg/Q}
nom_clk_div2 40.00 {0 20} G {normal_div2_reg/Q}
sht_clk_div2 40.00 {10 30} G {clkout_reg/Q}
与波形一致。

Startpoint: dnom_tmp_reg[2]
(rising edge-triggered flip-flop clocked by nom_clk_div2)
Endpoint: dout_reg (rising edge-triggered flip-flop clocked by sht_clk_div2)
Path Group: sht_clk_div2
Path Type: max

Des/Clust/Port Wire Load Model Library
div 8000 cb13fs120_tsmc_max

Point Incr Path
clock nom_clk_div2 (rise edge) 0.00 0.00
clock network delay (ideal) 0.00 0.00
dnom_tmp_reg[2]/CP (dfcrq1) 0.00 0.00 r
dnom_tmp_reg[2]/Q (dfcrq1) 0.31 0.31 f
U7/Z (xr03d1) 0.32 0.62 f
U6/Z (or04d0) 0.22 0.84 f
dout_reg/D (dfcrq1) 0.00 0.84 f
data arrival time 0.84

clock sht_clk_div2 (rise edge) 10.00 10.00
clock network delay (ideal) 0.00 10.00
dout_reg/CP (dfcrq1) 0.00 10.00 r
library setup time -0.09 9.91
data required time 9.91
data required time 9.91
data arrival time -0.84
slack (MET) 9.06
这样,检查10ns,才能反映RTL的真实情况。
当然,实施了分析RTL来编写SDC,一共提供了三次机会。
(1)通过代码分析,波形比对,可以与设计文档核对,有问题,及时反馈给设计。
(2)通过review,也可以更快地让设计了解到问题点。
(3)最晚地,在STA阶段还有机会发现问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值