用过ADI的DDS AD9951的同学应该都知道,AD9951在官网是没有Verilog的参考设计,而Datasheet读起来又是云里雾里。
在此,将AD9951的开发心得分享出来,与大家共同参考。
tips: 该设计已经可以正常运行,并能通过修改频率字(FTW)来修改DDS的输出频率。
设计背景:DDS的晶振时钟频率,25MHz。希望得到的输出频率为:32.768MHz。椭圆滤波器的截止频率:60MHz(硬件设计)。
根据设计背景,先将AD9951的内部时钟提高到200MHz,再通过频率字等调节使得输出为32.768MHz。
AD9951有多个寄存器,通过SPI配置寄存器,才能使其正常工作。但是奇葩的是,AD9951的寄存器并非是相同的长度,这也就使得在配置时带来不便甚至很难。
1、解释下各个寄存器:
(1)CFR1(控制功能寄存器):控制AD9951的功能、特性以及模式。寄存器地址:0x00,长度32bits;
(2)CFR2(控制功能寄存器):控制AD9951的功能、特性以及模式。寄存器地址:0x01,长度24bits;
(3)ASF(幅值因子):控制输出幅值。寄存器地址:0x02,长度16bits;
(4)ARR(振幅斜率):在自动OSK模式下,该寄存器为8bit的振幅斜率。寄存器地址:0x03,长度8bits;
(5)FTW0(频率字):控制DDS的输出频率。寄存器地址:0x04,长度32bits;
(6)POW(相位偏移字):控制相位偏移。寄存器地址:0x05,长度16bits;
2、操作步骤:
(1)上电配置DDS的寄存器;
(2)当FTW有更改时,对其再配置;
3、附上代码:
由于工作保密原因,已删除部分与硬件相关的代码。但是整体配置代码未改。
如有问题,欢迎讨论。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2019/12/02 14:29:50
// Design Name:
// Module Name: DDS_SPI
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// DDS output fre = (FTW)(fs)/(2^32) 0 <= FTW <= 2^31
// fre = fs*(1-(FTW/2^32)) 2^31 <= FTW <= 2^32-1
// system clock: datasheet P12
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module DDS_SPI(
input clk,
input rst,
//DDS configuration
input DDS_SPI_MISO,
input DDS_SYNCCLK,
output reg DDS_SPI_CSn,
output reg DDS_SPI_SCLK,
output reg DDS_SPI_MOSI,
output DDS_CLKMODESEL,
output DDS_PWRDWN,
output reg DDS_RSTn,
output DDS_IOSYNC,
output DDS_OSK,
output DDS_UPDATE,
input [31:0] DDS_SetCLK,
);
//define the data width that transfer
localparam datawidth_8b = 6'd8,
datawidth_16b = 6'd16,
datawidth_24b = 6'd24,
datawidth_32b = 6'd32;
//data type
localparam CFR1 = 8'h00,
CFR2 = 8'h01,
ASF = 8'h02,
ARR = 8'h03,
FTW0 = 8'h04,
POW0 = 8'h05,
Wait = 8'h06,
Ready = 8'h07,
w_delay = 8'h08,
reset = 8'h09;
//state mechine
localparam idle = 4'h0,
start = 4'h1,
next = 4'h2,
stop = 4'h3,
waits = 4'h4;
//read data or write data
localparam write_ins = 8'h7F, //and with register to determine write data
read_ins = 8'h80; //or with register to determine read data
//detect the back clock threshold
localparam detectclk_thres = 3'd7;
reg SPI_WEn; //