STA series --- 7.Configuring the STA SDC(PATR-II)

序:

本篇内容,基于阅读J. Bhasker • Rakesh Chadha著作《Static Timing Analysis for Nanometer Designs》后进行的总结以及自己的观点和感想,如有不正确的地方,还请指点。读者有微电子基础将更好理解内容。(图片内容绝大部分直接引用书中)

关于STA的概念,已经提到过很多次了,STA : Static Timing Analysis。做STA都需要准备哪些东西呢?从Timing Check – Timing signoff env中可以看到需要吃sdc/netlist/spef/lib等等。其中的每一项,都可以作为一个大的专题介绍,所以做STA并不是简简单单的run工具,需要对所有的数据输入键的内容非常了解,才能是STA check更加顺遂。书上本章内容,虽然名字写的STA环境配置,但是主要还是对SDC相关内容进行介绍。这一章节就详细的描述一下sdc相关内容。

2. IO约束

对于blk/sys/top上的port端口,如果对其进行timing check,外部path到这个ports是什么状态?外部path长短?内部需要预留多长的data path去做综合或者timing check?这是IO约束的来源。

2.1 input io 约束
	set Tclk2q 0.9      ; set Tc1 0.6
		Tclk2q表示UFF0 ck到q的cell delay ,Tc1表示data path上的组合逻辑的delay值。
	set_input_delay -clock CLKA -max [expr Tclk2q + Tc1]  [get_ports INP1]
		表示端口INP1关于CLKA的input delay max值为1.5ns,用于setup check
	set_input_delay -clock CLKA -min 1.3  [get_ports INP1]
		表示端口INP1关于CLKA的input delay min值为1.3ns,用于hold check

在这里插入图片描述

2.2 output io 约束
	set Tc2 3.9   ; set Tsetup 1.1
	set_output_delay -clock CLKQ -max [expr Tc2 + Tsetup] [get_ports OUTB]
	set_output_delay -clock CLKQ -min 4.5 [get_ports OUTB]

在这里插入图片描述

2.3 端口处attributes

由于前面章节介绍可以知道,对于一个cell的delay计算,取决于这个cell的input trans和output load,那么对于直连端口处的cell,比如input 端口处的cell,它的input端是个port,那它的input trans如何定义呢?对于output口处的cell,它的load是个port,那这个port的外部负载是多大呢?应该怎么表示呢?这就涉及到本小节内容:

  1. 对于input:
    可以通过set_drive/set_drive_cell/set_input_transition的方式对端口处的input slew进行设置
    ● set_drive : 表示端口处的驱动能力,默认没有设置的时候,认为端口处的驱动能力无限强,slew为0。
    set_drive 1 [all_inputs] 表示所有的输入端口电阻为1,当电阻为0时候表示驱动能力无限强
    ● set_drive_cell : 用具体的cell来代替port口的外部逻辑驱动。具体的驱动能力由该cell的真实的lib值决定。
    set_driving_cell -lib_cell INV3 -library slow [get_ports INPB]
    ● set_input_trans : 直接用trans值来表示驱动能力,在芯片设计中,也常常用这种方法。
    set_input_transition 0.85 [get_ports INPC]

  2. 对于output:
    通过直接对port设置电容负载之来进行属性标识
    set_load 5 [get_ports OUTX]

3. drc constraint

因为cell的delay计算,由transition和capacitance两个值,通过lib中对应的查找表来计算,而当我们trans和cap的值超过了查找表的范围,那么工具会通过外插法的办法去计算delay,我们知道这样的计算必然是不准确的,因此在做STA check时候,会有DRC相关的check ,即设定max_transition和max_capacity来保证我们delay计算的准确定。

set_max_transition 0.6 IOBANK
set_max_capacitance 0.5 [current_design]

一般在lib库里面,每一个cell都会给一个默认的max_trans值,在STA中会以改值为不可容忍值进行check,可能还会在此基础上进行更加严格的check,这个都取决于design的工艺和大小。
除此之外,还会有set_max_fanout 和set_max_area的设定

4. sdc exception

  1. set_case_analysis:
    对cell上的pin设置常数值,从而达到某种check的需求。如下图所示的mux ,当我们的mux的S端口设置为常数值,那么在STA check时候对于设置常数值的那一路arc或者它控制的那一路arc就没有相应的tming pathcheck 了。否则正常情况下,一个mux,如果没有对它的S端设置固定的值,那么它就会对MUX的I0和I1两路都进行sta 分析。这有时候对于我们来说是不必要的,甚至是浪费的。比如在scan mode时候,scan mux控制的func端口我们其实是不需要看的。

在这里插入图片描述

  1. set_disable_timing:
    打断一个cell的timing arc,如下图所示,比如如果存在S端口到Z端口的clock,这种就很有可能导致一个clock loop的存在,那么我们这个时候可以对S到Z进行一个timing arc的打断,这时候就会少很多的分析。经常遇到的还有ISO的EN端到Z的timing arc。在使用该命令时候需要注意,要非常谨慎。因为这个打断了timing arc ,是把经过这个arc所有的path全部打断了,可能有10条path ,都经过这个arc,那么这10条path就全部不会做timing 分析。所以如果你原本的意图只是对不去看某条path的timing,在可行的条件下了,最好设置false path

     set_disable_timing -from S -to Z [get_cells UMUX0]
    

    在这里插入图片描述

  2. set_false_path:
    对存在的timing path/arc设置false path,在做STAcheck时候不去查。真实的timing arc是存在的,且也是进行了时序和noise的update,只是在打报告的时候,把这部分隐藏起来而已,和set_disable_timing有很大区别。

  3. set_multicycle_path:
    常常用于不同时钟周期的同步时钟之间的check,增大setup 的check 裕度。

5. set max delay约束

set_max_delay的约束,可以参考sdc–set_max_delay的注意事项详细分析。

6. path groups

不得不佩服人类的智慧。对于一个庞大的design ,里面拥有着上百万甚至上千万条的path,如果对这些path下约束?如何对这些path就行check。在做STA分析工具的时候,牛人就想到了,无论path有多少,终归逃不过四类:reg2reg reg2out in2reg in2out,在进行约束的时候,每一类的path的约束可以按照类似的方式进行约束。就简单很多了。而在timing check的时候,分类 check也会提高效率。
在这里插入图片描述

7. Path Segmentation

这个其实就是把正常的timing arc打断,然后对path碎片化分析,这种在真实的芯片设计中几乎没有见过,感兴趣可以参考原书。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用USART通信实现STM32与GY-53-L1测距模块进行通信的示例代码: ``` #include "stm32f10x.h" #include <stdio.h> // 定义USART相关的GPIO口 #define USARTx USART1 #define USARTx_CLK RCC_APB2Periph_USART1 #define USARTx_TX_PIN GPIO_Pin_9 #define USARTx_TX_GPIO_PORT GPIOA #define USARTx_TX_GPIO_CLK RCC_APB2Periph_GPIOA #define USARTx_RX_PIN GPIO_Pin_10 #define USARTx_RX_GPIO_PORT GPIOA #define USARTx_RX_GPIO_CLK RCC_APB2Periph_GPIOA // 定义USART接收缓冲区大小 #define USART_RX_BUF_SIZE 100 // 定义发送和接收状态 #define USART_SENDING 0 #define USART_RECEIVING 1 // 定义USART接收缓冲区 uint8_t USART_RX_BUF[USART_RX_BUF_SIZE]; uint16_t USART_RX_STA = 0; uint8_t USART_RX_STATUS = USART_RECEIVING; // USART初始化函数 void USART_Config(void) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(USARTx_CLK | USARTx_TX_GPIO_CLK | USARTx_RX_GPIO_CLK, ENABLE); // 配置USARTx_TX的GPIO口 GPIO_InitStructure.GPIO_Pin = USARTx_TX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStructure); // 配置USARTx_RX的GPIO口 GPIO_InitStructure.GPIO_Pin = USARTx_RX_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USARTx, &USART_InitStructure); USART_Cmd(USARTx, ENABLE); } // USART发送一个字节 void USART_SendByte(USART_TypeDef *USARTx, uint8_t byte) { while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET); USART_SendData(USARTx, byte); } // USART发送字符串 void USART_SendString(USART_TypeDef *USARTx, char *str) { while (*str) { USART_SendByte(USARTx, *str++); } } // USART接收中断处理函数 void USART1_IRQHandler(void) { uint8_t ch; if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { ch = USART_ReceiveData(USART1); // 如果接收到换行符,则示一行数据接收完成 if (ch == '\n' || ch == '\r') { USART_RX_BUF[USART_RX_STA++] = ch; USART_RX_STATUS = USART_SENDING; } else { USART_RX_BUF[USART_RX_STA++] = ch; if (USART_RX_STA >= USART_RX_BUF_SIZE) { USART_RX_STATUS = USART_SENDING; } else { USART_RX_STATUS = USART_RECEIVING; } } } } int main(void) { uint32_t distance; USART_Config(); // 使能接收中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); while (1) { // 发送获取距离命令 USART_SendString(USART1, "AT+DIST?\r\n"); // 等待接收到距离数据 while (USART_RX_STATUS == USART_RECEIVING); // 解析距离数据 sscanf((const char *)USART_RX_BUF, "+DIST:%ldmm", &distance); printf("Distance: %ldmm\r\n", distance); // 清空接收缓冲区和状态 USART_RX_STA = 0; USART_RX_STATUS = USART_RECEIVING; // 延时一段时间 Delay(1000); } } ``` 在上述代码中,使用USART1与GY-53-L1测距模块进行通信,通过发送"AT+DIST?"命令获取距离数据。当接收到一行数据时,会将数据存储到USART_RX_BUF缓冲区中,直到接收到换行符或缓冲区已满。然后从缓冲区中解析出距离数据,并打印到串口终端上。最后清空接收缓冲区和状态,并延时一段时间再次发送命令。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值