Xilinx 平台 drp 动态调节 mmcm

分享个人觉得有意思的知识:

  1. 什么样的时钟 会输入到 锁相环里

  2. 锁相环框图 VCO 控制电压控制频率 DS182 可以查看 VCO 范围

    a. 先生成高频 的 VCO

    b. 再通过 倍频和分频 产生具体各路时钟

    c.

  3. 怎么控制 输出频率?XAPP888

    a. high time 是VCO 高电平 持续周期

    b. low time 是 VCO 低电平持续周期

    c. no count 是 VCO时钟周期的计数

    d. edge 将high time 再扩展半个vco 周期 ,可以用来奇数分频 变成 50%占空比

    e. high time 和 low time的 和 是 分频值

  4. 控制相位

    b. 八个可变调节 以 45°为步长

    c. 如果需要 20°就需要使用delay time

    d. vco 频率越高,分频系数越高,相位越精细,如果是 10分频那么VCO输出一周期就是便宜360/10 = 36°

  5. 小数分频

  6. 时序图:

  1. 代码:
    此代码 配置 其中的一个时钟输出,首先读出对于寄存器,然后设置,再读出对比寄存器值,观察是否设置成功,可以使用 LED 观察现象。

代码分享

c 复制代码
`timescale 1ns / 1ps
module drp(
    input               i_clk           ,
    input               i_rst           ,

    output [6 :0]       o_daddr         ,   
    output              o_dclk          ,   
    output              o_den           ,     
    output [15:0]       o_din           ,
    output              o_dwe           ,     
    input  [15:0]       i_dout          ,  
    input               i_drdy          ,
    output              o_mmcm_rst      
          
);

localparam              P_CLKOUT0_REG1_ADDR = 16'h08    ;
localparam [5 :0]       P_HIGN_TIME         = 6'd10     ;
localparam [5 :0]       P_LOW_TIME          = 6'd10     ;

localparam              P_ST_IDLE     = 0   ,
                        P_ST_RST      = 1   ,
                        P_ST_RREG     = 2   ,
                        P_ST_WRDY     = 3   ,
                        P_ST_SET      = 4   ,
                        P_ST_WAIT_RDY = 5   ,
                        P_ST_2RREG    = 6   ,
                        P_ST_2WRDY    = 7   ,
                        P_ST_END      = 8   ;

reg  [7 :0]             r_st_current    ;
reg  [7 :0]             r_st_next       ;
reg  [15:0]             r_st_cnt        ;

reg  [6 :0]             ro_daddr        ;
reg                     ro_dclk         ;
reg                     ro_den          ;
reg  [15:0]             ro_din          ;
reg                     ro_dwe          ;
reg                     ro_mmcm_rst     ;
(* MARK_DEBUG = "TRUE" *)reg  [15:0]             r_clkout0_reg1  ;
(* MARK_DEBUG = "TRUE" *)reg  [15:0]             r_clkout0_2reg1 ;
reg  [1 :0]             r_rdy           ;

assign o_daddr      = ro_daddr          ;
assign o_dclk       = ro_dclk           ;
assign o_den        = ro_den            ;
assign o_din        = ro_din            ;
assign o_dwe        = ro_dwe            ;
assign o_mmcm_rst   = ro_mmcm_rst       ;


always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_st_current <= P_ST_IDLE;
    else 
        r_st_current <= r_st_next;
end

always@(*)
begin
    case(r_st_current)
        P_ST_IDLE       : r_st_next = r_st_cnt == 20000 ? P_ST_RST  : P_ST_IDLE ;
        P_ST_RST        : r_st_next = r_st_cnt == 20    ? P_ST_RREG : P_ST_RST  ;
        P_ST_RREG       : r_st_next = P_ST_WRDY;
        P_ST_WRDY       : r_st_next = r_rdy[1]          ? P_ST_SET  : P_ST_WRDY ;
        P_ST_SET        : r_st_next = P_ST_WAIT_RDY;
        P_ST_WAIT_RDY   : r_st_next = r_rdy[1]          ? P_ST_2RREG  : P_ST_WAIT_RDY;
        P_ST_2RREG      : r_st_next = P_ST_2WRDY;
        P_ST_2WRDY      : r_st_next = r_rdy[1]          ? P_ST_END    : P_ST_2WRDY;
        P_ST_END        : r_st_next = P_ST_END;
        default         : r_st_next = P_ST_IDLE;
    endcase
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_st_cnt <= 'd0;
    else if(r_st_current != r_st_next)
        r_st_cnt <= 'd0;
    else 
        r_st_cnt <= r_st_cnt + 1;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        ro_mmcm_rst <= 'd0;
    else if(r_st_current == P_ST_END)
        ro_mmcm_rst <= 'd0;
    else if(r_st_current == P_ST_RST)
        ro_mmcm_rst <= 'd1;
    else 
        ro_mmcm_rst <= ro_mmcm_rst;
end

  
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst) begin
        ro_daddr <= 'd0;
        ro_den   <= 'd0;
        ro_din   <= 'd0;
        ro_dwe   <= 'd0;
    end else if(r_st_current == P_ST_RREG || r_st_current == P_ST_2RREG) begin 
        ro_daddr <= P_CLKOUT0_REG1_ADDR;
        ro_den   <= 'd1;
        ro_din   <= 'd0;
        ro_dwe   <= 'd0;
    end else if(r_st_current == P_ST_SET) begin 
        ro_daddr <= P_CLKOUT0_REG1_ADDR;
        ro_den   <= 'd1;
        ro_din   <= (r_clkout0_reg1 | 16'b0000_1111_1111_1111) & {4'b1111,P_HIGN_TIME,P_LOW_TIME};
        ro_dwe   <= 'd1;
    end else begin
        ro_daddr <= 'd0;
        ro_den   <= 'd0;
        ro_din   <= 'd0;
        ro_dwe   <= 'd0;
    end
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_rdy <= 'd0;
    else 
        r_rdy <= {r_rdy[0],i_drdy};
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_clkout0_reg1 <= 'd0;
    else if(r_st_current == P_ST_WRDY && i_drdy)
        r_clkout0_reg1 <= i_dout;
    else 
        r_clkout0_reg1 <= r_clkout0_reg1;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_clkout0_2reg1 <= 'd0;
    else if(r_st_current == P_ST_2WRDY && i_drdy)
        r_clkout0_2reg1 <= i_dout;
    else 
        r_clkout0_2reg1 <= r_clkout0_2reg1;
end
endmodule
相关推荐
Hello-FPGA9 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安10 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha601611 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld11 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家1 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家1 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
FPGA小迷弟2 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1282 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light2 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072193 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理