ADI芯片的通用SPI接口设计

前言:

鉴于一般ADI的AD、DA、时钟类的芯片应用的比较广泛,正好手上的一块板子上有三片ADI的芯片,都是SPI的接口。就想到设计一个比较通用的SPI Master,希望可以做到基本通用。

一、SPI的接口时序如下(摘自AD9517-3 datasheet)

clip_image002

1、 前16bit为Instruction Header,就是控制读/写、地址、长度(读/写)的。

2、后面跟的是读/写的数据。

说明:sdio是双向的,一般默认的就是双向的,所以sdo引脚可以不用。

二、设计SPI时序

clip_image004

SPI的时序很简单,就是一个时钟对应一个数据。通常SCLK的最高频率不超过25MHz。

对于低速的时序,我们可以在2倍或者4倍的系统下来控制输出的时序。如下图,clk是50MHz,输出的SCLK是25Mhz。这是一种时序控制的思想。

clip_image006

上图中,我们用到了一个计数器cnt,然后按照cnt的值来控制SCLK和高和低,以及SDIO上的数据。

部分verilog代码如下:

Case(cnt)

0: begin sclk <= 1; csb <= 0; cnt <= cnt + 1'b1; end(将csb信号拉低,对应图中cnt=1)

1: begin sclk <= 0; sdio <= instr_header[15]; cnt <= cnt + 1'b1; end(低电平送数据,保持一个周期,对应图中cnt=2,3)

2: begin sclk <= 1; sdio <= instr_header[15]; cnt <= cnt + 1'b1; end

3: begin sclk <= 0; sdio <= instr_header[14]; cnt <= cnt + 1'b1; end

4: begin sclk <= 1; sdio <= instr_header[14]; cnt <= cnt + 1'b1; end

5: begin sclk <= 0; sdio <= instr_header[13]; cnt <= cnt + 1'b1; end

6: begin sclk <= 1; sdio <= instr_header[13]; cnt <= cnt + 1'b1; end

7: begin sclk <= 0; sdio <= instr_header[12]; cnt <= cnt + 1'b1; end

8: begin sclk <= 1; sdio <= instr_header[12]; cnt <= cnt + 1'b1; end

……..

这样,一个完整的SPI总线“写操作”时序设计出来应该是这样子:

clip_image008

注:图中是8位的地址+8位的数据,所以SCLK共16个周期。如果是16位地址,应该共24个周期。

三、双向IO的控制

由于默认SDIO是双向的,所以这里再提一下双向IO的控制。

一般双向IO是这样定义的,先在模块中如下申明:

module spi_master(

inout sdio,

);

然后在程序中:

reg sdio_en = 0;

wire sdi;

reg sdo = 0;

assign sdio = (sdio_en) ? sdo : 1'bZ;

assign sdi = sdio;

sdio_en是使能双向端口的,sdio_en为1时输出,为0时输入。

sdo作为输出寄存器,sdi作为输入。

在程序中要输出的时候,要先把sdio­_en置为1,同时将数据放入sdo寄存器。输入的时候,先将sdio_en置0,再从sdi上取数据。

未完,敬请期待。。。

原文地址:https://www.cnblogs.com/craftor/p/2695187.html