【FPGA开发】Xilinx锁相环IP核仿真输出初始有一段高电平引发的思考与探究

现象

本来是在通过Xilinx提供的 Clocking Wizard IP核做有关锁相环的实验,在Vivado中的仿真结果如下:

后面输出的时钟波形是对的,但4路输出前确有一小段高电平,仔细放大看一下:

这个高电平持续了一个周期,这就奇怪了,无论是源代码还是仿真代码,都不涉及到它们四个wire类型的变量的初值之类的。

原始代码

源代码:

verilog 复制代码
module ip_clk_wiz(
    input  sys_clk_p,
    input  sys_clk_n,
    input  sys_rst_n,
    output o_pll_clk
    );

wire clk_out1;
wire clk_out2;
wire clk_out3;
wire clk_out4;

assign o_pll_clk = clk_out4;
    
clk_wiz_0 instance_name(

    .clk_out1  (clk_out1  ),
    .clk_out2  (clk_out2  ),
    .clk_out3  (clk_out3  ),
    .clk_out4  (clk_out4  ),
               
    .reset     (~sys_rst_n),
    .locked    (          ),

    .clk_in1_p (sys_clk_p ),
    .clk_in1_n (sys_clk_n )
    );
    
endmodule

tb代码:

verilog 复制代码
`timescale 100ps / 100ps
 
module tb_ip_clk_wiz();

reg sys_clk_p;
reg sys_clk_n;
reg sys_rst_n;

initial begin
    sys_clk_p <= 1'b0;
    sys_clk_n <= 1'b1;
    sys_rst_n <= 1'b0;
    #1000
    sys_rst_n <= 1'b1;
end

always begin
    sys_clk_p <= 1'b0;
    sys_clk_n <= 1'b1; 
    #25;
    sys_clk_p <= 1'b1;
    sys_clk_n <= 1'b0;        
    #25;
end

ip_clk_wiz u_ip_clk_wiz(
    .sys_clk_p   (sys_clk_p),
    .sys_clk_n   (sys_clk_n),
    .sys_rst_n   (sys_rst_n),
    
    .o_pll_clk   ()
    );   
     
endmodule

探究

一开始想着,是不是跟 IP 核的高电平复位有关,因为初始的复位是有效的,对于IP核就一直处于复位状态,然后干脆就IP核的复位都直接不接了,但还是会有这么一段高电平。

然后,尝试把 IP 核的例化注释掉,结果如下:

这样似乎就合乎常理了,因为 wire 类型变量按照语法,在仿真开始时,wire 变量的值是不确定的(通常表现为高阻态或未定义值,即 x 或 z ),这里就是表现为 z 高阻态。

想到这我接着探究,既然IP核的例化都注释掉了,那再用 modelsim 仿真一下,看看,结果如下:

与 Vivado 的结果相同。

综合以上的尝试,我们可以知道,出现最开始现象的原因应该是与 IP 核有关,不过结合 testbench 文件仔细研究一下那个输出:

​ 在 t=100ns 复位变为高电平,对于IP而言,开始有效输出,但根据波形可以看出,最终的有效时钟信号是在 200ns 以后产生的,这是因为,IP 核要获取稳定地输出需要一定的时间,与此同时也让人联想到了我前面源代码中没有接的 locked 信号,Xilinx 对它的解释如下:

即只有稳定了以后,才会把它拉高有效,我们继续仿真试试看,把这个信号加进来。

可以发现这个信号会在我们之前看到的有效时钟出来之后才会拉高,也进一步验证了前面的观点。对于我们的启示是,在实际使用 Clocking Wizard IP核时,最好是在判断 lock 信号拉高后再使用它输出的时钟,不然可能会出现一些隐蔽的隐患。

后来看正点原子的视频时发现,它们也提到,实际使用时,可以再给一个内部的复位信号采用以下逻辑给出这个复位信号,然后在这个复位信号有效的情况下再去进行一些用到PLL输出的时钟的操作。

verilog 复制代码
wire        locked;
wire        rst_n;
assign rst_n = sys_rst_n & locked;
相关推荐
水果里面有苹果4 小时前
1-FPGA的LUT理解
fpga开发
千宇宙航20 小时前
闲庭信步使用图像验证平台加速FPGA的开发:第二十七课——图像腐蚀的FPGA实现
图像处理·计算机视觉·fpga开发·图像腐蚀
小白到大佬1 天前
High Speed SelectIO Wizard ip使用记录
fpga开发·lvds·高速接口
嵌入式-老费1 天前
再谈fpga开发(fpga开发的几个特点)
fpga开发
范纹杉想快点毕业2 天前
基于C语言的Zynq SOC FPGA嵌入式裸机设计和开发教程
c语言·开发语言·数据库·嵌入式硬件·qt·fpga开发·嵌入式实时数据库
YONYON-R&D2 天前
LAYOUT 什么时候需要等长布线?
嵌入式硬件·fpga开发
我不是程序猿儿2 天前
【Servo】裸机还是RTOS驱动架构如何选?
驱动开发·fpga开发·架构·伺服驱动器·伺服
乌恩大侠2 天前
USRP X440
fpga开发
minglie12 天前
PetaLinux 使用技巧与缓存配置
fpga开发
青春猪头ic少年梦不到兔女郎师姐3 天前
软硬件协同仿真和验证的标准接口协议SCE-MI简介
fpga开发·uvm验证·软硬件协同仿真验证