前言:
鑒於一般ADI的AD、DA、時鍾類的芯片應用的比較廣泛,正好手上的一塊板子上有三片ADI的芯片,都是SPI的接口。就想到設計一個比較通用的SPI Master,希望可以做到基本通用。
一、SPI的接口時序如下(摘自AD9517-3 datasheet)
1、 前16bit為Instruction Header,就是控制讀/寫、地址、長度(讀/寫)的。
2、后面跟的是讀/寫的數據。
說明:sdio是雙向的,一般默認的就是雙向的,所以sdo引腳可以不用。
二、設計SPI時序
SPI的時序很簡單,就是一個時鍾對應一個數據。通常SCLK的最高頻率不超過25MHz。
對於低速的時序,我們可以在2倍或者4倍的系統下來控制輸出的時序。如下圖,clk是50MHz,輸出的SCLK是25Mhz。這是一種時序控制的思想。
上圖中,我們用到了一個計數器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總線“寫操作”時序設計出來應該是這樣子:
注:圖中是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上取數據。
未完,敬請期待。。。




