LMX2571 芯片配置Verliog SPI驱动

前言

本实验使用ZYNQ的PL(FPGA)对LMX2571芯片进行配置,以下连接为相关的原理和软件使用资料。
TICS Pro 配置时钟芯片
文献阅读--Σ-Δ 小数频率合成器原理
LMX2571芯片数据手册

一、LMX2571配置时序分析

1.1 写时序

  LMX2571使用24位寄存器进行编程。一个24位移位寄存器用作临时寄存器,间接地对片上寄存器进行编程。移位寄存器由一个数据字段、一个地址字段和一个读写位组成。MSB是读写位。0表示写寄存器,1表示读寄存器。后面的7位,ADDR6:0,构成地址字段,用来解码内部寄存器地址。剩下的16位组成数据字段data15:0。当LE为低时,串行数据在时钟上升沿上被时钟输入移位寄存器。当LE变高时,数据从数据字段传输到选定的寄存器。

1.2 读时序

  读时序分为两部分写地址和读数据。先设R/W位为1 ,然后写入寄存器地址此时数据字段的内容将被忽略。然后从第9个时钟周期开始,将输出回读串行数据 。

二、LMX2571配置

2.1 软件生成配置信息

参考该文章可以完成配置:TICS Pro 配置时钟芯片
这里就写几个注意事项 :不管是什么芯片,寄存器的功能一定要了解清楚特别是一些功能设置的寄存器。

例如:LMX2571的R42是一个锁定模式寄存器,锁定模式下MUXout变为锁定指示,1为锁定频率,0为未锁定。此时读寄存器是没有用的。还有R7-R8的输出接口的选择配置等等一定要和自己的设计对上。

2.2 初始化流程

  1. 向器件供电,并确保Vcc引脚处于适当的电平。
  2. 如果CE为LOW,则拉高。
  3. 等待100µs,使内部ldo稳定。
  4. 确保对OSCin引脚应用了有效的引用。
  5. 程序寄存器R0复位=1。这将确保所有寄存器被重置为其默认值。
  6. 程序在顺序寄存器R60, R58, R53,...,R1,然后R0。

2.3 SPI时序代码

写数据

  不论是读还写核心代码就是按照手册的时序输出数据,一个简单的SPI时序。以下代码片段为输出24位数据的代码,1位数据使用4个system_clk进行设置。

c 复制代码
//开始发送数据
      state_sent:
         if( i >= 7'd1 ) begin
             case(clkcnt)
                 0: //写使能
                    begin
                       PLL_LE<=0;
                       PLL_SCK<=0;
                       clkcnt<=clkcnt+1'b1;
                       PLL_SD<=Reg2571[cnt][23];
                    end
                  1: //输出数据
                    begin                                     
                       Reg2571[cnt]<=Reg2571[cnt]<<1;
                       clkcnt<=clkcnt+1'b1;                                      
                    end
                  2: //保持数据
                    begin
                       PLL_SCK<=1;
                       clkcnt<=clkcnt+1'b1;
                    end
                  3:  
                  	begin
                       i<=i-1'b1;
                       clkcnt<=8'd0;
                    end
                  default: 
                    PLL_SCK<=PLL_SCK;
              endcase
        	end
        else if( i == 7'd0 ) state<=state_start;

读数据

  读代码也类似,只不过是先写地址再读。

c 复制代码
         //读取寄存器
                state_rdata:
                   if( i >= 7'd17 ) begin  //设置读取的寄存器地址
                       case(clkcnt)
                          0: //写使能
                             begin
                                PLL_LE<=0;
                                PLL_SCK<=0;
                                clkcnt<=clkcnt+1'b1;
                                PLL_SD<=Reg2571adr[7];
                                Reg2571Rdata[i-1]<= Reg2571adr[7]; 
                            end
                          1: //输出数据
                             begin                              
                                Reg2571adr<=Reg2571adr<<1;
                                clkcnt<=clkcnt+1'b1;                                      
                             end
                          2:  
                              begin
                                PLL_SCK<=1;
                                clkcnt<=clkcnt+1'b1;
                              end
                          3:  begin
                              i<=i-1'b1;
                              clkcnt<=8'd0;
                              end
                          default: PLL_SCK<=PLL_SCK;
                      endcase
                   end
                   else if( i >=7'd1 && i<=7'd16 ) begin //接收读出的数据
                       case(clkcnt)
                           0: //写使能
                             begin
                                PLL_SCK<=0;
                                clkcnt<=clkcnt+1'b1;
                            end
                          1:  clkcnt<=clkcnt+1'b1;                               
                          2:  
                              begin
                                PLL_SCK<=1;
                                Reg2571Rdata[i-1]<=PLL_MUXO;//读数据记录
                                clkcnt<=clkcnt+1'b1;
                              end
                          3:  
                              begin
                                i<=i-1'b1;
                                clkcnt<=8'd0;
                              end
                          default: PLL_SCK<=PLL_SCK;
                       endcase   
                  end 

2.3 芯片配置代码

  整体代码就是对读写代码的使用,因为涉及到其他不可公开的信息,展示代码并且以图例说明以下配置代码。整个程序分为 state_init,state_reset,state_start,state_delay,state_sent,state_rdata--六个状态。

  1. state_init :初始化配置寄存器
  2. state_reset :R0的复位设置,复位所有寄存器
  3. state_start :依次配置寄存器R60--R0
  4. state_delay:每个寄存器配置完成后的延时
  5. state_sent :每个寄存器数据的发送
  6. state_rdata: 每个寄存器数据的接收

各状态的跳转顺序如下图 ,实验中使用的case语句实现不同状态的跳转

LMX5271配置主要代码

c 复制代码
 always @(posedge CLK)begin
        if(!RST_n)
        begin
            PLL_SD<=0;
            PLL_LE<=1;
            PLL_SCK<=0;
            i<=7'd24;
            cnt<=8'd60;//寄存器计数
            delay_cnt<=16'd0;
            Reg2571Rdata<=24'd0;
            Reg2571Rdataout<=24'd0;
            Reg2571adr<=8'd0;
            state<=state_init;
            clkcnt<=8'd0;
        end
        else begin
            case(state)
                //寄存器初始化
                state_init: 
                    begin
                        //----------------------------默认寄存器配置------------------------------------
                        Reg2571Reset<=24'h002082; //R0_reset
                        Reg2571[60]<= 24'h3CA000;
                        //这里依次填入寄存器初始化pei'z 	
                        state<= state_reset;
                     end
                //复位LMX2571寄存器
                state_reset: 
                    begin
                        if( i >= 7'd1 ) begin
                            case(clkcnt)
                                0: //写使能
                                   begin
                                      PLL_LE<=0;
                                      PLL_SCK<=0;
                                      clkcnt<=clkcnt+1'b1;
                                      PLL_SD<=Reg2571Reset[23];
                                  end
                                1: //输出数据
                                   begin                                     
                                      Reg2571Reset<=Reg2571Reset<<1;
                                      clkcnt<=clkcnt+1'b1;                                      
                                   end
                                2: 
                                    begin
                                      PLL_SCK<=1;
                                      clkcnt<=clkcnt+1'b1;
                                    end
                                3: //输出结束 
                                   begin
                                      i<=i-1'b1;
                                      clkcnt<=8'd0;
                                    end
                                default: PLL_SCK<=PLL_SCK;
                            endcase
                        end
                        else if( i == 7'd0 ) begin 
                            PLL_SD<=0;
                            PLL_SCK<=0;
                            PLL_LE<=1;
                            i<=7'd24;
                            cnt<=8'd60;
                            state<=state_delay;
                        end
                    end
                 //开始配置LMX2571寄存器
                state_start: 
                    case(cnt)
                       default: 
                            if( i == 7'd24 ) begin  
                               state<=state_sent;
                            end
                            else if( i == 7'd0 ) begin  //切换寄存器
                                PLL_SD<=0;
                                PLL_LE<=1;
                                PLL_SCK<=0;
                                i<=7'd24;
                                if(cnt==0) cnt=61; //切换至读寄存器,锁定模式下读不出
                                else cnt<=cnt-1'b1; 
                                state<=state_delay;
                           end 
                        //代码和default类似注意跳转即可
                        39,40,41,42:;
                        46,47:;
                        53,58:;
                        60:;  
                    endcase
                //开始发送数据
                state_sent:;
                //写入后的延时clk*10
                state_delay: 
                    if(delay_cnt<10) delay_cnt<=delay_cnt+1'b1; 
                    else begin
                       if(cnt==61) 
                            begin //读寄存器数据
                                    state<= state_rdata;
                                    Reg2571adr<=Regadr;
                            end  
                       else
                            begin  //写寄存器数据
                                   state<=state_start;
                            end  
                       delay_cnt<=16'd0;
                    end          
                //读取寄存器
                state_rdata:;
               default:begin
                    PLL_SD<=0;
                    PLL_LE<=1;
               end
            endcase

三、实验结果

60个寄存器依次设置

示波器观测时序

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