当前位置: 首页 > article >正文

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 观察现象。

代码分享

`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


http://www.kler.cn/a/450626.html

相关文章:

  • Flutter 异步编程简述
  • 单片机:实现数码管动态显示(0~99999999)74hc138驱动(附带源码)
  • go语言并发文件备份,自动比对自动重命名(逐行注释)
  • 使用TC命令模拟弱网丢包
  • 信号仿真高级工程师面试题
  • 写给Pythoner的前端进阶指南(五):事件驱动模型
  • python基础知识(六)
  • 【day15】String常用API
  • 【论文阅读笔记】Learning to sample
  • 数据结构经典算法总复习(上卷)
  • redis延迟队列
  • 云边端一体化架构
  • pyinstaller打包资源文件和ini配置文件怎么放
  • 油漆面积(2017年蓝桥杯)
  • 在瑞芯微RK3588平台上使用RKNN部署YOLOv8Pose模型的C++实战指南
  • ABP vNext框架之EntityVersion
  • 绩效考核试题
  • 技术文档的语言表达:简洁、准确与易懂的平衡艺术
  • 嵌入式科普(24)从SPI和CAN通信重新理解“全双工”
  • 智能脂肪秤方案pcba设计研发步骤解析
  • 开发场景中Java 集合的最佳选择
  • 华为浏览器(HuaweiBrowser),简约高效上网更轻松
  • uniapp Native.js原生arr插件服务发送广播到uniapp页面中
  • leetcode 面试经典 150 题:螺旋矩阵
  • Spring基础分析13-Spring Security框架
  • Python中zip