手册学习:
一、接口部分:
Vdd:电源输入,2.7 V至5.5 V; Vref:参考电压输入; VoutA/VoutB:DAC A/B 的模拟输出电压; SYNC:输入数据的帧同步信号输入,低电平有效,当 SYNC 处于低电平,它使能输入移位寄存器,数据在 SCLK 的下降沿传输; SCLK: 串行时钟输入,数据可以以高达 30 MHz 的速率在 5 V 下传输;
VDD 在 3.6 V ~ 5.5 V 时,SCLK最大30M; VDD 在 2.7 V ~ 3.6 V 时,SCLK最大20M;
DIN :串行数据输入,数据在串行时钟输入的下降沿被计时到 24 位输入移位寄存器; GND:
二、 时序要求
三、设备功能模式
DAC8532 的输入移位寄存器为 24 位宽(见图),由 8 个控制位,(DB16–DB23) 和 16 个数据位 (DB0–DB15) 组成。前两个控制位(DB22 和 DB23)是保留的,必须为 0 才能正常运行。 LD A (DB20) 和 LD B (DB21) 控制每个模拟输出的更新指定的 16 位数据值或掉电命令。位 DB19 是无关位,不影响DAC8532 的操作,可以是 1 或 0。下面的控制位,缓冲器选择 (DB18),控制DAC A 和 DAC B 之间数据(或掉电命令)的目的地。最后两个控制位,PD0(DB16) 和 PD1 (DB17),选择一个或两个 DAC 通道的掉电模式。四种模式是正常模式或三种掉电模式中的任何一种。更完整的操作模式描述DAC8532 可在“掉电模式”部分找到。 24 位输入的其余 16 位字组成数据位。这些被传送到指定的数据缓冲器或 DAC 寄存器,具体取决于控制字节发出的命令,在 SCLK 的第 24 个下降沿。 一般就用正常模式
四、操作举例
本驱动用到的是例1:DACA 和 DACB 模拟输出在第二次完成后同时稳定到指定值的写顺序(在该寄存器转换发生和模拟输出更新的同时,Load 命令将数字数据从数据缓冲器移动到 DAC 寄存器。在SYNC LOW 后的第 24 个SCLK下降沿完成)
五、程序
底层 dac8532_drive.v
module dac8532_drive(
input wire sys_clk,
input wire sys_rst,
input wire [15:0] data_dout,
input wire start,
output reg done,
output wire P_SCLK,
output reg P_SYNC,
output reg P_DIN
);
reg div_clk;
reg sclk_en;
reg [7:0] DAC_ctrl_state;
reg [7:0] SPI_cnt;
reg [7:0] div10_cnt;
reg [23:0] DAC_buf_A;
reg [23:0] DAC_buf_B;
assign P_SCLK = sclk_en ? sys_clk : 1'b0 ;
always@(posedge sys_clk or negedge sys_rst)
begin
if(sys_rst == 1'b0)
DAC_ctrl_state <= 8'd0;
else
begin
case (DAC_ctrl_state)
8'd0:
begin
if(start == 1'b0)
DAC_ctrl_state <= 8'd0;
else
DAC_ctrl_state <= 8'd1;
end
8'd1:
begin
if(SPI_cnt < 8'd24)
DAC_ctrl_state <= 8'd1;
else
DAC_ctrl_state <= 8'd2;
end
8'd2:
DAC_ctrl_state <= 8'd3;
8'd3:
begin
if(SPI_cnt < 8'd24)
DAC_ctrl_state <= 8'd3;
else
DAC_ctrl_state <= 8'd0;
end
default:
DAC_ctrl_state <= 8'd0;
endcase
end
end
always@(posedge sys_clk or negedge sys_rst)
begin
if(sys_rst == 1'b0)
begin
sclk_en <= 1'b0;
P_SYNC <= 1'b1;
P_DIN <= 1'b0;
done <= 1'b0;
SPI_cnt <= 8'd0;
DAC_ctrl_state <= 8'd0;
DAC_buf_A[23:0] <= 24'h0;
DAC_buf_B[23:0] <= 24'h0;
end
else
begin
case(DAC_ctrl_state)
8'd0:
begin
done <= 1'b0;
DAC_buf_A[23:0] <= {8'b00000000, data_dout};
DAC_buf_B[23:0] <= {8'b00110100, data_dout};
end
8'd1:
begin
P_SYNC <= 1'b0;
sclk_en <= 1'b1;
if(SPI_cnt < 8'd24)
begin
P_DIN <= DAC_buf_A[23];
DAC_buf_A[23:1] <= DAC_buf_A[22:0];
DAC_buf_A[0] <= 1'b0;
SPI_cnt <= SPI_cnt + 8'd1;
end
else
begin
sclk_en <= 1'b0;
P_SYNC <= 1'b1;
SPI_cnt <= 8'd0;
end
end
8'd3:
begin
P_SYNC <= 1'b0;
sclk_en <= 1'b1;
if(SPI_cnt < 8'd24)
begin
P_DIN <= DAC_buf_B[23];
DAC_buf_B[23:1] <= DAC_buf_B[22:0];
DAC_buf_B[0] <= 1'b0;
SPI_cnt <= SPI_cnt + 8'd1;
end
else
begin
sclk_en <= 1'b0;
SPI_cnt <= 8'd0;
P_SYNC <= 1'b1;
done <= 1'b1;
end
end
default:
P_SYNC <= P_SYNC;
endcase
end
end
endmodule
顶层 dac8532_demo.v
module dac8532_demo(
input wire sys_clk,
input wire sys_rst,
output wire DAC_SCLK,
output wire DAC_SYNC,
output wire DAC_DIN
);
reg [15:0] DAC_data;
wire DAC_done;
reg DAC_start;
reg [23:0] cnt;
always @(posedge sys_clk or negedge sys_rst)
begin
if(sys_rst == 1'b0)
begin
DAC_data <= 16'hFFFF;
DAC_start <= 1'b0;
cnt <= 24'd0;
end
else
begin
if(cnt < 24'd10_0000)
begin
cnt <= cnt + 24'd1;
DAC_start <= 1'b0;
end
else
begin
cnt <= 24'd0;
DAC_start <= 1'b1;
end
end
end
dac8532_drive dac8532_drive_1(
.sys_clk (sys_clk),
.sys_rst (sys_rst),
.data_dout (DAC_data),
.start (DAC_start),
.done (DAC_done),
.P_SCLK (DAC_SCLK),
.P_SYNC (DAC_SYNC),
.P_DIN (DAC_DIN)
);
endmodule
仿真 tb_sim1.v
`timescale 1ns / 1ps
module tb_sim1;
reg clk;
reg rst;
parameter SYSCLK_PERIOD = 100;
initial begin
clk = 0;
rst = 0;
end
initial
begin
#(SYSCLK_PERIOD * 10 )
rst = 1'b1;
end
always #(SYSCLK_PERIOD / 2.0) clk = ~clk;
wire DAC_SCLK;
wire DAC_SYNC;
wire DAC_DIN ;
dac8532_demo dac8532_demo_1(
.sys_clk (clk),
.sys_rst (rst),
.DAC_SCLK (DAC_SCLK ),
.DAC_SYNC (DAC_SYNC ),
.DAC_DIN (DAC_DIN )
);
endmodule
vivado前仿真:
|