第7講 SPI和RAM IP核


學習目的:

(1) 熟悉SPI接口和它的讀寫時序;

(2) 復習Verilog仿真語句中的$readmemb命令和$display命令;

(3) 掌握SPI接口寫時序操作的硬件語言描述流程(本例僅以寫時序為例),為以后描述更復雜的時序邏輯電路奠定基礎。

學習過程:

SPI的相關知識】

① SPI的速度比串口的快,采用源同步傳輸的方式,且為串行傳輸,應用場景不同則時序和接口名稱會有不同;

② 串行flash的讀寫擦除命令可通過SPI接口進行通信,CPU芯片與FPGA可通過SPI接口進行通信,某些芯片的參數寄存器也可通過SPI的方式配置;

③ SPI接口說明

clip_image002

圖1 SPI接口

SCLK:主機給從機的系統時鍾信號;

SDI:主機輸出給從機的數據信號;

SDO:從機輸出給主機的數據信號;

CS:片選信號(此處為高電平有效);

SDIO(三線模式):主機與從機之間的雙向數據總線。

DAC3283芯片與SPI有關內容】

DAC3283芯片的寄存器映射如圖1所示:

image

圖1 DAC3283芯片的寄存器映射圖

從圖1可知,此DAC芯片共有32個寄存器需要配置(CONFIG0~CONFIG31),且每個寄存器均為8bit。

【關於這些寄存器的配置方法】對於寄存器數量少的情況,可以直接定義幾個reg型變量,然后用這些reg變量初始化那些待配置的寄存器;而對於像本例這樣有如此多的寄存器需要配置,則需通過FPGA的ROM或RAM完成寄存器的初始化,即:先將配置參數寫到FPGA的ROM或者RAM中,然后再通過FPGA把這些參數從ROM或者RAM中讀出並寫入到外部芯片的寄存器中去。在本例中,是通過SPI接口寫入到DAC3283芯片的。

DAC3283芯片的SPI接口時序】

image

圖2 SPI的寫時序圖

image

圖3 SPI的讀時序圖

首先,對圖2、圖3中的幾個信號名稱作介紹。SCLK是由FPGA送給DAC芯片的時鍾信號;SDENB是串行接口的使能信號(相當於片選信號),只有當它為低電平時,SPI的讀寫才有效;對於“三線模式”的SPI,SDIO是一個雙向的數據線,負責數據的讀寫數據傳輸;對於“四線模式”的SPI,SDIO也是一個雙向的數據線,但ALARM_SDO是一個只讀數據線,僅負責DAC芯片輸出數據的傳輸。數據在SCLK的上升沿時刻寫入DAC芯片,在SCLK的下降沿時刻從DAC芯片中讀出。

然后,介紹一下SPI每次傳輸的數據內容。本例中,SPI采用的是先傳高位后傳低位的串行傳輸方式,每次傳輸16bit,其中,前8bit構成SPI的指令周期,后8bit構成SPI的數據周期。在前8bit中,rwb(R/W)是讀/寫控制信號,即:若rwb為高電平時,此條指令為讀指令;若rwb為低電平時,此條指令為寫指令。N1、N0指明每幀傳輸的數據字節數(范圍為1~4字節,不包含前面的那個指令字節),A3…A0是DAC芯片各寄存器的地址。

SPI接口的狀態機】

 
   

image

圖4 DAC芯片寄存器初始化操作狀態機(概念模型)

IDLE是起始狀態(默認態),work_en是從外部輸入的啟動使能信號(高電平有效);WAIT是等待狀態,在本例中,等待8個時鍾周期后(wait_cnt[3] == 1'b1)即進入到READ_MEM狀態(讀存儲器狀態),直接讀取RAM中的數據;WRITE_REG是寫寄存器狀態,將32個16bit位寬的數據通過串行移位的方式送給DAC芯片的寄存器,移位完1個16bit位寬的數據后(shift_cnt == 4'd15 && pose_flag == 1'b1 && data_end != 1'b1)就回到WAIT狀態,然后重新等待8個時鍾周期,重新執行READ_MEM狀態和WRITE_REG狀態,直到32個數據全都讀寫完畢后才進入STOP狀態(shift_cnt == 4'd15 && pose_flag == 1'b1 && data_end == 1'b1),拉高conf_end信號。

【設計步驟】

(1) 寫spi_ctrl.v文件,首先寫分頻計數器,將50MHz的系統時鍾分頻為1MHz作為SPI的時鍾spi_clk(一般是50~60MHz,但此處僅是演示實驗,用1MHz即可),同時,產生clk_p和clk_n兩個相位相反、頻率為1MHz的reg信號,clk_p是正相時鍾信號,用以觸發脈沖標志信號pose_flag(標志SPI時鍾信號上升沿的到來),clk_n是反相的時鍾信號,用作spi_clk,送給SPI當作時鍾使用,以上共需寫4個always語句塊。

(2) 建立一個16bit x 32的單口RAM IP核(僅讀不寫),並例化到spi_ctrl.v中,完成mif文件的編輯和拷貝。

(3) 聲明狀態機變量,寫狀態機(兩段式),包括等待狀態下的計數器、讀RAM的地址產生模塊(1個系統時鍾周期讀出1個數據)、串行移位寄存器(左移,移出最高位)、移位操作的計數器、data_end信號控制模塊、數據輸出模塊、片選信號控制模塊、conf_end信號控制模塊以及狀態跳轉模塊等部分。

(4) 寫testbench文件和run.do文件,運行仿真並分析仿真結果(跑300us)。對testbench文件的要求如下:①能使用$readmemb命令讀出dac_ini_16x32.mif文件中的數據;②能在rec_spi任務塊中實現對SPI傳輸數據的回收,並與dac_ini_16x32.mif文件中的數據進行校對,然后用$display命令顯示校對結果和數據信息。

【代碼實現】

(1)設計一個計數分頻模塊,用50MHz的系統時鍾產生1MHz的時鍾信號給SPI讀/寫操作使用,同時產生clk_p和clk_n兩個相位相反、頻率均為1MHz的信號:

image

同時,產生一個標志clk_p上升沿的標志信號pose_flag,用它統一系統的全局時鍾:

image

【注意事項】盡量不要使用分頻產生的clk_p或clk_n當作always塊的觸發條件!原因:時鍾信號在很大程度上決定了整個設計的性能和可靠性,應盡量避免使用FPGA內部邏輯產生的時鍾,因為它很容易導致功能或時序出現問題,內部邏輯產生的時鍾信號容易出現毛刺(布線用線的質量較差),影響信號質量,同時,組合邏輯電路固有的延時也容易導致時序問題。詳細的解說請見特權的《深入玩轉FPGA》一書的P59。

(2)RAM IP核的創建和例化:

clip_image015

圖5 RAM IP核的參數配置

clip_image017

圖6 去掉q端寄存器

clip_image019

圖7 新建和添加mif文件

clip_image021

圖8 勾選例化文件

例化到spi_ctrl.v文件中:

image

(3)聲明狀態變量和狀態參數,寫狀態機:

image

狀態跳轉控制:

image

image

① 寫狀態機寫到WAIT狀態時,發現需要產生wait_end信號,而wait_end信號是由計數等待8個時鍾周期后產生的,故先需要設計WAIT狀態等待計數模塊:

image

然后,用設計wait_end信號產生模塊:

image

② 寫狀態機寫到READ_MEM狀態時,發現需要先將RAM中的數據讀出來,故先需設計產生讀RAM地址的模塊:

image

③ 寫狀態機寫到WRITE_REG狀態時,發現先要將從RAM讀出來的數據緩存起來(通過shift_buf緩存),然后逐比特地通過sdi線送給DAC芯片(串行移位寄存器):

image

然后,設計模塊產生移位完成的標志信號shift_end:

image

然后,設計SPI接口的數據輸出模塊、片選信號控制模塊以及時鍾信號產生模塊:

image

image

image

數據逐比特地送給spi_sdi接口,每幀傳輸16bit的數據,當傳輸完32個16bit的數據后,需要產生一個data_end標志信號,標志所有數據已經傳輸完畢:

image

當傳輸完32個16bit的數據時,也即完成了DAC芯片32個寄存器的配置工作,故需要產生一個conf_end標志信號,標志配置操作的完成:

image

Testbenchrun.do

Testbench文件:

① 用文件控制任務$readmemb讀出dac_ini_16x32.mif文件中的數據,並用這些數據初始化存儲器mif_data(reg [15:0] mif_data[0:31]):

image

② 計一個名為spi_check的任務,用它回收spi通信的數據,並將其與dac_ini_16x32.mif文件中的數據進行校對,如果數據一致則輸出數據的索引和具體內容,否則提示“SPI write is error!”:

image

run.do文件:

image

【仿真結果及分析】

image

圖9 transcript窗口的信息1

image

圖10 transcript窗口的信息2

如圖9、圖10所示,Testbench從SPI接口回收的數據與mif文件中的數據一致,由此可見SPI數據傳輸的正確性。

image

圖11 狀態機視圖

如圖12所示,是SPI仿真波形的整體圖:

image

圖12 仿真波形圖1

如圖13所示,spi_clk的上升沿對准spi_sdi數據的中心,滿足DAC芯片SPI寫時序的要求,即:數據在時鍾信號上升沿到來的時候寫入DAC芯片。

image

圖13 仿真波形圖2

如圖14所示,展示了狀態機跳轉到STOP狀態(10000)及data_end上升沿的出現。

image

圖14 仿真波形圖3

image

圖15 仿真波形圖4

由圖15可知,在WRITE_REG狀態下,片選信號spi_csn低電平狀態的持續時間約為16us,而spi_clk的周期是1us,故由此可知SPI每次移位傳輸占用了16個SPI時鍾周期,這與代碼中設計的每幀傳輸16bit數據的設想是一致的。

关注微信公众号

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com