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
相关推荐
鸡精拌饭4 小时前
FPGA练习
fpga开发
可编程芯片开发10 小时前
基于FPGA的特定序列检测器verilog实现,包含testbench和开发板硬件测试
fpga开发·verilog·特定序列检测
Cynthia的梦12 小时前
FPGA——FPGA状态机实现流水灯
fpga开发
cjie22113 小时前
linux系统调试PCIe板卡常用指令
linux·fpga开发
XINVRY-FPGA15 小时前
Xilinx FPGA XCVC1902-2MSEVSVA2197 Versal AI Core系列芯片的详细介绍
人工智能·嵌入式硬件·5g·ai·fpga开发·云计算·fpga
9527华安15 小时前
FPGA实现4K MIPI视频解码H265压缩网络推流输出,基于IMX317+VCU架构,支持4K60帧,提供工程源码和技术支持
fpga开发·h265·mipi·vcu·imx317
一大Cpp16 小时前
FPGA状态机思想实现流水灯及HDLBits学习
fpga开发
北京太速科技股份有限公司2 天前
太速科技-FMC144 -八路 250MSPS 14bit AD FMC子卡
fpga开发
不可思议迷宫2 天前
Verilog编程实现一个分秒计数器
单片机·嵌入式硬件·fpga开发
Terasic友晶科技3 天前
第3篇:Linux程序访问控制FPGA端LEDR<一>
fpga开发·嵌入式系统·de1-soc开发板