Verilog基础之十七、锁相环PLL

目录

一、前言

1.1 背景

1.2 PLL结构

二、工程设计

2.1 PLL IP核配置

2.2 设计代码

2.3 测试代码

2.4 仿真结果

2.5 常见问题


一、前言

1.1 背景

    若将一个FPGA工程看做一个人体,时钟的重要性丝毫不亚于心脏对于人体的重要性,时钟的每一个周期对于工程都是一次全面的状态更新,因此,时钟的有效使用重要性不言而喻。

    以赛灵思7系列的器件为例,在之前的文章Xilinx之7系列时钟资源与时钟架构 中,第三节时钟管理单元 提到了7系列时钟管理单元CMT,CMT包含了MMCM和PLL,PLL的功能为MMCM功能的子集,可实现时钟网络去偏斜,频率合成,去抖动。

1.2 PLL结构

     根据赛灵思官网用户手册,PLL的结构如下图

    PLL主要的组成部分有图中3个红色框:鉴相器PFD,电荷泵CP和低通滤波器LF,压控振荡器VCO。实现的流程为VCO自身输出一个时钟CLKFBOUT反馈到PFD,PFD对输入时钟和反馈时钟的相位进行比较,将比较的相位差传输到CP和LF,LF主要用于滤除高频干扰信号。CP和LF会将结果转换成电压信号,电压信号控制VCO的输出频率。在PLL达到稳定状态后,输出频率FvcoH和输入频率Fclkin满足如下关系。

     对于例化PLL的原语有两种:PLLE2_BASE,PLLE2_ADV,PLLE2_ADV的端口更多,功能更丰富。

在Vivado的Language Templates中搜索PLL可查找到7系列的4个型号Atrix,都具有PLLE2_BASE,PLLE2_ADV两种类型,类似的MMCM也有两种BASE和ADV两种类型

以PLLE2_ADV为例,各端口说明如下,其中,CLKOUT0-CLKOUT3支持PLL/MMCM间的级联连接。

二、工程设计

   下面展示使用原语例化和IP核两种方式使用PLL,用CLKOUT0-CLKOUT3 4路输出示例,其中PLL IP核的配置与例化的PLL相同。

2.1 PLL IP核配置

2.2 设计代码

module PLL( CLKIN1,CLKIN2,CLKIN1_ip,CLKIN2_ip,RST,CLKINSEL,CLKOUT0,CLKOUT1,CLKOUT2,CLKOUT3,
CLKOUT0_ip,CLKOUT1_ip,CLKOUT2_ip,CLKOUT3_ip);
input CLKIN1,CLKIN2,CLKIN1_ip,CLKIN2_ip,RST,CLKINSEL;
output CLKOUT0,CLKOUT1,CLKOUT2,CLKOUT3;
output CLKOUT0_ip,CLKOUT1_ip,CLKOUT2_ip,CLKOUT3_ip;
wire n_clkfbout;

//使用PLLE2_ADV原语
   PLLE2_ADV #(
      .BANDWIDTH("OPTIMIZED"),  // OPTIMIZED, HIGH, LOW
      .CLKFBOUT_MULT(9),       //时钟输出乘该值
      .CLKFBOUT_PHASE(0.0),     // Phase offset in degrees of CLKFB, (-360.000-360.000).
      // CLKIN_PERIOD: Input clock period in nS to ps resolution (i.e. 33.333 is 30 MHz).
      .CLKIN1_PERIOD(10.0),    //参考时钟1周期为10ns
      .CLKIN2_PERIOD(8.333),    //参考时钟2周期为8.333ns
      // CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for CLKOUT (1-128)
      .CLKOUT0_DIVIDE(1),       //第一路输出分频系数为1
      .CLKOUT1_DIVIDE(2),       //第一路输出分频系数为2
      .CLKOUT2_DIVIDE(10),      //第一路输出分频系数为10
      .CLKOUT3_DIVIDE(20),      //第一路输出分频系数为20
//      .CLKOUT4_DIVIDE(10),
//      .CLKOUT5_DIVIDE(20),
      // CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.001-0.999).
      .CLKOUT0_DUTY_CYCLE(0.5),  //第一路输出占空比为0.5
      .CLKOUT1_DUTY_CYCLE(0.1), //第一路输出占空比为0.1 
      .CLKOUT2_DUTY_CYCLE(0.3), //第一路输出占空比为0.3
      .CLKOUT3_DUTY_CYCLE(0.7), //第一路输出占空比为0.7
//      .CLKOUT4_DUTY_CYCLE(0.4),
//      .CLKOUT5_DUTY_CYCLE(0.6),
      // CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000).
      .CLKOUT0_PHASE(0.0),
      .CLKOUT1_PHASE(0.0),
      .CLKOUT2_PHASE(0.0),
      .CLKOUT3_PHASE(0.0),
      .CLKOUT4_PHASE(0.0),
      .CLKOUT5_PHASE(0.0),
      .COMPENSATION("ZHOLD"),   // ZHOLD, BUF_IN, EXTERNAL, INTERNAL
      .DIVCLK_DIVIDE(1),        // Master division value (1-56)
      // REF_JITTER: Reference input jitter in UI (0.000-0.999).
      .REF_JITTER1(0.0),
      .REF_JITTER2(0.0),
      .STARTUP_WAIT("FALSE")    // Delay DONE until PLL Locks, ("TRUE"/"FALSE")
   )
   PLLE2_ADV_inst (
      // Clock Outputs: 1-bit (each) output: User configurable clock outputs
      .CLKOUT0(CLKOUT0),   // 1-bit output: CLKOUT0
      .CLKOUT1(CLKOUT1),   // 1-bit output: CLKOUT1
      .CLKOUT2(CLKOUT2),   // 1-bit output: CLKOUT2
      .CLKOUT3(CLKOUT3),   // 1-bit output: CLKOUT3
      .CLKOUT4(CLKOUT4),   // 1-bit output: CLKOUT4
      .CLKOUT5(CLKOUT5),   // 1-bit output: CLKOUT5
      // DRP Ports: 16-bit (each) output: Dynamic reconfiguration ports
      .DO(),             // 16-bit output: DRP data
      .DRDY(),         // 1-bit output: DRP ready
      // Feedback Clocks: 1-bit (each) output: Clock feedback ports
      .CLKFBOUT(n_clkfbout), // 1-bit output: Feedback clock
      .LOCKED(),     // 1-bit output: LOCK
      // Clock Inputs: 1-bit (each) input: Clock inputs
      .CLKIN1(CLKIN1),     // 1-bit input: Primary clock
      .CLKIN2(CLKIN2),     // 1-bit input: Secondary clock
      // Control Ports: 1-bit (each) input: PLL control ports
      .CLKINSEL(CLKINSEL), // 1-bit input: Clock select, High=CLKIN1 Low=CLKIN2
      .PWRDWN(PWRDWN),     // 1-bit input: Power-down
      .RST(RST),           // 1-bit input: Reset
      // 动态重配相关的不使用,悬空即可
      .DADDR(DADDR),       // 7-bit input: DRP address
      .DCLK(DCLK),         // 1-bit input: DRP clock
      .DEN(DEN),           // 1-bit input: DRP enable
      .DI(DI),             // 16-bit input: DRP data
      .DWE(DWE),           // 1-bit input: DRP write enable
      // Feedback Clocks: 1-bit (each) input: Clock feedback ports
      .CLKFBIN(n_clkfbout)    // 1-bit input: Feedback clock
   );

 //调用PLL的IP核
  clk_wiz_0 pll_ip
  (
   // Clock in ports
  .clk_in1(CLKIN1_ip),
  .clk_in2(CLKIN2_ip),
  .clk_in_sel(CLKINSEL),
  // Clock out ports  
  .clk_out1(CLKOUT0_ip),
  .clk_out2(CLKOUT1_ip),
  .clk_out3(CLKOUT2_ip),
  .clk_out4(CLKOUT3_ip),
  // Status and control signals               
  .reset(RST), 
  .locked()

  );

endmodule

2.3 测试代码

module PLL_TB(  );
reg CLKIN1,CLKIN2,CLKIN1_ip,CLKIN2_ip,RST,CLKINSEL;
wire CLKOUT0,CLKOUT1,CLKOUT2,CLKOUT3;
wire CLKOUT0_ip,CLKOUT1_ip,CLKOUT2_ip,CLKOUT3_ip;
initial
begin
CLKIN1=0;
CLKIN2=0;
CLKIN1_ip=0;
CLKIN2_ip=0;
RST=0;
CLKINSEL=0; 
#50 RST=1;   //复位信号切换为0,为CLKINSEL切换做准备,因为RST为0时,CLKINSEL不能进行切换
#100 CLKINSEL=1;  //切换参考信号为CLKIN2
#10 RST=0;   //取消复位 
#2000 RST=1;   //复位信号切换为0,为CLKINSEL切换做准备,因为RST为0时,CLKINSEL不能进行切换
#10 CLKINSEL=0;   //参考时钟选择信号初始化为1,即选择CLKIN1为参考信号
#10 RST=0;   //取消复位 
end
always#10 CLKIN1=~CLKIN1;     //CLKIN1输入周期为20ns
always#10 CLKIN1_ip=~CLKIN1_ip;  //CLKIN1_ip输入周期为20ns
always#4 CLKIN2=~CLKIN2;        //CLKIN2输入周期为8ns
always#4 CLKIN2_ip=~CLKIN2_ip;  //CLKIN2_ip输入周期为8ns
PLL PLL_test(.CLKIN1(CLKIN1),.CLKIN2(CLKIN2),.CLKIN1_ip(CLKIN1_ip),.CLKIN2_ip(CLKIN2_ip),
.RST(RST),.CLKINSEL(CLKINSEL),.CLKOUT0(CLKOUT0),.CLKOUT1(CLKOUT1),.CLKOUT2(CLKOUT2),.CLKOUT3(CLKOUT3),
.CLKOUT0_ip(CLKOUT0_ip),.CLKOUT1_ip(CLKOUT1_ip),.CLKOUT2_ip(CLKOUT2_ip),.CLKOUT3_ip(CLKOUT3_ip));
endmodule

2.4 仿真结果

分别对比CLKOUT0-CLKOUT3与CLKOUT0_ip-CLKOUT3_ip,两种情况下4个输出端口的波形相同,符合预期

输入参考信号切换,下图中CLKOUT1-CLKOUT3在左右两侧的频率不同,即进行了输入参考信号的切换,左侧波形松散,右侧密实,即切换后参考信号频率更高

2.5 常见问题

1)使用原语例化PLL时布线失败,报错如下图,

DRC error内容详细如下

[DRC PDRC-43] PLL_adv_ClkFrequency_div_no_dclk: The computed value 300.000 MHz (CLKIN1_PERIOD, net CLKIN1_IBUF) for the VCO operating frequency of the PLLE2_ADV site PLLE2_ADV_X0Y1 (cell PLLE2_ADV_inst) falls outside the operating range of the PLL VCO frequency for this device (800.000 - 1600.000 MHz). The computed value is (CLKFBOUT_MULT_F * 1000 / (CLKINx_PERIOD * DIVCLK_DIVIDE)). Please adjust either the input period CLKINx_PERIOD (10.000000), multiplication factor CLKFBOUT_MULT_F (3) or the division factor DIVCLK_DIVIDE (1), in order to achieve a VCO frequency within the rated operating range for this device.

通过该信息知设计的VCO的为300MHZ,不在允许的【800-1600MHZ】范围内,这是由于CLKIN1和CLKFBOUT_MULT设置不合理,CLKIN1为100MHZ,CLKFBOUT_MULT为3,因此VC0为300MHZ,将CLKFBOUT_MULT值改大即可

2)进行仿真,点击运行,弹出“Finish Vsim”窗口

内容如下,即仿真文件中在复位信号RST=1时进行了参考信号的切换,更改测试文件使CLKINSEL在RST为0时进行切换

Input Error : Input clock can only be switched when RST=1. CLKINSEL on PLLE2_ADV instance PLL_TB.PLL_test.PLLE2_ADV_inst at time              2190000 changed when RST low, which should change at RST high.

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Verilog语言是一种硬件描述语言,可以用于FPGA数字锁相环PLL)实现。PLL是一种基于电路的频率合成器,可将输入信号的频率锁定到输出时钟信号的频率,实现时钟信号的同步和稳定性。 在Verilog中,PLL可以通过使用IP核来实现。IP核是可重用的硬件组件,可在设计中轻松添加和配置功能。 要使用Verilog实现PLL,您需要了解PLL的基本结构和原理,以及Verilog编程语言。您需要编写代码来初始化PLL的各个功能块(如相位检测器、环路滤波器和VCO),并编写代码来配置所需的输出时钟频率。 您可以使用仿真工具(如ModelSimVerilog Simulator)验证与设计的正确性。一旦验证完成,您可以将代码编译成比特流并将其下载到FPGA中。然后,您可以使用FPGA来实现锁相环,生成所需的时钟信号。 总体而言,使用Verilog语言实现FPGA数字锁相环PLL可以提供高度可定制和灵活的设计,同时具有良好的时钟同步和稳定性。 ### 回答2: Verilog语言的FPGA数字锁相环PLL实现,是一种利用FPGA的硬件资源实现的数字控制系统。通过使用Verilog语言编写数字锁相环的控制逻辑,并将其实现到FPGA芯片上。这种实现方式具有功耗低、可编程性强、精度高等优点。 数字锁相环是一种常见的时钟和频率控制电路,在各种数字电路中得到广泛应用。常用于时钟成形、数字信号解调和数据通信等领域。 在Verilog语言的FPGA数字锁相环PLL实现中,需要设计锁相环控制电路的各个模块,包括相锁环环路(PLL)、振荡器、分频器和反馈控制等模块。通过适当的控制和优化,可实现锁相环的频率和相位的高精度控制。 在实现过程中,需要深入了解数字锁相环的工作原理和各个模块的功能,同时要熟练掌握Verilog语言的编程技术。此外,还需要根据具体应用需求对系统进行合理的设计和优化,以保证系统的性能和稳定性。 总之,Verilog语言的FPGA数字锁相环PLL实现是一种颇具挑战性的技术,它能够为数字电路的实现和应用提供重要的支持和保障。 ### 回答3: Verilog语言是一种硬件描述语言,用于设计各种数字电路、系统和芯片。在 FPGA 中,数字锁相环PLL)是一种重要的基础电路,可以对时钟信号进行频率分频、频率加倍、相位偏移等操作,从而实现时钟信号的高精度控制和校准。本文将介绍如何用 Verilog 语言实现 FPGA 上的数字 PLL。 在 Verilog 中,数字 PLL 的实现通常需要依靠三个模块:相位比较器、数字控制振荡器和滤波器。相位比较器用于将参考时钟信号与反馈时钟信号进行比较,产生一个相位误差信号。数字控制振荡器根据相位误差信号调整自身振荡频率,从而使其输出的时钟信号与参考时钟信号保持同步。滤波器则用于平滑相位误差信号,避免产生较大的频率震荡和噪声。 具体地,可以采用如下的 Verilog 代码实现数字 PLL 的各个模块: // Phase Comparator module phase_comparator ( input reference_clock, input feedback_clock, output phase_error ); always @(posedge reference_clock or posedge feedback_clock) begin if (feedback_clock && ~reference_clock) // rising edge of feedback_clock phase_error <= phase_error + 1; else if (~feedback_clock && reference_clock) // rising edge of reference_clock phase_error <= phase_error - 1; end endmodule // Numerical Controlled Oscillator module nco ( input system_clock, input signed [15:0] phase_error, output reg signed [15:0] accumulator, output nco_clock ); reg signed [15:0] increment = 100; // initial phase increment value reg signed [15:0] offset = 0; // initial phase offset value always @(posedge system_clock) begin accumulator <= accumulator + increment + phase_error + offset; nco_clock <= $signed($greater(accumulator, 0)); end endmodule // Low-pass Filter module low_pass_filter ( input system_clock, input filter_input, output reg signed [15:0] filter_output ); reg signed [15:0] filter_gain = 100; always @(posedge system_clock) begin filter_output <= (filter_gain * filter_input + (32768 - filter_gain) * filter_output) >> 15; end endmodule 然后,将上述模块进行组合,并添加时钟频率控制、时钟输出等接口,即可构建出数字 PLL 的完整设计。实际的设计中,还需要通过仿真和调试来验证和优化设计的性能和精度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值