前言
本实验使用ZYNQ的PL(FPGA)对LMX2571芯片进行配置,以下连接为相关的原理和软件使用资料。
TICS Pro 配置时钟芯片
文献阅读–Σ-Δ 小数频率合成器原理
LMX2571芯片数据手册
一、LMX2571配置时序分析
1.1 写时序
LMX2571使用24位寄存器进行编程。一个24位移位寄存器用作临时寄存器,间接地对片上寄存器进行编程。移位寄存器由一个数据字段、一个地址字段和一个读写位组成。MSB是读写位。0表示写寄存器,1表示读寄存器。后面的7位,ADDR[6:0],构成地址字段,用来解码内部寄存器地址。剩下的16位组成数据字段data[15:0]。当LE为低时,串行数据在时钟上升沿上被时钟输入移位寄存器。当LE变高时,数据从数据字段传输到选定的寄存器。
1.2 读时序
读时序分为两部分写地址和读数据。先设R/W位为1,然后写入寄存器地址此时数据字段的内容将被忽略。然后从第9个时钟周期开始,将输出回读串行数据。
二、LMX2571配置
2.1 软件生成配置信息
参考该文章可以完成配置:TICS Pro 配置时钟芯片
这里就写几个注意事项:不管是什么芯片,寄存器的功能一定要了解清楚特别是一些功能设置的寄存器。
例如:LMX2571的R42是一个锁定模式寄存器,锁定模式下MUXout变为锁定指示,1为锁定频率,0为未锁定。此时读寄存器是没有用的。还有R7-R8的输出接口的选择配置等等一定要和自己的设计对上。
2.2 初始化流程
- 向器件供电,并确保Vcc引脚处于适当的电平。
- 如果CE为LOW,则拉高。
- 等待100µs,使内部ldo稳定。
- 确保对OSCin引脚应用了有效的引用。
- 程序寄存器R0复位=1。这将确保所有寄存器被重置为其默认值。
- 程序在顺序寄存器R60, R58, R53,…,R1,然后R0。
2.3 SPI时序代码
写数据
不论是读还写核心代码就是按照手册的时序输出数据,一个简单的SPI时序。以下代码片段为输出24位数据的代码,1位数据使用4个system_clk进行设置。
//开始发送数据state_sent:if( i >= 7'd1 ) begincase(clkcnt)0: //写使能beginPLL_LE<=0;PLL_SCK<=0;clkcnt<=clkcnt+1'b1;PLL_SD<=Reg2571[cnt][23];end1: //输出数据begin Reg2571[cnt]<=Reg2571[cnt]<<1;clkcnt<=clkcnt+1'b1; end2: //保持数据beginPLL_SCK<=1;clkcnt<=clkcnt+1'b1;end3: begini<=i-1'b1;clkcnt<=8'd0;enddefault: PLL_SCK<=PLL_SCK;endcaseendelse if( i == 7'd0 ) state<=state_start;
读数据
读代码也类似,只不过是先写地址再读。
//读取寄存器state_rdata:if( i >= 7'd17 ) begin //设置读取的寄存器地址case(clkcnt)0: //写使能beginPLL_LE<=0;PLL_SCK<=0;clkcnt<=clkcnt+1'b1;PLL_SD<=Reg2571adr[7];Reg2571Rdata[i-1]<= Reg2571adr[7]; end1: //输出数据begin Reg2571adr<=Reg2571adr<<1;clkcnt<=clkcnt+1'b1; end2: beginPLL_SCK<=1;clkcnt<=clkcnt+1'b1;end3: begini<=i-1'b1;clkcnt<=8'd0;enddefault: PLL_SCK<=PLL_SCK;endcaseendelse if( i >=7'd1 && i<=7'd16 ) begin //接收读出的数据case(clkcnt)0: //写使能beginPLL_SCK<=0;clkcnt<=clkcnt+1'b1;end1: clkcnt<=clkcnt+1'b1; 2: beginPLL_SCK<=1;Reg2571Rdata[i-1]<=PLL_MUXO;//读数据记录clkcnt<=clkcnt+1'b1;end3: begini<=i-1'b1;clkcnt<=8'd0;enddefault: PLL_SCK<=PLL_SCK;endcase end
2.3 芯片配置代码
整体代码就是对读写代码的使用,因为涉及到其他不可公开的信息,展示代码并且以图例说明以下配置代码。整个程序分为 state_init,state_reset,state_start,state_delay,state_sent,state_rdata–六个状态。
- state_init :初始化配置寄存器
- state_reset :R0的复位设置,复位所有寄存器
- state_start :依次配置寄存器R60–R0
- state_delay:每个寄存器配置完成后的延时
- state_sent :每个寄存器数据的发送
- state_rdata: 每个寄存器数据的接收
各状态的跳转顺序如下图,实验中使用的case语句实现不同状态的跳转
LMX5271配置主要代码
always @(posedge CLK)beginif(!RST_n)beginPLL_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;endelse begincase(state)//寄存器初始化state_init: begin//----------------------------默认寄存器配置------------------------------------Reg2571Reset<=24'h002082; //R0_resetReg2571[60]<= 24'h3CA000;//这里依次填入寄存器初始化pei'z state<= state_reset;end//复位LMX2571寄存器state_reset: beginif( i >= 7'd1 ) begincase(clkcnt)0: //写使能beginPLL_LE<=0;PLL_SCK<=0;clkcnt<=clkcnt+1'b1;PLL_SD<=Reg2571Reset[23];end1: //输出数据begin Reg2571Reset<=Reg2571Reset<<1;clkcnt<=clkcnt+1'b1; end2: beginPLL_SCK<=1;clkcnt<=clkcnt+1'b1;end3: //输出结束 begini<=i-1'b1;clkcnt<=8'd0;enddefault: PLL_SCK<=PLL_SCK;endcaseendelse if( i == 7'd0 ) begin PLL_SD<=0;PLL_SCK<=0;PLL_LE<=1;i<=7'd24;cnt<=8'd60;state<=state_delay;endend//开始配置LMX2571寄存器state_start: case(cnt)default: if( i == 7'd24 ) begin state<=state_sent;endelse 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*10state_delay: if(delay_cnt<10) delay_cnt<=delay_cnt+1'b1; else beginif(cnt==61) begin //读寄存器数据state<= state_rdata;Reg2571adr<=Regadr;end elsebegin //写寄存器数据state<=state_start;end delay_cnt<=16'd0;end //读取寄存器state_rdata:;default:beginPLL_SD<=0;PLL_LE<=1;endendcase
三、实验结果
60个寄存器依次设置
示波器观测时序