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的结构如下图

Verilog基础之十七、锁相环PLL_第1张图片

    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的端口更多,功能更丰富。

Verilog基础之十七、锁相环PLL_第2张图片

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

Verilog基础之十七、锁相环PLL_第3张图片

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

Verilog基础之十七、锁相环PLL_第4张图片

二、工程设计

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

2.1 PLL IP核配置

Verilog基础之十七、锁相环PLL_第5张图片

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个输出端口的波形相同,符合预期

Verilog基础之十七、锁相环PLL_第6张图片

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

Verilog基础之十七、锁相环PLL_第7张图片

2.5 常见问题

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

Verilog基础之十七、锁相环PLL_第8张图片

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值改大即可

Verilog基础之十七、锁相环PLL_第9张图片

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

Verilog基础之十七、锁相环PLL_第10张图片

内容如下,即仿真文件中在复位信号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.

你可能感兴趣的:(Vivado,FPGA所知所见所解,Verilog学习笔记,fpga开发,锁相环,PLL,modelsim仿真)