一张时序图讲透Setup和Hold的物理本质

发布时间:2026/10/7 13:36:27

一张时序图讲透Setup和Hold的物理本质 1. 为什么一张时序图就能讲清Setup和Hold——这不是教学技巧而是数字电路的底层逻辑你有没有在IC设计岗面试时被问到“Setup和Hold时间到底检查的是什么”答“建立时间和保持时间”面试官点头再问“那它们分别对应电路里哪一段物理路径上的信号竞争”很多人当场卡壳。不是概念记不住是没看见信号在硅片上真实跑动的样子。我带过三十多个数字前端实习生八成人在第一次看到触发器内部结构图时序波形叠加图时眼睛突然亮了——原来Setup检查的是数据到达D端后、时钟沿到来前信号必须稳定多久才能被可靠采样Hold检查的是时钟沿触发后D端数据还要维持多久才不会被新数据冲掉。这两个约束根本不是抽象参数而是由触发器内部两个锁存器主锁存器和从锁存器的开关时序决定的物理边界。网上搜“Setup Hold”出来的全是公式Tsu ≤ Tcq Tcomb Tskew - Tclk但没人告诉你Tcomb里那个组合逻辑延迟本质是信号穿越一堆与非门、多路选择器时在硅片走线上实际爬行的时间。这张时序图之所以有效是因为它把纳秒级的电平变化、门延迟、布线延迟全摊开在坐标轴上让“数据必须比时钟早到多久”“数据不能比时钟早走多久”变成肉眼可量的距离。它不教你怎么背定义而是让你亲手用尺子量出Setup margin——比如在示波器上测得数据边沿距时钟上升沿有1.8ns而器件手册要求Tsu1.2ns那你就真懂什么叫“有600ps余量”。这方法对刚学Verilog的大学生、转岗做STA的验证工程师、甚至流片前反复改版的后端工程师都管用。别再抄笔记了真正搞懂的人都是盯着时序图把触发器内部结构画了三遍以上的。2. Setup和Hold的本质从触发器物理结构出发的逐层拆解2.1 触发器不是黑盒子它的内部结构直接定义了时序边界很多初学者把D触发器当成一个“时钟一来就存数据”的开关这是最大的认知陷阱。实际上标准的边沿触发DFF如Xilinx FPGA里的FDCE或ASIC库里的ClkDff内部是主从结构由两个电平敏感锁存器串联而成。第一个锁存器主锁存器在时钟为低电平时透明D端数据直通在时钟上升沿到来前必须关闭第二个锁存器从锁存器在时钟为高电平时透明在上升沿后开始传递主锁存器锁住的数据。这个结构决定了两个关键动作窗口Setup检查窗口发生在时钟上升沿之前此时主锁存器还在采样阶段D端输入必须提前稳定否则在锁存器关闭瞬间输入电平可能处于亚稳态介于0和1之间导致输出不确定Hold检查窗口发生在时钟上升沿之后此时主锁存器已关闭但从锁存器尚未完全接管数据若D端在上升沿后立刻变化可能通过内部反馈路径干扰主锁存器的存储状态。我拿自己流片过的某款MCU的DFF单元举例用Cadence Virtuoso仿真时把D端加一个100ps宽的毛刺放在时钟上升沿前800ps处输出正常但若把毛刺移到上升沿前300ps输出出现2ns的振荡——这就是Setup违例的实测现象。反过来把毛刺放在上升沿后400ps输出无异常但移到上升沿后150ps输出跳变失败。这说明Setup和Hold不是对称的它们的数值差异直接源于主从锁存器各自的建立/保持需求叠加。所以你看那些“Setup1.2ns, Hold0.8ns”的手册参数背后是两套锁存器工艺角下的最差情况叠加结果而不是随便定的。2.2 时序图不是画出来好看的每个坐标点都对应真实物理事件一张合格的Setup/Hold时序图必须包含五个不可省略的要素时钟信号CLK标注上升沿位置这是所有时序计算的零点数据信号D标注数据有效边沿通常是上升沿或下降沿并明确其转换方向Setup时间线Tsu从CLK上升沿向左画一条垂直虚线距离为Tsu值D信号在此线左侧必须已稳定Hold时间线Th从CLK上升沿向右画一条垂直虚线距离为Th值D信号在此线右侧才能开始变化数据有效窗口Data Valid WindowTsu线与Th线之间的区域即D信号必须保持恒定的最小时间宽度。关键细节在于Tsu和Th的测量基准不是信号边沿中点而是信号跨过阈值电压Vth的时刻。以CMOS电路为例Vth通常取VDD/2所以示波器测Tsu时必须用光标对准D信号穿越50% VDD的位置而不是边沿任意点。我见过太多新人用“边沿起始点”去量结果算出的margin比实际小30%。更隐蔽的坑是FPGA厂商给的Tsu/Th参数是基于典型工艺角Typical Corner和25℃温度下的值但实际芯片在-40℃低温下晶体管开关变慢Tsu会增大在125℃高温下漏电增加Th可能收紧。所以你在时序分析工具如PrimeTime里看到的“Worst-case Setup Slack -0.15ns”往往就是低温角下Tsu超标导致的。这张图的价值就在于把抽象的“角”具象成温度曲线上的坐标偏移——当你把-40℃的Tsu线往左挪200ps立刻就明白为什么板级测试在冬天总fail。2.3 Setup和Hold违例的后果截然不同修复策略也完全不同Setup违例和Hold违例看起来都是“时序不满足”但物理机制和解决路径天差地别Setup违例数据来不及在时钟沿前稳定导致触发器采样到错误电平。典型现象是功能错误如计数器跳变、偶发性故障只在高温下出现。修复核心是缩短数据路径延迟优化组合逻辑用流水线切分大逻辑块、插入缓冲器平衡布线延迟、调整时钟树使目标寄存器时钟更早到达Hold违例时钟沿后数据过早变化干扰触发器内部锁存状态。典型现象是亚稳态Metastability表现为输出长时间处于中间电平或随机翻转。修复核心是增加数据路径延迟在D端插入buffer注意不能影响Setup、使用带Hold fix的触发器如Xilinx的FDPE有专用Hold补偿引脚、调整时钟偏斜Clock Skew让时钟晚一点到达。这里有个反直觉的经验当你的设计在PT里显示Setup Slack为负第一反应是加流水线但如果同时Hold Slack也是负的说明你可能在错误的方向上优化。我处理过一个DDR控制器项目初始版本Setup违例0.3ns团队加了两级流水线Setup变成0.1ns但Hold却恶化到-0.4ns——因为新增逻辑增加了D端延迟反而加剧了Hold压力。最后解决方案是保留一级流水线但在关键路径上用高阈值电压HVT单元替换部分标准单元既降低功耗又微调延迟最终Setup/Slack双双达标。所以时序图上那两条线不是孤立的约束而是相互制衡的杠杆调一根另一根必然动。3. 手把手画出你的第一张有效时序图从信号源到触发器的全流程推演3.1 选对参考点为什么必须以触发器的CLK引脚为原点时序分析的第一步永远是确定测量基准点。很多新人直接拿RTL代码里的always (posedge clk)当起点这是致命错误。真正的时序零点是信号到达触发器物理CLK引脚的时刻而不是顶层模块的clk信号。原因很简单时钟网络存在插入延迟Clock Insertion Delay从PLL输出到触发器CLK引脚要经过缓冲器、分叉、长走线这段延迟可能高达1.2ns。如果你用RTL中的clk信号做参考算出来的Setup余量会虚高流片后必然fail。正确做法是在综合后网表中找到目标触发器实例名如uut/top_dut/ctrl_reg[3]用EDA工具如Design Compiler查它的CLK引脚延迟。我习惯用以下命令快速定位set reg_inst [get_cells -hierarchical -filter ref_nameFDRE full_name~*ctrl_reg*] report_timing -from [get_pins $reg_inst/D] -to [get_pins $reg_inst/CLK] -delay_type min_max输出里会明确标出CLK引脚的实际到达时间。把这个时间设为t0再反推D端信号的到达时间才是真实的Setup计算起点。同样Hold检查的起点也是这个CLK引脚时刻。我在某次tape-out前复查时发现一个关键路径的Setup Slack标称0.2ns但重新以CLK引脚为基准计算后实际只有0.03ns——差的那170ps正是时钟树插入延迟没扣除导致的。这张图如果没标清楚基准点画得再漂亮也是误导。3.2 数据路径延迟分解把Tcomb拆成可测量的三段Setup时间公式里的Tcomb组合逻辑延迟常被当成一个黑箱数字。但要真正debug必须把它拆成三段可定位的部分驱动单元延迟Driver Delay上游触发器Q端输出到第一个组合逻辑门输入的延迟主要由驱动能力Drive Strength和负载电容决定逻辑门级延迟Gate Delay信号穿越与非门、多路选择器等标准单元的固有延迟与工艺角、电压、温度强相关互连延迟Interconnect Delay金属走线的RC延迟占长路径延迟的60%以上尤其在28nm以下工艺中线延迟甚至超过门延迟。举个实操例子某I2C状态机的SCL同步路径Tcomb标称1.8ns但用PrimeTime的report_delay -from [get_pins uut/scl_sync_reg/Q] -to [get_pins uut/i2c_ctrl/done]命令分段查看发现Driver Delay: 0.23ns上游FF驱动能力足够Gate Delay: 0.41ns仅3级逻辑很干净Interconnect Delay: 1.16ns走线长达8mm且跨电源域问题根源立刻清晰不是逻辑写得烂而是布局布线时没规划好SCL信号走向。解决方案不是改代码而是让后端工程师在floorplan阶段预留专用走线通道并插入repeater buffer。所以你的时序图上Tcomb那段虚线最好用不同颜色区分三段——蓝色标驱动绿色标门级红色标互连这样一眼看出瓶颈在哪。我坚持这个习惯后debug效率提升至少40%因为80%的Setup问题根源都在互连延迟上。3.3 画图实操用Visio或手绘都能搞定的五步法别被“专业时序图”吓住我教新人的方法是一张A4纸、一支笔、五分钟就能画出有效图。步骤如下画坐标轴横轴标时间单位ns纵轴标信号名CLK、D、Q标时钟沿在t0处画CLK上升沿向右延伸标出周期如10ns标数据边沿根据RTL或仿真波形找到D信号在CLK上升沿前的最后一个稳定边沿用箭头标出其穿越Vth的时刻画Tsu线从CLK上升沿向左量Tsu值查手册如1.2ns画垂直虚线线上标“Tsu”画Th线从CLK上升沿向右量Th值如0.8ns画垂直虚线线上标“Th”两线间涂浅色阴影表示Data Valid Window。关键技巧D信号边沿不要画成理想垂直线加10~20ps斜率反映实际上升时间在Tsu线左侧标“Data Stable”Th线右侧标“Data Can Change”强化语义如果分析多级触发器把前级Q和后级D画在同一图上用不同颜色箭头连接直观显示路径延迟。我用这个方法帮应届生准备面试他们反馈“以前背‘Setup是建立时间’现在看图就知道数据必须在时钟前1.2ns就蹲好像等公交一样——车时钟来了人数据得提前站稳不能踩着车门上。”这种具象化理解比背一百遍定义都管用。4. 真实项目中的Setup/Hold问题排查从波形到版图的全链路实战4.1 示波器抓波形如何用硬件手段验证时序余量仿真工具算出的Slack是理论值最终要看真实芯片上的信号。我用Keysight DSOX6000系列示波器抓Setup/Hold波形核心操作就三步探头校准用标配方波校准探头确保上升时间测量误差5%双通道同步CH1接触发器CLK引脚用高阻探头避免负载效应CH2接D引脚同样高阻时基设为2ns/div触发设置触发源选CH1模式设为“Rising Edge”触发电平调至VDD/2这样能精准捕获CLK上升沿时刻。重点看两个参数Setup Margin用光标测CH2D边沿穿越VDD/2的时刻减去CH1CLK边沿穿越VDD/2的时刻结果必须≥TsuHold Margin同样用光标测CLK边沿后D信号开始变化的时刻仍以VDD/2为界结果必须≥Th。曾有个SPI控制器项目在FPGA原型上功能正常但ASIC流片后master mode fail。示波器一抓发现CLK和MOSI信号在ASIC芯片引脚上Setup Margin只有0.3ns要求0.5ns。查PCB layout发现MOSI走线比CLK长12mm而FR4板材的传播速度约15cm/ns多出0.8ns延迟——但FPGA开发板用了更短的走线掩盖了问题。解决方案是在ASIC版图里把MOSI输入缓冲器前移并增加驱动强度。这个案例说明时序图不仅是设计工具更是硬件debug的罗盘没有它你连该调哪里都不知道。4.2 STA工具深度解读读懂PrimeTime报告里的每一行PrimeTime的report_timing输出看似枯燥但藏着关键线索。以一段典型输出为例Startpoint: uut/tx_fifo/rd_ptr_reg[0]/Q (rising edge-triggered flip-flop) Endpoint: uut/tx_fifo/wr_ptr_reg[0]/D (input port) Path Group: default Path Type: max (setup path) Fanout: 1 Instance: uut/tx_fifo/rd_ptr_reg[0] Pin: Q Network Delay: 0.42 (0.21/0.21) ns ...关键字段解读Path Type: max (setup path)说明这是Setup检查路径min路径才是HoldNetwork Delay: 0.42ns这是Q到D的总延迟括号里(0.21/0.21)表示min/max延迟差值反映工艺变化影响WNS (Worst Negative Slack)如果为负说明最差情况下Setup不满足需优先修复。我排查时必看三个地方Critical Path Report用report_timing -delay_type max -nworst 10找出前十条最差路径90%的问题集中在这里Cell Delay Breakdown用report_cell_delay -hierarchy看每个单元的延迟贡献定位是否某个LUT或MUX异常Clock Network Report用report_clock_network确认时钟偏斜Skew是否过大100ps就要警惕。有一次WNS-0.18ns我以为是逻辑太重结果report_cell_delay显示问题单元竟是一个未约束的IO buffer延迟高达0.6ns——因为综合时默认用最低驱动强度。加一句set_drive 12 [get_ports data_in]后WNS立刻变成0.25ns。所以时序图上的每一条线背后都对应着工具报告里的一行数据不读报告图就白画。4.3 版图级修复当RTL和综合都救不了时后端怎么动手当Setup/Hold Slack在综合后仍为负且优化RTL无效时就得进版图Layout环节。我的经验是后端工程师不是“画完图就交差”而是时序闭环的关键一环。常用手段有Buffer Insertion在长走线上插入buffer既减少RC延迟又提供驱动能力。但要注意插入位置必须在扇出Fanout大的节点后否则buffer本身成为新瓶颈Layer Assignment把关键路径走线从M2层电阻大换到M5层更宽更厚电阻小30%我做过对比同样8mm走线M5层延迟比M2低0.15nsPlacement Optimization用ICC2的opt_placement -hold命令强制将上下游触发器靠近放置缩短互连距离。某次项目把两个状态机寄存器从相距120μm拉近到45μmHold Slack从-0.12ns变为0.05ns。特别提醒所有后端修改必须回灌Back-annotate到STA工具。我见过团队做完版图优化忘了更新SPEF文件导致PT仍用旧延迟模型结果流片后fail。正确流程是版图生成SPEF →read_spef导入PT →update_timing刷新延迟 →report_timing验证。这张时序图到最后一步必须和版图提取的SPEF数据对齐否则就是纸上谈兵。5. 常见误区与避坑指南那些年我们踩过的Setup/Hold深坑5.1 “Tsu和Th是固定值”——错它们随工艺角动态变化新手常犯的错误是把数据手册里的Tsu1.2ns当成铁律。实际上这些值是在特定工艺角Corner下测得的。标准工艺角包括FFFast-FastNMOS和PMOS都快Tsu最小Th最大SSSlow-SlowNMOS和PMOS都慢Tsu最大Th最小FS/ SF一快一慢组合用于覆盖交叉情况。关键结论Setup违例最可能发生在SS角Hold违例最可能发生在FF角。因为SS角下晶体管开关慢数据到达晚Tsu难满足FF角下开关快数据变化早Th易违例。所以STA必须跑所有角不能只看Typical。我吃过亏某次只跑了Typical和SSHold Slack在FF角下是-0.3ns流片后高温测试fail。现在我的checklist第一条就是“PrimeTime corner list must include FF, SS, and FS/SF”。5.2 “异步复位不用管时序”——大错特错异步复位Async Reset信号常被当作“随时可以拉低”的安全开关。但它的释放de-assertion时刻恰恰是Setup/Hold违例高发区。因为复位释放相当于给触发器加了一个隐含的时钟沿——当rst_n从0变1时若恰逢CLK上升沿附近就会引发亚稳态。正确做法是对rst_n做同步释放用两级触发器打两拍确保进入系统时已与时钟域对齐在时序图上把rst_n释放边沿当作虚拟时钟沿同样画Tsu/Th线检查。某次调试UART接收器发现偶尔丢帧最终定位到rst_n释放点距CLK上升沿仅200ps低于Tsu要求。加了同步电路后问题消失。所以时序图上除了CLK和D一定要把rst_n也画进去标清它的有效窗口。5.3 “FPGA里不用操心”——FPGA的时序约束更复杂很多人觉得FPGA有成熟IP核时序自动搞定。错FPGA的时序挑战在于IO标准影响大LVDS和LVCMOS的Vth不同导致Tsu/Th测量点偏移时钟网络灵活但难控MMCM/PLL输出的时钟相位可调但调相位可能恶化某些路径的SkewBlock RAM/FIFO IP的隐藏约束Xilinx FIFO Generator的read/write clock域切换有额外的Setup/Hold要求文档里藏得很深。我处理过一个PCIe endpoint项目用Vivado的report_timing_summary看一切正常但实测吞吐率上不去。用ChipScope抓波形发现user_clk和app_clk域交叉处Setup Margin仅0.05ns。解决方案是在Vivado中显式添加set_input_delay -clock [get_clocks user_clk] 1.5 [get_ports app_rdata]约束把输入延迟从默认0.8ns提高到1.5ns问题解决。所以FPGA工程师更要画时序图因为它的约束是“软”的不画图你根本不知道约束写对没。5.4 面试高频题实战解析用时序图秒杀经典考题面试官最爱问“为什么Hold时间通常比Setup时间短”答案不能只说“工艺决定”要结合图讲Hold检查的是时钟沿后数据保持依赖的是锁存器关断速度而关断比建立快PMOS关断比NMOS建立快Setup要等数据穿越整个组合逻辑路径长Hold只关心D端局部变化路径短。再比如“如何修Hold违例”标准答案是“加buffer”但高手会补充“加在D端而非CLK端因为加在CLK端会恶化Setup”。我建议候选人现场画图在白板上画出CLK、D、Th线然后在D线上加一段buffer标出延迟增加立刻体现Hold Margin变大Setup Margin不变——这才是面试官想看的思维过程。最后分享个硬核技巧遇到“AXI协议时序”类问题别死背waveform直接画主从设备交互图。标出AWVALID/AWREADY握手点把Master的AWVALID边沿当作D信号Slave的AWREADY边沿当作CLK立刻套用Setup/Hold模型——AXI的Setup就是AWVALID要比AWREADY早到多久Hold就是AWVALID拉高后要保持多久。所有协议时序本质都是触发器输入输出的变形抓住这个内核万变不离其宗。我在实际项目中发现真正能把Setup/Hold讲透的人不是背熟手册的而是能随手画出触发器内部结构、标出每个信号路径、并用示波器实测验证的。这张时序图不是学习终点而是你走进数字电路物理世界的通行证——它让你看见电子在硅片上奔跑的轨迹听见晶体管开关的咔嗒声。下次再看到“i2c时序图”或“axi时序图”别急着查资料先拿出纸笔画出CLK和DATA标上Tsu和Th问问自己数据在这里稳定了吗时钟在这里可靠吗答案就在那两条虚线之间。
延伸阅读

更多相关文章

2026/10/7 13:31:27

Java毕设实战:高校智能浴室管理系统源码拆解与二次开发指南

简介:这份资源是面向高校计算机相关专业学生与Java初学者的一套完整项目实战包,以「高校智能浴室管理系统」为题,可作为毕业设计、课程设计或AndroidJava全栈练手参考。系统采用Java语言与JDK1.8开发,数据库为MySQL 5.7&#xff0…

2026/10/7 13:31:27

AI编程智能体全解析:从自动补全到自主执行,程序员如何借力升级

这两年,AI编程工具的变化快得有点让人喘不过气。上半年大家还在讨论Copilot能不能帮我们少写点样板代码,下半年画风就变了——AI不再只是“补全括号”的助手,而是可以自己读需求、改代码、跑测试、修Bug的“编程智能体”。作为一个写了十几年…

2026/10/7 14:16:32

控制即推断:从最优控制到概率推断的建模视角转换

1. 为什么值得把控制问题当成推断问题来做第一次看到“Control as Inference”这个说法,我脑子里冒出来的疑问很直接:控制就是控制,推断就是推断,一个是让系统按预期动起来,一个是根据观测猜隐藏变量,这两件…

2026/10/7 14:16:32

Agent Skills 技能体系实战:从设计到 GKE 部署

1. 从“skills”这个标题说起:它到底指什么第一次看到“skills”这个标题,很多人会以为是泛泛而谈的“技能”二字,没什么信息量。但结合热词里反复出现的 Google Cloud、Agent Skills、npx、GKE、claude agent skills、codex skills 这些词&a…

2026/10/7 14:16:32

eFuse+MCU:工业电源路径保护方案设计与实践

前阵子帮一个做工业网关的朋友排查现场返修问题,设备返修率一度高得吓人。拆开故障板一看,坏得最集中的不是 DC-DC,也不是负载端的 MCU,而是输入端到 DC-DC 之间那一小段电源路径——走线烧断、防反接 MOS 击穿、甚至 PCB 铜箔直接…

2026/10/7 14:11:31

MCP从入门到实战:用TaoToken统一Key搭建AI Agent工具调用系统

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/7 8:18:33

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/6 17:46:51

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:05:03

ESP32免重刷固件:浏览器直接修改NVS键值实现WiFi配置更新

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:05:03

SAP HANA查询结果导出CSV:避开乱码、性能与权限的实用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/7 1:05:03

数字后端Placement阶段Density与Congestion控制实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑