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
相关推荐
techdashen2 小时前
从网络栈继续往下:micro:bit、2.4GHz、调制方式,以及一个不太靠谱但很有趣的想法
网络·fpga开发
FPGA小徐2 小时前
FIR 数字滤波器 --verilog设计实现
fpga开发
zlinear数据采集卡2 小时前
从协议解析到波形实时显示:硬核拆解ZLinear采集卡上位机软件的开发架构
arm开发·单片机·嵌入式硬件·fpga开发·架构·开源
pcjiushizhu3 小时前
ModelSim 仿真时 Simulate 无反应或只显示 Loading 的解决方法:网卡问题排查
fpga开发
FPGA小迷弟6 小时前
vivado中的AXI Interconnect到底应该怎么用,他的底层原理是什么,一篇文档全部理清楚!!!
网络协议·tcp/ip·fpga开发·verilog·fpga
国科安芯15 小时前
ASC4T245S分组双向控制架构深度解析:独立DIR/OE控制、QFN16封装与混合方向总线桥接
单片机·嵌入式硬件·物联网·fpga开发·架构·risc-v
尤老师FPGA1 天前
GT系列2:GT基础架构(二)
fpga开发
想你依然心痛1 天前
电源时序控制:多路电源的上电顺序与监控——复位、看门狗
fpga开发
Eloudy1 天前
hsb fpga/ 目录分析
fpga开发·量子计算
Hello-FPGA1 天前
GPU Direct DMA RDMA 与FPGA 通讯在Jetson 平台的测试表现
fpga开发