时钟信号设计基础——FPGA

35 篇文章 5 订阅
8 篇文章 2 订阅

目录/contents

● 时钟信号设计概述

● 时钟信号属性特征

● 常见时钟信号概念

● 时钟信号设计要点

01——时钟信号设计概述

时钟信号作为数字电路系统的“心脏”,始终伴随着数字电路信号的变化,在数字电路设计中具有重要意义。数字电路通常被划分为组合逻辑与时序逻辑,在实际数字电路系统中又存在同步电路和异步电路的区别,这些都与时钟信号密切相关。

通常情况下,时钟信号是指由时钟源产生具有一定频率的方波信号,时钟源根据来源分为外部时钟源和内部时钟源:

  • 外部时钟源:由外部电路或器件产生,例如,石英晶体/晶振、RC/LC振荡电路、MEMS时钟振荡器、555振荡电路和8038振荡电路等;

  • 内部时钟源:由内部逻辑或器件产生,例如,锁相环(PLL)和分频电路等。

由于异步电路通常会存在竞争冒险和亚稳态等问题,所以数字逻辑电路设计过程中通常采用同步设计,即电路中寄存器由共同的时钟电路控制,从而可以有效提高系统的最高工作频率,提升系统的性能。

02——时钟信号属性特征

时钟信号在数字电路系统中主要以时钟树的形式体现,一套完整的数字电路系统通常涉及多个时钟信号,不同时钟信号具备不同的属性特征。通过分析时钟信号的属性特征,可以区分不同的时钟/时钟域,从而为系统设计提供更加健康的时序关系。

时钟信号的属性特征可以划分为基本属性和偏差属性两部分:基本属性通常包括时钟周期、频率、相位、电平、边沿和占空比等特征;偏差属性通常包括时钟精度、温漂、偏移、抖动、延时和转换时间等特征。

2.1 时钟信号的基本属性

对于理想时钟而言,周期、频率、相位、电平、边沿和占空比等特征通常决定唯一的时钟波形,因此可以认为,基本属性相同的理想时钟是同一时钟信号。

2.1.1 时钟周期(Period)

时钟周期是指时钟信号周期性重复出现的固定时间间隔,通常用时间单位(s)表示。

2.1.2 时钟频率(Frequency)

时钟频率是指时钟信号每秒钟重复出现的周期数,单位为赫兹(Hz)。频率f和周期T的关系:f=1/T,例如,25MHz频率的时钟表示每秒重复出现25,000,000次,时钟周期为40ns。

2.1.3 时钟相位(Phase)

时钟相位是指时钟信号的位置或偏移量相对于某个参考点或时间基准的位置,可以用于控制电路工作顺序和时序关系,通常用角度或时间单位表示。

2.1.4 时钟电平(Level)

时钟电平是指时钟信号的电压状态,电压基于不同电平标准可分为高电平和低电平,通常情况下高电平表示为逻辑1,低电平表示逻辑0。例如,在3.3V电压标准下,高电平3.3V表示为逻辑1,低电平0V表示为逻辑0。

2.1.5 时钟沿(Edge)

时钟沿是指时钟信号从一个电平到另一个电平的过渡点,可以用来触发和同步电路,通常情况下从低电平到高电平的时钟沿为上升沿,从高电平到低电平的时钟沿为下降沿。

2.1.6 时钟占空比(Duty Cycle)

时钟占空比是指时钟信号在一个周期内高电平时间所占总周期时间的比例,通常以百分比表示。例如,40%的占空比表示高电平占一个周期的40%。

2.2 时钟信号的偏差属性

由于器件材料、工艺、温度等各种因素导致的噪声,实际时钟通常无法保证绝对的精准,所以除理想时钟的基本属性之外,还需要考虑到时钟信号的偏差属性。

2.2.1 时钟精度(Accuracy)

时钟精度是指在25℃下实际测量时钟相对于标准频率的偏差,单位是ppm(百万分之一)。例如,晶振规格说明书中Initial Tolerance指出时钟精度为±15ppm,即该晶振每秒将会产生15us的误差。若时钟频率为25MHz,周期为1/25MHz=40ns,那么每个时钟周期产生的精度偏差值就是40ns*(±15/1000000)=0.6ps。

2.2.2 时钟温漂(Temperature Drift)

由于材料和工艺的限制,晶振在不同的温度下精度会有较大的偏差,这种精度偏差被称为时钟温漂,单位是ppm(百万分之一)。例如,晶振规格说明书中Frequency Stability指出时钟温漂存在±50ppm和±100ppm两种规格。若时钟频率是25MHz,并且选择了±100ppm的型号,那么每个时钟周期由于温漂所产生的精度偏差值就是40ns*(±100/1000000)= 4ps。

2.2.3 时钟偏移(Skew)

在时钟信号驱动多个寄存器时,由于线网的传输延时,到达不同寄存器时钟端口的时钟信号存在有相位差,无法保证所有的时钟沿对齐,这种差异称为时钟偏移。时钟偏移与时钟频率不存在直接关系,而与时钟布线长度和被时钟驱动的时序单元数量相关,在实际工程设计中可以用时钟不确定性Uncertainty进行约束。

2.2.4 时钟抖动(Jitter)

相比于理想时钟,实际时钟存在一定的不随时间积累的周期性偏差,这种偏差称为时钟抖动(Jitter)。时钟抖动可以分为随机性抖动(Random Jitter)和确定性抖动(Deterministic Jitter):随机性抖动与半导体工艺相关,造成随机性抖动的原因通常是热噪声等材料物理噪声;确定性抖动与电路设计相关,造成确定性抖动的原因通常是PCB布局布线不合理引发的电磁干扰和阻间串扰等。时钟抖动通常以ps或fs为单位,与时钟频率不存在直接关系,在实际工程设计中同样可以用时钟不确定性Uncertainty进行约束。

2.2.5 时钟延时(Latency)

在时钟信号从时钟源传输到寄存器时钟端口的过程中,线网的传输导致存在时钟延时,包括时钟源延时(Source Latency)和时钟网络延时(Network Latency):

时钟源延时:也可称为插入延时,指时钟信号从实际时钟源到设计定义时钟源的传输时间;

时钟网络延时:指时钟信号从设计定义时钟源,经过缓冲器和线网,到寄存器时钟引脚的传输时间。

2.2.6 时钟转换时间(Transition)

理想时钟通常被认为是理想的方波信号,上升沿与下降沿直接的跳变时间往往被忽略。然而,实际时钟上升沿与下降沿的跳变需要一定的时间,这段时间被称为时钟的转换时间。时钟的转换时间与单元延时和电容负载相关。

03——常见时钟信号概念

在数字电路系统中,除时钟源(晶振)提供提供的主时钟以外,还存在多种不同的时钟概念,例如,衍生时钟、随路时钟、虚拟时钟、内部逻辑生成时钟、门控时钟、行波时钟、双边沿时钟和多路复用时钟等。本节将主要介绍以上时钟相关概念,为时钟设计提供参考。

3.1 STA相关时钟

STA(Static Timing Analysis, 静态时序分析)涉及到的时钟类型主要有主时钟、衍生时钟、随路时钟和虚拟时钟,EDA软件通常依据上述时钟从输入/输出延时等角度进行计算分析,验证数字系统时序是否健康。

如图所示,其中 CLK 1 是主时钟,CLK 2 是由MMCM输出的衍生时钟,CLK 3 是端口A数据的随路时钟。如果衍生时钟 CLK 2 与主时钟 CLK 1 频率不是整数倍关系,那么在对C端口数据采样时,由于没有随路时钟,所以需要创建虚拟时钟用内部时钟捕获数据。

3.1.1 主时钟

主时钟是指系统中的主要时钟信号,通常由外部晶振或时钟发生器提供。主时钟具有固定的频率和周期,为整个数字信号系统提供时钟源,用于信号同步与时序控制。

3.1.2 衍生时钟

衍生时钟是指由主时钟通过分频、相位偏移或逻辑操作衍生或派生的时钟信号,例如专用时钟管理单元(PLL、MMCM等)生成的时钟信号。由于在数字信号系统中,除主时钟外还需要其他不同频率/相移的时钟信号驱动不同模块(例如,以太网phy芯片通常需要提供一个50MHz的输入时钟phy_clk),所以衍生时钟广泛存在于整个系统。

3.1.3 随路时钟

随路时钟是指随主时钟和数据一起送到下游模块的时钟信号,通常用于调整接口时序以满足器件建立/保持时间要求。随路时钟通常由PLL生成,通过调整随路时钟的相位,保证系统接口信号和时钟满足下游模块的建立/保持时间要求。

例如,FPGA操作SDRAM芯片时需要设计SDRAM接口模块,因此除SDRAM芯片主时钟SDRAM_clk外,还需要提供时钟clk控制SDRAM接口模块。因为由clk控制的SDRAM接口模块生成的信号D相对于clk存在一定的延时,所以,为满足SDRAM_clk建立/保持时间要求,可以通过PLL调整SDRAM_clk的相位,此时SDRAM_clk就是随路时钟。

3.1.4 虚拟时钟

虚拟时钟是指FPGA约束中的一种特殊的时钟信号,即在约束时未绑定特定的物理管脚。虚拟时钟的定义是因为以下两个方面:对于输入而言,输入到目标内部时序单元的捕获时钟由FPGA内部产生且与主时钟频率不同,或PCB的Clock Buffer导致时钟延迟不同;对于输出而言,目标内部逻辑单元只接受到数据而无随路时钟,需要用内部时钟进行捕获。

因此,虚拟时钟主要应用于以下三个场景:

  1. 外部IO的参考时钟不是设计中的时钟;

  2. I/O路径参考时钟来源于内部衍生时钟且与主时钟频率关系不是整数倍;

  3. I/O指定不同的抖动和延迟。

3.2 常见时钟设计

主时钟是指系统中的主要时钟信号,通常由外部晶振或时钟发生器提供。主时钟具有固定的频率和周期,为整个数字信号系统提供时钟源,用于信号同步与时序控制。

3.2.1 门控时钟

门控时钟是指利用使能信号控制时钟信号,当不需要使用时钟信号时,可以通过使能信号关闭时钟,从而降低系统的动态功耗,因此,门控时钟常用于系统低功耗设计。

通过分析波形图发现,如果门控使能信号在时钟的高电平时跳变,门控时钟高电平将会被截断为毛刺信号,而在时钟的低电平时跳变不会对门控时钟产生影响。因此,需要针对门控时钟电路高电平翻转进行优化。

寄存器可以有效处理毛刺问题,通过设计同步门控时钟电路,保证门控信号在高电平保持,低电平翻转,从而有效解决在门控时钟高电平处翻转被截断的问题。

注:当门控使能信号高电平有效时,采用触发器时钟沿为低电平触发;当门控使能信号低电平有效时,采用触发器时钟沿为高电平触发。

3.2.2 行波时钟

行波时钟是指上一级触发器的输出用作下一级触发器的时钟输入,通常应用于异步计数器和分频电路设计。行波时钟原理简单、设计方便,但容易造成时钟偏差,当级联触发器数目较多时,可能会导致信号无法满足触发器的建立\保持时间要求,造成亚稳态等问题的发生。

3.2.3 双边沿时钟

双边沿时钟是指系统在时钟的上升沿和下降沿均进行数据传输,从而将数据的传输速率提高一倍,例如,DDR(Double Data Rate) SDRAM存储器时钟。

在一般情况下,设计中不建议使用双边沿时钟:

  • 上升沿和下降沿同时使用对时钟质量要求很高,一般时钟源很难达到要求且时钟成本高;

  • 时钟抖动等不确定因素容易导致时钟占空比发生改变,造成建立/保持时间的时序违例;

  • 双边沿时钟约束复杂,相比于单边沿时钟,双边沿时钟的违例路径查找难度大;

  • 双边沿时钟测试难度大,在扫描测试时,上升沿和下降沿时钟都需要提前插入多路复用器进行选择。

3.2.4 多路复用时钟

多路复用时钟是指系统中的触发器需要多个不同频率的时钟进行驱动,为适应不同数据速率要求或节约功耗而进行的时钟切换。

多路复用时钟通常也会导致一些问题,例如,时钟切换导致驱动寄存器建立时间不足等,因此系统使用多路复用时钟需要满足一定的条件:

  • 时钟复用电路上电后不对复用逻辑进行更改,避免时钟切换可能导致的时序违例;

  • 在系统测试时,需要设计电路绕过时钟复用逻辑,选择普通时钟进行测试;

  • 在时钟切换时,寄存器应处于复位状态,避免时钟切换可能导致的建立时间不足,系统进入亚稳态;

  • 在时钟切换时,可能产生的短暂错误对整体系统没有影响;

  当系统要求严格时,例如时钟切换频繁,复位时无法切换,不允许短暂错误等,多路复用时钟的切换方法将不能被用于系统中,需要使用时钟同步或设计其他的时钟切换方案。

04——时钟信号设计要点

时钟信号对于时序逻辑至关重要,高质量的时钟信号可以保证数据传输的稳定性,因此,在设计时钟信号时通常需要注意以下几个方面:

  1. 减少门控时钟和内部逻辑产生时钟的使用,对于需要控制的时钟信号,尽量采用使能时钟替代:门控时钟和内部组合逻辑产生时钟容易出现毛刺和组合逻辑的固有延时将导致时序问题,影响设计的功能实现;

  2. 减少内部逻辑对时钟分频的使用,对于需要分频或倍频的时钟,尽量采用内部专用时钟管理单元(PLL、DLL或MMCM)生成:FPGA采用内部逻辑生成分频时钟存在精度较低、相位不稳等问题,尤其是在数据高速处理时,可能会出现时序问题。FPGA内部通常会集成专用的时钟管理单元,对于需要分频或倍频的时钟通常采用此类专用时钟管理单元生成;

  3. 减少异步信号复位或置位控制的使用,对于异步信号而言,尽量采用时钟进行锁存多拍后做同步处理:异步信号是指跨时钟域的信号,异步信号在不同频率\相位时钟间传输时,如果没有可靠的同步机制将会导致数据误采集。因此,异步信号通常不能直接作为内部复位或置位控制信号使用,需要本地时钟锁存多拍(通常为打两拍)同步处理后使用;

  4. 对于需要驱动多寄存器的时钟,尽量在设计过程中添加缓冲器以提高时钟的驱动能力:在默认情况下,驱动多寄存器的时钟在逻辑综合时,综合工具通常不会在时钟的连线上添加时钟缓冲器以提高驱动能力,而是将时钟输入端直接连接到所有寄存器的时钟引脚。因此,在设计中可以通过添加ODDR等缓冲器用以提高时钟的驱动能力。

  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个万年历的FPGA课程设计的Verilog代码和仿真: ``` module calendar( input clk, // 时钟信号 input reset, // 复位信号 output reg [3:0] year, // 年份 output reg [3:0] month, // 月份 output reg [4:0] day, // 日 output reg [2:0] week // 星期 ); // 闰年判断 wire leap_year = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); // 每月天数 reg [6:0] days_in_month; always @(*) begin case (month) 4, 6, 9, 11: days_in_month = 30; 2: days_in_month = leap_year ? 29 : 28; default: days_in_month = 31; endcase end // 日历计算 reg [5:0] day_count; reg [2:0] day_of_week; always @(posedge clk or posedge reset) begin if (reset) begin year <= 0; month <= 1; day <= 1; week <= 0; day_count <= 0; day_of_week <= 0; end else begin if (day_count == 0) begin day_count <= 1; day_of_week <= (day_of_week == 6) ? 0 : day_of_week + 1; if (day == days_in_month) begin day <= 1; if (month == 12) begin month <= 1; year <= year + 1; end else begin month <= month + 1; end end else begin day <= day + 1; end end else begin day_count <= day_count + 1; end week <= (day_count + day_of_week) % 7; end end endmodule ``` 在上面的代码中,我们使用了一个状态机来计算每一天的日期和星期。在每个时钟上升沿,我们检查当前是否需要更新日历,以及更新哪些日期和星期。我们还使用一个闰年标志来计算每个月的天数。最后,我们将日历输出到四个输出端口。 以下是一个简单的仿真测试,它显示了日历的输出。在仿真中,我们提供了一个时钟信号和一个复位信号,以便在仿真开始时将日历复位为1月1日。 ``` module calendar_tb; reg clk; reg reset; wire [3:0] year; wire [3:0] month; wire [4:0] day; wire [2:0] week; calendar dut( .clk(clk), .reset(reset), .year(year), .month(month), .day(day), .week(week) ); initial begin clk = 0; reset = 1; #10 reset = 0; end always #5 clk = ~clk; initial begin $monitor("%d/%d/%d %d", year, month, day, week); #100 $finish; end endmodule ``` 在上面的仿真测试中,我们使用了一个monitor语句来跟踪日历的输出,并在仿真完成时结束仿真。我们还提供了一个时钟和复位信号以启动仿真。 希望这个代码和仿真对您有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Me sl ·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值