1. 程式人生 > >EMIF介面與FPGA的互聯(轉)

EMIF介面與FPGA的互聯(轉)

reference: https://blog.csdn.net/ruby97/article/details/7539151

DSP6455的EMIFA模組

之前介紹了DSP6455的GPIO和中斷部分。今天,繼續介紹EMIFA模組。

關於C6000系列的GPIO,請參考:C6000系列DSP的GPIO模組

關於C6000系列的中斷系統,請參考:C6000系列DSP的中斷系統


 

背景

      使用FPGA系統進行視訊採集,DSP進行視訊處理需要了解以下知識:

  • 1.  DSP-C6000系列的中斷與GPIO系統
  • 2.  DSP-C6000系列的EMIFA模組
  • 3.  DSP-C6000系列的EDMA模組
  • 4.  FPGA的乒乓RAM
  • 5.  一種視訊格式(例如VGA,PAL等)
  • 6.  視訊處理演算法

 

之前已經介紹了第一部分,今天介紹第二部分。


 

主題

      EMIF是External Memory Interface的簡稱。個人認為它是DSP比較強大的地方之一。通過EMIF介面,使得DSP可以和FPGA很方便地進行大資料量的資料傳輸。

 

      C6455的EMIFA可以訪問多種外部儲存器,比如:SRAM,ROM,FLASH等等。當然,也包括FPGA。本文的重點就是介紹使用EMIFA介面與FPGA建立無縫連線。

 

--------------------------------------------華麗分割------------------------------------------------

 

EMIFA

根據習慣,還是先貼圖,框圖總給人一目瞭然的感覺。

 

 

這是官方文件給出的EMIFA模組的介面示意圖,乍一看,複雜的很。好多引腳而且還有好多複用。沒關係,我們再貼一張,你就會感覺輕鬆很多了。

 

 

 

這一張圖首先是把EMIFA模組的介面分了類,然和呢,我把在與FPGA通訊場合下所需要使用的管腳使用紅色框框標註了出來。是不是少了很多呢。歸納一下標註的管腳,如下:

  • AED[63:0]        64位資料匯流排
  • AEA[19:0]        20位地址匯流排(Optional)
  • ACE2              片選訊號(低有效)
  • AECLKOUT      時鐘訊號
  • ASWE             寫使能(低有效)
  • ASRE               讀使能(低有效)

(注:應用場合是DSP讀FPGA內部RAM中的影象資料,其他場合續根據情況調整)

由於FPGA的可程式設計性,使得一切從DSP看來簡單了許多。因為DSP面對的“儲存器”顯得格外智慧。甚至連地址線都可以不需要。

下面,我們來一一分析上述的訊號。

  • 首先,應該是片選訊號CE。這裡不得不提到DSP的地址空間。下圖是DSP6455的EMIFA對映情況
  從圖中可以看出:
  • EMIFA共支援4個外部儲存器,比如可以把CE2分配給FPGA,CE3分配給SRAM,CE4分配給FLASH等。
  • 每個外部儲存器的定址空間大小是8MB。20根地址線即2的20次方,也就是1MB,此外由於資料匯流排是64位的,故對應的定址空間是8MB

 

由於FPGA內部時序邏輯可以產生地址,所以我們可以不使用地址線。這樣,下面的事情就簡單了。只要把CE2管腳和FPGA的某一個通用IO口連上即可。

在讀取FPGA內部RAM資料時告訴EDMA要讀取的資料的基地址是0xA0000000,以及讀取的資料的長度即可。

  • 第二個訊號,ECLKOUT,即時鐘訊號的。因為FPGA工作是需要時鐘激勵的,沒有時鐘訊號怎麼產生地址邏輯呢?此外,時鐘頻率不能過高,要考慮到FPGA晶片的能力。OK,因為有了同步時鐘,所以EMIFA模組的工作模式也就確定了,即同步工作模式。
  • 第三個訊號,包括2個,即ASRE,ASWE。更熟悉的叫法是RE,WE。讀使能和寫使能。這個就不贅述了。
  • 第四個訊號,資料匯流排&地址匯流排。也不贅述了。

經過上面的分析,我們可以簡要的畫出FPGA與DSP的連線圖:

      在連線的思路清晰之後,我們可以開始配置EMIFA的暫存器了。

其實也就只有1個比較重要的暫存器,即CEnCFG。該暫存器有兩套完全不同的配置。分別對應於同步儲存器模式和非同步儲存器模式。由於FPGA內部RAM工作於同步模式,故我們來看一下同步模式下該暫存器的配置。

  SSEL設定為1時,表示該CE對應同步模式的外部儲存器。 在與FPGA連線時,主要考慮以下四個引數:  
R_ENABLE 設定SRE/SADS管腳功能
值為 1 管腳功能為SRE,即Read Enable
值為 0 管腳功能為SADS

 

W_LTNCY 寫延時週期
值為 00 0週期延時
值為 01 1週期延時
值為 10 2週期延時
值為 11 3週期延時

 

R_LTNCY 讀延時週期
值為 01 1週期延時
值為 10 2週期延時
值為 11 3週期延時

 

讀延時:當CE和RE同時為低電平後,表示DSP開始讀FPGA的RAM,經過R_LTNCY個ECLKOUT週期後第一個資料出現在資料匯流排上

 

SBSIZE 資料位寬
值為 00 8位資料匯流排
值為 01 16位資料匯流排
值為 10 32位資料匯流排
值為 11 64位資料匯流排

 


 

 

EMIFA之CSL

使用CSL配置EMIFA模組時,主要的步驟如下:

  • l  1. 使能裝置EMIFA模組
  • l  2. 配置CEnCFG暫存器
  • l  3. 初始化EMIFA模組
  • l  4. 開啟EMIFA模組
  • l  5. 把2中配置的引數設定到開啟的EMIFA模組中

 

完整配置程式碼:(把EMIFA的CE2配置為以FPGA作為外部儲存器,64位資料線,2個週期的讀延時)

 

 
/*-----------------------------------------------------------------------------------
 
*
 
* 初始化EMIFA
 
*
 
-----------------------------------------------------------------------------------*/
 
#define EMIFA_MEMTYPE_ASYNC 0
 
#define EMIFA_MEMTYPE_SYNC 1
 
 
 
#define EMIFA_CE2_BASE_ADDR (0xA0000000)//地址空間基地址
 
#define CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER 2//讀延時2週期
 
#define CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER 3//64位資料匯流排
 
#define CSL_EMIFA_SYNCCFG_READEN_PARAMETER	1//SRE
 
 
 
//CEnCFG暫存器引數巨集
 
#define CSL_EMIFA_SYNCCFG_PARAMETER {\
 
(Uint8)CSL_EMIFA_SYNCCFG_READBYTEEN_DEFAULT, \
 
(Uint8)CSL_EMIFA_SYNCCFG_CHIPENEXT_DEFAULT, \
 
(Uint8)CSL_EMIFA_SYNCCFG_READEN_PARAMETER, \
 
(Uint8)CSL_EMIFA_SYNCCFG_WLTNCY_DEFAULT, \
 
(Uint8)CSL_EMIFA_SYNCCFG_RLTNCY_PARAMETER, \
 
(Uint8)CSL_EMIFA_SYNCCFG_SBSIZE_PARAMETER \
 
}
 
 
 
void Init_EMIF()
 
{
 
CSL_EmifaObj emifaObj;
 
CSL_Status status;
 
CSL_EmifaHwSetup hwSetup;
 
CSL_EmifaHandle hEmifa;
 
CSL_EmifaMemType syncVal;
 
CSL_EmifaSync syncMem = CSL_EMIFA_SYNCCFG_PARAMETER;
 
 
 
memset(&emifaObj, 0, sizeof(CSL_EmifaObj));
 
memset(&hwSetup, 0, sizeof(CSL_EmifaHwSetup));
 
 
 
//步驟1: 使能裝置的EMIFA功能(不用先解鎖外設暫存器)
 
CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG1, DEV_PERCFG1_EMIFACTL, ENABLE);
 
 
 
//步驟2:配置CE2CFG暫存器
 
syncVal.ssel = EMIFA_MEMTYPE_SYNC;
 
syncVal.async = NULL;
 
syncVal.sync = &syncMem;
 
 
 
hwSetup.ceCfg[0] = &syncVal;
 
hwSetup.ceCfg[1] = NULL;
 
hwSetup.ceCfg[2] = NULL;
 
hwSetup.ceCfg[3] = NULL;
 
 
 
//步驟3:初始化EMIFA模組
 
status = CSL_emifaInit(NULL);
 
 
 
#ifdef SHOW_PRINTF
 
if (status != CSL_SOK) {
 
printf("EMIFA: Initialization error.\n");
 
printf("\tReason: CSL_emifaInit [status = 0x%x].\n", status);
 
return;
 
}
 
else {
 
printf("EMIFA: Module Initialized.\n");
 
}
 
#endif
 
 
 
//步驟4:開啟EMIFA模組
 
hEmifa = CSL_emifaOpen(&emifaObj,CSL_EMIFA,NULL,&status);
 
 
 
#ifdef SHOW_PRINTF
 
if ((status != CSL_SOK) || (hEmifa == NULL)) {
 
printf("EMIFA: Error opening the instance. [status = 0x%x, hEmifa \
 
= 0x%x]\n", status, hEmifa);
 
return;
 
}
 
else {
 
printf("EMIFA: Module instance opened.\n");
 
}
 
#endif
 
 
 
//步驟5:把步驟2中配置的引數設定到開啟的EMIFA模組中
 
status = CSL_emifaHwSetup(hEmifa,&hwSetup);
 
#ifdef SHOW_PRINTF
 
if (status != CSL_SOK) {
 
printf("EMIFA: Error in HW Setup.\n");
 
printf("Read write operation fails\n");
 
return;
 
}
 
else {
 
printf("EMIFA: Module Hardware setup is successful.\n");
 
}
 
#endif
 
}