SPI学习笔记:DAC与ACD

一、SPI协议简介

SPI = Serial Peripheral Interface,是串行外围设备接口,是一种高速,全双工,同步的通信总线。常规只占用四根线,节约了芯片管脚,PCB的布局省空间。现在越来越多的芯片集成了这种通信协议,常见的有EEPROM、FLASH、AD转换器等。

SPI学习笔记:DAC与ACD_第1张图片

SPI学习笔记:DAC与ACD_第2张图片

二、遵循SPI协议控制DAC:tlv5618

   1.时序分析

    从tlv5618芯片的数据手册中可找到其时序特性:

SPI学习笔记:DAC与ACD_第3张图片

由tw确定sclk时钟频率为20MHz;根据DIN时序可知在SCLK上升沿DIN改变,在SCLK下降沿读取DIN;tsu与thd长度之和小于tw,故直接用20MHz时钟设计DIN长度即可满足;tsu用于限制CS的起止点,在仿真时检验并调整使CS满足tsu即可。

2.模块框图

        根据时序图可知,用线性序列机即可(LSM)实现。定义的信号如下:

SPI学习笔记:DAC与ACD_第4张图片

3.代码实现

//采用线性序列机(LSM)来实现
module dac_driver(
	input fpga_clk ,
	input rst_n ,
	input dac_pulse ,
	input [15:0]dac_data ,
	
	output reg cs_n ,//low level valid
	output reg sclk ,
	output reg mosi ,
	output reg dac_sig ,
	output reg dac_done 
);


//供电电压不同,参数最小值不同,这里按照兼容VDD = 5V 和 VDD = 3V 的参数设计 
// 			tsu(cs-ck) : 20ns														// 
//				tsu(c16-cs): 20ns															//
//				th(D): 10ns																	//	
//				th(csh):50ns																//
//           sclk : 20Mhz    															//
//
// D15 - D12 : 设置位  根据手册来设置                                     //
// D11 - D0  : 数据位	  需要转化的电压值												//



wire clk_40m ;
pll pll_inst(
	.inclk0(fpga_clk),
	.c0(clk_40m)
	);

//detect dac_pulse
reg dac_pulse_reg ;
always@(posedge fpga_clk or negedge rst_n)
if(!rst_n)
	dac_pulse_reg <= 0 ;
else 
	dac_pulse_reg <= dac_pulse ;

//dac_sig 
always@(posedge fpga_clk or negedge rst_n)
if(!rst_n)	
	dac_sig <= 0 ;
else if( (dac_pulse_reg == 0) & ( dac_pulse == 1) )
	dac_sig <= 1 ;
else if( dac_done )
	dac_sig <= 0 ;

// dac_cnt : 0 - 15
reg [5:0]dac_cnt ;
always@(posedge clk_40m or negedge rst_n)
if(!rst_n)	
	begin
		dac_cnt <= 0 ;
	end
else if(dac_sig)
	begin
		dac_cnt <= dac_cnt + 1 ;	
		if(dac_cnt == 34 )
			dac_cnt <= 0 ;
	end
else
	dac_cnt <= 0 ;
	
//dac_done:
always@(posedge clk_40m or negedge rst_n)
if(!rst_n)	
	dac_done <= 0 ;
else if( dac_cnt == 34 )
	dac_done <= 1 ;
else if( dac_done )
	dac_done <= 0 ;
	
// cs_n
always@(posedge clk_40m or negedge rst_n)
if(!rst_n)	
	cs_n <= 1 ;
else if(dac_sig)
	begin
		if(dac_cnt < 32 )
			cs_n <= 0 ;
		else
			cs_n <= 1 ;
	end
	
// sclk
always@(posedge clk_40m or negedge rst_n)
if(!rst_n)	
	sclk <= 0 ;
else if(dac_sig)
	begin
		sclk <= !sclk ; 
	end
else 
	sclk <= 0 ;

//mosi
always@(posedge clk_40m or negedge rst_n)
if(!rst_n)	
	mosi <= 0 ;
else if(dac_sig)
	begin
		case(dac_cnt)
			0 :  mosi <= dac_data[15] ;
			2 :  mosi <= dac_data[14] ;
			4 :  mosi <= dac_data[13] ;
			6 :  mosi <= dac_data[12] ;
			8 :  mosi <= dac_data[11] ;
			10 : mosi <= dac_data[10] ;
			12 : mosi <= dac_data[9] ;
			14 : mosi <= dac_data[8] ;
			16 : mosi <= dac_data[7] ;
			18 : mosi <= dac_data[6] ;
			20 : mosi <= dac_data[5] ;
			22 : mosi <= dac_data[4] ;
			24 : mosi <= dac_data[3] ;
			26 : mosi <= dac_data[2] ;
			28 : mosi <= dac_data[1] ;	
			30 : mosi <= dac_data[0] ;	
			32 : mosi <= 0 ;	
			default:;
		endcase
	end
else 
	mosi <= 0 ;
	
endmodule
`timescale 1ns/1ns
module dac_driver_tb();

reg fpga_clk ;
reg rst_n  ;
reg dac_pulse ;
reg [15:0]dac_data ;
wire cs_n ;
wire sclk ;
wire mosi ;
wire dac_done ;

dac_driver dac_driver_inst(
	.fpga_clk(fpga_clk) ,
	.rst_n(rst_n) ,
	.dac_pulse(dac_pulse) ,
	.dac_data(dac_data) ,
	
	.cs_n(cs_n) ,//low level valid
	.sclk(sclk) ,
	.mosi(mosi) ,
	.dac_done(dac_done)
);

initial fpga_clk = 0 ;
always #10 fpga_clk = ! fpga_clk ;

initial
begin
	rst_n = 0 ;
	dac_pulse = 0 ;
	dac_data = 0 ;
	#100 ;
	rst_n = 1 ;
	#100 ;
	dac_data = 16'h5a5a ;
	#100 ;
	dac_pulse = 1 ;
	#40 ;
	dac_pulse = 0 ;
	#100;
	wait(dac_done);
	#3000 ;
	dac_data = 16'ha5a5 ;
	#100 ;
	dac_pulse = 1 ;
	#40 ;
	dac_pulse = 0 ;
	#100;
	wait(dac_done);
	#3000 ;
	$stop;
	
end

endmodule

4.仿真验证

SPI学习笔记:DAC与ACD_第5张图片由图可知,tsu为25ns,th(csh)为50ns,满足要求。

你可能感兴趣的:(学习,笔记)