《FPGA基础知识》系列导航
本专栏专为FPGA新手打造的Xilinx平台入门指南。旨在手把手带你走通从代码、仿真、约束到生成比特流并烧录的全过程。
本篇是该系列的第十三篇内容
上一篇:FPGA基础知识(十二):详解跨时钟域约束-优快云博客
下一篇:FPGA基础知识(十四):FIFO工作原理与基础概念-优快云博客
深入解析分数分频时钟的约束方法,解决实际工程中的时序分析难题
在复杂的FPGA设计中,单一时钟源通过PLL或MMCM生成多个衍生时钟是常见做法。但当分频系数不是整数时(如100MHz生成35MHz),很多工程师在约束时会感到困惑。本文将深入探讨衍生时钟,特别是非整数分频时钟的约束策略。
1 衍生时钟的基本概念
1.1 什么是衍生时钟?
衍生时钟(Generated Clock)是由设计中的内部电路(如PLL、MMCM、分频器等)从主时钟派生出来的时钟信号。它们与主时钟有确定的频率和相位关系。
// 简单的寄存器分频示例
always @(posedge clk_100m) begin
if (reset) begin
clk_25m <= 1'b0;
counter <= 0;
end else begin
if (counter == 3) begin
clk_25m <= ~clk_25m;
counter <= 0;
end else begin
counter <= counter + 1;
end
end
end
1.2 非整数分频的挑战
非整数分频(如100MHz → 35MHz)带来几个独特挑战:
-
周期不是整数纳秒:35MHz周期 ≈ 28.571ns
-
时钟边沿不规则:分数关系导致边沿对齐复杂
-
时序分析精度:工具需要精确周期值进行有效分析
2 非整数分频时钟的约束方法
2.1 方法一:精确周期约束(推荐)
直接计算精确周期并进行约束:
# 使用精确周期值
create_clock -period 28.571428 -name clk_35m [get_pins mmcm_inst/CLKOUT0]
# 或者使用TCL计算
set clk35_period [expr 1000.0 / 35.0] ;# 计算结果: 28.57142857
create_clock -period $clk35_period -name clk_35m [get_pins mmcm_inst/CLKOUT0]
2.2 方法二:使用分频系数约束
对于能够明确分频系数的情况:
# 100MHz → 35MHz = 20/7 分频比
create_generated_clock -name clk_35m \
-source [get_pins mmcm_inst/CLKIN] \
-divide_by 20 -multiply_by 7 \
[get_pins mmcm_inst/CLKOUT0]
2.3 完整工程示例
假设一个系统需要从100MHz主时钟生成35MHz:
# 主时钟定义
create_clock -period 10.000 -name clk_100m [get_ports sys_clk]
# MMCM生成35MHz的时钟
# 35MHz: 1000/35 = 28.57142857 ns
create_generated_clock -name clk_35m \
-source [get_pins mmcm_inst/CLKIN] \
-divide_by 20 -multiply_by 7 \
[get_pins mmcm_inst/CLKOUT0]
# 注意:实际分频系数 = 100/35 = 20/7
# -divide_by 20 -multiply_by 7 表示频率乘以7/20
# 时钟关系约束
set_clock_groups -asynchronous \
-group {clk_100m} \
-group {clk_35m}
2.4 验证时钟关系
# 检查生成的时钟周期
report_clocks
# 验证时钟网络
report_clock_networks
# 检查时钟交互
report_clock_interaction
3 实际工程中的处理策略
策略1:基于IP核生成的约束
当使用Xilinx Clocking Wizard时,工具会自动生成精确约束:
# 通常由Vivado自动生成的约束类似这样:
create_clock -period 10.000 -name sys_clk [get_ports sys_clk]
# Clocking Wizard会自动创建生成的时钟约束
# 你可以在生成的xdc文件中找到类似内容:
create_generated_clock -name clk_out1_mmcm \
-source [get_pins mmcm_inst/CLKIN1] \
[get_pins mmcm_inst/CLKOUT0]
策略2:手动精确约束
如果需要手动约束,推荐的计算方法:
# 精确频率到周期的转换函数
proc freq_to_period {freq_mhz} {
return [expr 1000.0 / $freq_mhz]
}
# 使用函数定义多个非整数时钟
create_clock -period [freq_to_period 35.0] -name clk_35m [get_pins mmcm/CLKOUT0]
create_clock -period [freq_to_period 27.5] -name clk_27m [get_pins mmcm/CLKOUT1]
create_clock -period [freq_to_period 41.7] -name clk_41m [get_pins mmcm/CLKOUT2]
4 精度对时序分析的影响
不同精度级别的比较
# 低精度:可能引入时序误差
create_clock -period 28.57 -name clk_35m_low_precision [get_pins mmcm/CLKOUT0]
# 中等精度:工程常用
create_clock -period 28.571 -name clk_35m_medium_precision [get_pins mmcm/CLKOUT0]
# 高精度:对敏感设计推荐
create_clock -period 28.571428 -name clk_35m_high_precision [get_pins mmcm/CLKOUT0]
精度选择指南
-
一般应用:3位小数精度(如28.571ns)足够
-
高速接口:推荐4-6位小数精度
-
时钟恢复系统:可能需要更高精度
5 实用工具和脚本
自动计算脚本
# 自动频率到周期转换脚本
proc create_frequency_clock {clk_name clk_pin freq_mhz} {
set period_ns [expr 1000.0 / $freq_mhz]
create_clock -period $period_ns -name $clk_name [get_pins $clk_pin]
puts "Created clock $clk_name: $freq_mhz MHz -> $period_ns ns"
return $period_ns
}
# 使用示例
create_frequency_clock clk_35m mmcm_inst/CLKOUT0 35.0
create_frequency_clock clk_27m mmcm_inst/CLKOUT1 27.5
约束验证脚本
# 验证时钟约束的完整性
proc verify_clock_constraints {} {
# 检查所有时钟是否正确定义
set clocks [get_clocks]
if {[llength $clocks] == 0} {
puts "Error: No clocks defined!"
return 0
}
# 报告每个时钟的周期
foreach clock $clocks {
set period [get_property PERIOD $clock]
set sources [get_property SOURCES $clock]
puts "Clock: $clock, Period: $period ns, Source: $sources"
}
return 1
}
# 运行验证
verify_clock_constraints
6 工程实践经验
经验1:保持一致性
在整个项目中保持精度一致性:
# 好的实践:统一使用3位小数
create_clock -period 10.000 -name clk_100m [get_ports clk_in]
create_clock -period 28.571 -name clk_35m [get_pins mmcm/CLKOUT0]
create_clock -period 16.667 -name clk_60m [get_pins mmcm/CLKOUT1]
经验2:文档化约束决策
在约束文件中添加注释:
# 时钟约束说明:
# 主时钟: 100MHz 外部晶振
# 生成时钟1: 35MHz (1000/35 = 28.57142857ns) 用于视频处理
# 生成时钟2: 27.5MHz (1000/27.5 = 36.36363636ns) 用于音频处理
create_clock -period 10.000 -name clk_100m [get_ports sys_clk]
create_clock -period 28.571 -name clk_video [get_pins mmcm/CLKOUT0]
create_clock -period 36.364 -name clk_audio [get_pins mmcm/CLKOUT1]
经验3:考虑工具限制
不同工具对精度的支持:
-
Vivado:支持至少6位小数精度
-
Quartus:类似的高精度支持
-
第三方工具:可能需要检查具体限制
总结
处理非整数分频时钟约束的关键点:
-
精确计算:使用
1000.0 / 频率公式计算周期 -
合理精度:通常3位小数精度足够工程使用
-
一致性:在整个项目中保持精度标准一致
-
文档化:记录约束决策和计算过程
-
验证:运行时序分析验证约束效果
记住:约束的精度应该与设计的时序要求相匹配。对于大多数应用,3位小数精度提供了良好的平衡点,既能满足时序分析需求,又不会过度复杂化约束文件。
559

被折叠的 条评论
为什么被折叠?



