Xilinx FPGA时序约束简单实例

该博客介绍了在FPGA设计中处理低频时钟分频以及跨时钟域同步的问题。通过使用计数器实现时钟分频,并详细展示了如何进行时钟约束,包括创建生成时钟、设置时钟相位,以及解决时序错误。在时序调试过程中,通过调整时钟相位避免了亚稳态,最终成功实现了时序收敛。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题阐述

源自通信算法的一个工程,存在两种频率,基带算法频率和中频频率,记为clk_1和clk_2,分别为2kHz与100kHz,对于FPGA为低频时钟。以接收端为例,接收端接收到频率为clk_1的中频信号后需经过变频等操作,变换到基带的clk_2,因此涉及到多bit信号快时钟域到慢时钟域的处理问题,相反的发射端是慢时钟域到快时钟域的问题。这里以接收端为例说明时序约束的方法。

1. 时钟分析

使用的FPGA为ZYNQ7020,时钟为50MHz,由PS端产生,如图所示。
在这里插入图片描述
由于clk_1和clk_2频率过低,MMCM和PLL无法生成,因此采用计数器来实现时钟分频。分频代码:

module clk_gen(
    input sys_clk, //系统时钟
    input sys_rst_n,
    
    output reg clk_1, //基带时钟 2k 
    output reg clk_2 //中频时钟 100k
    );

reg [5:0] clk_cnt_1;
reg [9:0] clk_cnt_2;

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(sys_rst_n==1'b0)begin
        clk_cnt_1<=5'b0;
        clk_cnt_2<=10'b0;
        clk_1<=1'b0;
        clk_2<=1'b0;
    end    
    else if(clk_cnt_1<6'd49)begin
        if(clk_cnt_2<10'd249)begin
            clk_cnt_2<=clk_cnt_2+1'b1;
        end
        else begin
            clk_cnt_2<=10'b0;
            clk_2<=~clk_2;
            clk_cnt_1<=clk_cnt_1+1'b1;
        end
        end
        else begin
            if(clk_cnt_2<10'd249)begin
                clk_cnt_2<=clk_cnt_2+1'b1;
            end
            else begin
                clk_cnt_1<=5'b0;
                clk_cnt_2<=10'b0;
                clk_1<=~clk_1;
                clk_2<=~clk_2;
            end
        end  

仿真:
在这里插入图片描述

2. 添加时钟约束

对整个工程综合、实现,看到timing如下:
在这里插入图片描述

此时时序没有报错,但实际是因为没有做时序约束引起的,在tcl运行命令:

report_clock_networks -name timing

打开"clock networks":
在这里插入图片描述
这里两个未约束时钟就是clk_1,clk_2:
在这里插入图片描述
右键时钟,选择"create generated clock"
在这里插入图片描述
设置名字,来源时钟,分频系数:
在这里插入图片描述

在这里插入图片描述
此时再查看"clock networks",时钟都被约束:
在这里插入图片描述
输入命令:

report_clocks

可以查看:
在这里插入图片描述
generated clocks:
在这里插入图片描述
此时再查看xdc文件,多了这两条:

create_generated_clock -name clk_2 -source [get_pins system_i/top_module_0/sys_clk] -divide_by 500 -add -master_clock clk_fpga_0 [get_pins system_i/top_module_0/inst/u_receiver/u_clk_gen/clk_2_reg/Q]
create_generated_clock -name clk_1 -source [get_pins system_i/top_module_0/sys_clk] -divide_by 25000 -add -master_clock clk_fpga_0 [get_pins system_i/top_module_0/inst/u_receiver/u_clk_gen/clk_1_reg/Q]

3. 时序调试

再进行综合,实现,时序出现错误:
在这里插入图片描述
查看报告主要是clk_2到clk_1出现了建立时间的错误:
在这里插入图片描述
这属于多bit信号跨时钟域处理问题,常见的方法异步FIFO、DMUX等,网上资料很多,但我们这个时钟频率很低,不需要用到这么复杂的方法。
查看"clocking summary":

“waveform"里有时钟的相位信息,clk_1和clk_2是相位偏移为0的时钟,clk_1时钟域对clk_2时钟域采样的时候,二者的时钟沿差不多是重合的,猜测可能在数据变化的时候进行了采样,从而可能会产生亚稳态。但是如果让clk_1和clk_2的相位错开,在clk_2高电平或低电平的中间对数据进行采样,因为clk_2的时钟频率对FPGA来说是很低的,在数据稳定时进行采样可能可以避免亚稳态的出现。
所以我们做一个小的修改,删除xdc里的对clk_2时钟约束,然后对其重新设置:
在这里插入图片描述
其他设置都相同,不同的是在"derive from source clock waveform"里选择"by clock edges”,设置的是前三个上升沿或下降沿。
再重新进行综合,xdc文件里也多了代码:

create_generated_clock -name clk_2 -source [get_pins system_i/top_module_0/sys_clk] -edges {1 2 3} -edge_shift {2500.000 7500.000 12500.000} -add -master_clock clk_fpga_0 [get_pins system_i/top_module_0/inst/u_receiver/u_clk_gen/clk_2_reg/Q]

此时的"waveform":
在这里插入图片描述
此时时序也不再报错:
在这里插入图片描述
后续再修改一下clk_gen的代码,来修改下clk_2的初始相位应该就可以了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值