(1.中國科學院 光電研究院, 北京 100094; 2.中國科學院大學, 北京 100049)
SPI(Serial Peripheral Interface)是由摩托羅拉公司在20世紀80年代中期針對短距離通信提出的一種同步串行通訊接口,被廣泛地應用于嵌入式系統中。嵌入式處理器可以通過SPI接口與許多外設芯片如FLASH、氣壓傳感器、EEPROM、高速ADC等[1-4]進行通信。
目前,大部分嵌入式處理器片內都自帶了SPI控制器。在有些情況下,SPI控制器的一些片選引腳可能會被其它片內外設所使用,此時如果系統需要控制多路SPI接口外設芯片,可以采用FPGA來擴展多路SPI控制器,通過FPGA擴展出來的SPI控制器與SPI接口外設芯片進行通信[5]。
本文設計了一個具有多路SPI控制器的系統,該系統采用TMS320C6748作為主控制器,采用FPGA作為協處理器。在FPGA上實現了接口模塊、寄存器讀寫模塊以及多路SPI模塊。DSP芯片通過其異步存儲器訪問接口EMIFA(External Memory Interface A)可以訪問FPGA內的寄存器,與FPGA進行通信[6],從而實現與多路SPI接口外設芯片的通信。采用DSP的EMIFA接口,結合硬件可重置的FPGA,極大地增強了系統的接口擴展能力,系統不僅能擴展多路SPI接口,還能擴展其它通信接口,如UART、CAN[7-8]等。
針對所設計的系統,在ModelSim環境下進行了仿真實驗,對SPI控制器進行了簡單的收發測試,驗證了其邏輯正確。最后,在DSP-FPGA集成計算機上展開實物測試,利用所設計SPI控制器對SPI接口CAN控制器芯片進行控制,實現了CAN通信,驗證了該系統的可行性。
系統的硬件拓撲如圖1所示,DSP與FP-GA通過EMIFA接口通信,FPGA的一個引腳作為中斷信號引腳連接到DSP的一個GPIO引腳上,FPGA外接多路SPI接口芯片。
當FPGA接收到任意一路SPI接口芯片的數據時,會在其中斷信號引腳int_o上產生中斷信號,通知DSP讀取FPGA接收到的數據。int_o引腳此時由低電平變為高電平,產生了上升沿跳變。若在軟件中已經使能了DSP的GPIO BANK中斷,且GPIO中斷觸發類型被設置為上升沿觸發,則DSP將產生GPIO BANK中斷。DSP在中斷子程序中讀取了FPGA所接收到的數據后,FPGA將把中斷信號引腳int_o的電平清零,此時DSP的GPIO引腳又將恢復為低電平。

圖1 系統硬件拓撲圖
FPGA實現了接口模塊、寄存器讀寫模塊、SPI模塊以及中斷管理組合邏輯,各模塊連接關系如圖2所示。

圖2 FPGA片內模塊連接圖
接口模塊與DSP的EMIFA接口相連,對EMIFA接口時序解析,產生讀控制信號re_o和寫控制信號we_o給寄存器讀寫模塊。讀控制信號re_o同時還控制三態門的開閉,re_o有效時,三態門將會打開,FPGA輸出數據到DSP,否則,三態門關閉,DSP輸出數據到FPGA。寄存器讀寫模塊包括各個SPI模塊的寄存器,配置SPI模塊的工作模式,保存SPI模塊接收的數據。SPI模塊與外設芯片相連,將接收到的數據存到寄存器讀寫模塊的寄存器中,同時將寄存器讀寫模塊內要發送的數據發送出去。中斷管理組合邏輯對各個SPI模塊進行中斷管理,并產生中斷信號輸出至DSP。各個SPI模塊功能一致,但是相互獨立,使SPI接口擴展更為靈活。
為了讓模塊連接圖更為簡潔,圖2中省略寄存器讀寫模塊與SPI模塊間的連接關系,文中后續再給出細節。
接口模塊的作用是對EMIFA接口時序解析,產生地址信號addr、讀控制信號re_o、寫控制信號we_o。
對EMIFA接口而言,只要按照EMIFA接口的讀寫時序定義好接口模塊,將FPGA片內寄存器的地址統一映射到EMIFA的訪問空間,訪問FPGA的片內寄存器和訪問其它異步存儲器并無二致。
TMS32C6748的EMIFA接口一共有4個片選引腳,標號為EMA_CS[5:2],系統使用片選引腳EMA_CS[2]作為FPGA的片選,則FPGA片上寄存器在TMS32C6748地址空間里的基址為0x60000000。FPGA對外數據總線接口D[15:0]為16位,根據數據手冊,TMS320C6748訪問16位異步存儲器時,其地址線連接關系如圖3所示。

圖3 EMIFA至16位異步存儲器連接圖
由圖可見接口模塊輸入端EMIFA地址信號EMA_A[15:0]應連接至輸出端地址信號的高16位,接口模塊輸入端EMIFA的BANK地址信號EMA_BA[1]應連接至輸出端地址信號的最低位。接口模塊地址轉換Verilog代碼如下:
assign addr[16:1] = emifa_addr[15:0];
assign addr[0] = emifa_ba1;
EMIFA的讀寫時序如圖4、圖5所示[10]。

圖4 EMIFA讀時序圖

圖5 EMIFA寫時序圖
當DSP訪問0x6000 0000~0x61FF FFFF地址空間時,EMA_CS[2]信號將會有效[9]。讀數據時,OE信號有效,輸出低電平;寫數據時,WE信號有效,輸出低電平。據此,FPGA接口模塊可以結合EMA_CS[2]、OE、WE3個信號的電平高低來判斷DSP進行的是讀操作還是寫操作,分別在讀信號引腳re_o和寫信號引腳we_o上產生有效電平,并輸出至寄存器讀寫模塊。由以上分析可得,接口模塊輸出的讀寫信號與輸入的EMIFA接口讀寫信號邏輯關系為:
assign we_o = ~cs_n&(we_n == 1’b0);
assign re_o = ~cs_n&(oe_n == 1’b0);
寄存器讀寫模塊保存各個SPI模塊的寄存器數據,每一路SPI模塊對應寄存器讀寫模塊中3個32位寄存器和1個16位寄存器,各寄存器名稱如表1所示,表中n表示該寄存器對應第n路SPI模塊。

表1 寄存器讀寫模塊SPI寄存器表
SPI格式寄存器存儲SPI模塊數據傳輸的格式信息,其字段描述如表2所示。

表2 SPIFMT寄存器字段描述表
SPI接收數據寄存器存儲SPI模塊接收到的數據,SPI發送數據寄存器存儲SPI模塊要發送的數據,SPI延時寄存器存儲SPI數據傳輸的延時信息。
EMIFA數據總線只有16位,因此,每次讀寫32位寄存器只能讀寫高16位或低16位。
寄存器讀寫模塊與SPI模塊的接口關系如圖6所示。

圖6 寄存器讀寫模塊接口圖
在時鐘的上升沿,寄存器讀寫模塊分別判斷寫控制信號we或讀控制信號re是否有效。若讀寫控制信號有效,寄存器讀寫模塊根據輸入的偏移地址信號addr確定所要讀寫的SPI寄存器的地址,對該偏移地址處的SPI寄存器進行讀寫。
當SPIDAT寄存器低16位數據更新時,寄存器讀寫模塊的spidat_write_pulse信號有效,并保持1個時鐘周期。SPI模塊檢測到spidat_write_pulse信號有效后,將啟動數據傳輸。
寄存器讀寫模塊不僅能保存多路SPI模塊的寄存器,還能保存其它通信模塊的寄存器。當系統需要擴展其它通信接口,如串口、CAN時,在寄存器讀寫模塊中對每一路通信接口定義一組該接口專用的寄存器即可。通過寄存器讀寫模塊對各個通信接口的寄存器統一管理,簡化了通信接口模塊的實現。通信接口模塊只需關注通信協議的實現,而無需考慮DSP對其相關寄存器的讀寫操作。
SPI模塊對外提供SPI接口,與外設芯片相連。SPI模塊實現SPI通信協議,具有以下功能:
1)支持8位、16位、24位、32位4種字長數據傳輸;
2)支持4種時鐘傳輸模式;
圖7為SPI模塊的原理框圖。MOSI、MISO、CS、SCLK為標準SPI協議引腳,連接外設芯片。BUSY引腳接DSP的GPIO,DSP可以查詢該引腳,判斷SPI模塊是否正在發送數據。SPIDAT、SPIBUF、SPIDAT、SPIDEL端口與寄存器讀寫模塊相連。
SPI模塊讀取寄存器讀寫模塊SPIDAT寄存器的值輸出到外設芯片,從外設芯片接收到的數據則保存到SPIBUF寄存器中。SPIDEL寄存器表示SPI數據連續傳輸時相鄰數據傳輸時間間隔大小。SPIFMT寄存器控制SPI模塊數據傳輸的格式,包括字長、分頻系數、相位極性、移位方向、傳輸延時。

圖7 SPI模塊框圖
SPI模塊分為三部分實現:數據發送、數據接收、模式與時鐘發生。txbuf_8b、txbuf_16b、txbuf_24b、txbuf_32b為用于發送數據的緩沖寄存器,對應4種字長的數據發送。SPI模塊將SPIDAT寄存器讀取到其中一個數據發送緩沖寄存器中,再將其移位輸出至MOSI引腳。
在SPI傳輸的每個時鐘周期內,SPI模塊同時會讀取MISO引腳接收的數據。根據字長,將MISO引腳接收的數據移位輸入到4個接收緩沖數據寄存器中的一個。rxbuf_8b、rxbuf_16b、rxbuf_24b、rxbuf_32b4個接收緩沖數據寄存器分別用于8位、16位、24位、32位4種字長數據傳輸的數據接收。移位接收完成后,SPI模塊再把接收緩沖寄存器的值輸出到SPIBUF寄存器。
模式與時鐘發生部分從SPIFMT寄存器讀取出控制SPI傳輸的格式信息,包括字長、分頻系數、極性、相位、數據移位方向、傳輸延時等,同時對SPI模塊輸入時鐘分頻,輸出SPI時鐘SCLK。其中,字長表示每次SPI數據收發的位數;分頻系數用于調整SCLK大小;SCLK與SPI模塊輸入時鐘的頻率關系如式(1)所示:
(1)
極性與相位共同決定SPI傳輸的時鐘模式,根據其不同組合,SPI模塊可工作在4種時鐘模式下;數據移位方向確定SPI傳輸是從最高位至最低位還是從最低位至最高位;傳輸延時表示SPI連續傳輸時相鄰兩次傳輸的最小時間間隔。
SPI模塊工作在有限狀態機,其狀態可分為空閑態、延時態和傳輸態3種。圖8為4種SPI時鐘模式下各延時態示意圖。

圖8 SPI模塊傳輸延時圖
其中,延時態C2TDELAY、T2CDELAY、WDELAY分別表示片選有效到第一個SCLK之間的延時階段、最后一個SCLK到片選無效之間的延時階段、片選無效到空閑態延時階段。
傳輸態有4種模態,每種模態對應一種時鐘模式。狀態機狀態轉移圖如圖9所示。
SPI模塊初始時處于空閑狀態,當DSP往寄存器讀寫模塊的SPIDAT寄存器低16位寫入新的數據后,spidat_write_pulse為1, SPI模塊將進入C2TDELAY延時態,片選信號EMA_CS[2]被拉低,延時時間由式(2)計算可得:
TC2T=Tclk*(c2tdelay+1)
(2)
延時結束后,SPI狀態機根據極性和相位的組合,切換至4種傳輸模態之一。在傳輸模態,SPI模塊發送數據到MOSI引腳,同時從MISO引腳讀取數據。發送完成后,狀態機依次切換至T2CDELAY延時態和WDELAY延時態,兩個延時態的延時時間由式(3)和式(4)可計算得到:
TC2T=Tclk*(t2cdelay+1)
(3)
TW=Tclk*(wdelay+1)
(4)
最后,狀態機回到空閑狀態,等待DSP啟動下一輪的數據傳輸。

圖9 SPI模塊狀態轉移圖
FPGA接收到SPI外設芯片的數據后,通過中斷方式通知DSP讀取所接收到的數據。一種簡單的中斷管理方式是FPGA為每一路SPI外設芯片都配置一個中斷信號引腳,每一個中斷信號引腳分別連接到DSP的不同GPIO引腳上。當FPGA接收到來自不同的SPI外設芯片發送過來的數據時,就在其所對應的中斷信號引腳上產生中斷信號。在SPI外設芯片較少的時候,這種方法簡單實用,但是在SPI外設芯片較多時,該方法將占用較多GPIO。
系統采用了一種常用的中斷管理方法,所有SPI外設芯片共用一個中斷信號引腳,通過中斷標志寄存器來判斷中斷源是誰。每一路SPI外設芯片都是一個中斷源,對應中斷標志寄存器中的一個標志位,當FPGA接收到SPI外設芯片數據時,會將中斷標志寄存器中相應的標志位置1,并在中斷信號引腳上產生中斷。DSP在GPIO BANK中斷處理子程序中讀取FPGA的中斷標志寄存器即可判斷中斷源是哪一路SPI外設芯片,在讀取中斷標志寄存器后,所有中斷標志位將自動清除。
在ModelSim環境下對系統進行仿真,在激勵模塊中,先對寄存器讀寫模塊中的相關寄存器進行設置。為了便于觀察,在仿真程序中設置分頻系數為7,SCLK頻率為輸入時鐘的8分頻。c2tdelay和t2cdelay均設為7,則C2TDELAY和T2CDELAY延時態均為延時8個SPI模塊輸入時鐘周期。字長設置為8位,移位輸出方向設為從最高位到最低位,相位和極性均設置為0,主機在SCLK上升沿輸出數據到MOSI引腳,在SCLK下降沿鎖存MISO引腳輸入的數據。
測試過程如下,激勵模塊通過EMIFA接口往SPIDAT寄存器低16位寫入0x00AA,啟動SPI數據發送。因為字長為8,每次SPI模塊只發送SPIDAT的低8位,所以SPI模塊應發送0xAA到激勵模塊。為了觀測SPI模塊是否能進行全雙工通信,在SPI模塊發送0xAA到激勵模塊的同時,激勵模塊也發送0x55至SPI模塊。然后讀取寄存器讀寫模塊的SPIBUF寄存器的低16位,如果SPIBUF寄存器低8位為0x55,說明接收邏輯正確。仿真波形如圖10所示。

圖10 仿真波形圖
由圖10可見,FPGA輸出到MOSI上的數據為10101010,故發送給激勵模塊的數據為0xAA,與激勵模塊寫入SPIDAT寄存器低8位的數據一致;MISO上接收的數據為01010101,故FPGA讀取到的數據為0x55,與激勵模塊發送給SPI模塊的數據一致。可見收發邏輯均無誤,所設計的系統在仿真實驗中可以進行正常的全雙工通信。
為了驗證設計的SPI控制器能否正常工作,將具有SPI接口的CAN控制器芯片MCP2515連接到FPGA擴展出的SPI控制器引腳上進行測試。
DSP先發送一幀數據到上位機,幀ID為0x7ff,數據為0x7f、0x04。然后上位機再發送一幀數據到DSP,幀ID為0x7ff,數據為0x00、0x01、0x02、0x03、0x04、0x05、0x06、0x07。測試結果如圖11和圖12所示。由圖11可以看出,上位機接收到一幀數據,幀ID為0x07ff,數據為0x7f、0x04,與DSP發送的數據一致。然后上位機返回一幀數據給DSP,幀ID為0x7ff,數據為0x00、0x01、0x02、0x03、0x04、0x05、0x06、0x07,DSP接收到的數據如圖12所示。可以看到,與上位機發送的數據一致,說明MCP2515可以實現正常的CAN數據收發,所設計的SPI控制器系統可以正常地與SPI外設芯片通信。

圖11 上位機收發圖

圖12 DSP接收數據圖
本文實現了基于FPGA和EMIFA的SPI控制器。在FPGA上擴展了多路SPI控制器,TMS320C6748通過EMIFA接口訪問通過FPGA擴展的SPI控制器,實現了與多路SPI接口外設同時通信的需求。采用模塊化設計的方法,系統具有良好的可擴展性。經過仿真測試與實際硬件測試,證明了該系統工作正常。