《電子技術應用》
您所在的位置:首頁 > 可編程邏輯 > 其他 > 教程:SDRAM存儲控制器的設計與實現(xiàn)

教程:SDRAM存儲控制器的設計與實現(xiàn)

2022-10-24
來源:FPGA之旅
關鍵詞: 存儲控制器 SDRAM

  一. 簡介

  本例將介紹SDRAM的使用,。SDRAM是一個存儲器件,,存儲容量大,,存儲速度比較快,速度可達100M,,特別適合用來當做視頻或者音頻中的存儲器件,。

  在采集到OV5640傳輸過來的圖像數(shù)據(jù)的時候,,F(xiàn)PGA的片上資源是沒有那么大的存儲空間進行存儲的,必須通過外部的存儲器件進行存儲,。恰好開發(fā)板上有一片SDRAM,,所以用此來進行存儲,一般而言入門級的FPGA開發(fā)板上都是配置的SDRAM,,中高級一點的是DDR2(alter開發(fā)板),,DDR3(xilinx開發(fā)板)。

  所以本例將實現(xiàn)一個完善的SDRAM存儲控制器,,供大家查看,。

  二. SDRAM接口信號

  從下面框圖中可以看出,SDRAM接口信號可以分為四大類:控制信號,,地址信號,,數(shù)據(jù)輸入輸出信號,掩碼信號,。下面將詳細介紹各個命令的作用。

  050.JPG

  以上就是SDRAM的全部接口信號了,,并沒有特別復雜,。

  下圖是SDRAM的所有命令,在對SDRAM進行操作的時候,,需要使用到,。

049.JPG

  然后在。v文件中先將其定義出來,,方便后續(xù)使用

048.JPG

  三.  SDRAM上電初始化

  上電后,,沒有任何時序上的操作,只需要延時100us(手冊上要求最小為100us),,使輸入輸出電平達到穩(wěn)定,,即可,在此期間,,發(fā)送的命令最好為NOP,。

  這里初始化包括了初始化和加載模式寄存器,我認為初始化,,就是加載模式寄存器,。

  (1)模式寄存器

  模式寄存器的定義如下,,通過地址線給出,,每位都有其具體的含義。

  0-2 bit:定義突發(fā)長度,,每給一個讀/寫命令后,,輸出/輸入的數(shù)據(jù)大小

  4-6bit :定義潛伏期,,發(fā)出讀命令后,延時多少個周期給讀數(shù)據(jù),,僅對讀操作有效

  10-12bit: 保留,,始終置高即可

  其余位始終保持為0即可。模式寄存器的內容就這么多,。

047.JPG

 ?。?)初始化

  下圖是初始化的過程,按照圖示要求依次發(fā)送對應的命令即可,,命令與命令之間的間隔時間手冊上都有說明,,取的時候,可以適當取大,。模式寄存器的A信號被分成了兩部分A10和其他,,可以看到A10在PRECHARGE階段有特殊作用,一般為1,,對所有的bank都進行預充電,。

  在模式寄存器中A10也是為1的,所以在整個初始化過程中,,A可以直接賦值為模式寄存器的值,。

046.JPG

  實現(xiàn)過程如下,也是非常簡潔的,,編寫好初始化模塊看,,可以直接仿真,這里多虧了大佬寫的sdram模型(就是一個,。v文件),,不用上板,可以直接仿真看代碼編寫是否正確,。

  045.JPG

  仿真輸出如下,,可以看到和時序圖中,命令發(fā)送過程是一樣,,同時也可以看到,,模式寄存器配置的具體參數(shù),非常方便,,初始化模塊就順利的編寫完成了,。

 044.JPG

  四. 刷新模塊

  由于sdram的特殊結構,sdram在使用的過程中,,需要每隔一段時間,,對所有的存儲區(qū)域進行一次刷新操作(充電),否則內部存儲的數(shù)據(jù)會丟失,,這將會成為后面設計的一大難點,。

  根據(jù)手冊得知每64ms需要完成8192次刷新操作,,也就是下面的時序圖需要在64ms內運行8192次,平均下來7us就要進行一次,,這個時間需要記住非常重要,。

  同樣也是根據(jù)手冊給出的時序圖進行編寫代碼,一共需要發(fā)送三個命令

043.JPG

  代碼實現(xiàn)如下,,也是非常容易實現(xiàn)的,。

042.JPG

  從圖中可以看出,每隔7090ns進行一次刷新,,滿足要求,。

  041.JPG

  至此,初始化和刷新模塊編寫完成,,這兩部分只需要按照手冊上給出的時序圖來編寫代碼即可,,比較容易即可完成,后面的讀寫模塊會復雜一些,。

  五. 寫模塊

  讀模塊的時序圖如下,,截取的是沒有auto precharge操作的,也就是在數(shù)據(jù)寫完后,,需要手動發(fā)送一個precharge命令,。同樣可以讓sdram自動完成這個操作,只需要在發(fā)送write命令的時候,,將A10拉高即可,這樣在發(fā)送完數(shù)據(jù)后,,就可以直接結束了,,不用發(fā)送precharge命令。本次介紹的是需要發(fā)送precharge命令,。

  設計時需要清楚以下兩個問題

  發(fā)送過程中,,需要切換行地址或者bank的時候,應該怎樣操作

  發(fā)送過程中,,突然來了刷新請求時,,該如何處理

  040.JPG

  先對第一個問題進行說明一下,在sdram中,,行地址和bank是發(fā)送ACTIVE命令時指定的,,發(fā)送write命令時,就可以指定列地址了,,如下BL=1,。也就是說切換行地址或bank時需要重新發(fā)送ACTIVE命令。ps:寫操作是沒有潛伏期的,。

039.JPG

  手冊中也給出了這部分的時序圖,,如下,。需要注意的一點是,它這是使能了auto precharge,,所以數(shù)據(jù)發(fā)送完成后,,沒有發(fā)送precharge命令,就發(fā)送了ACTIVE命令來切換行地址或bank了,。沒有使能的情況下,,需要加上precharge地址,然后再延時tRCD,,發(fā)送ACTIVE命令,,這點需要注意。

038.JPG

  第二個問題,,當刷新請求來時,,這個時候當然是要暫停發(fā)送數(shù)據(jù),需要保存已經(jīng)發(fā)送數(shù)據(jù)的個數(shù),,以及當前發(fā)送的地址和bank,。然后在刷新結束后,繼續(xù)發(fā)送數(shù)據(jù),。

  模塊框圖和狀態(tài)機如下,。在write_data_en使能的情況下,外部輸入數(shù)據(jù)進來,,其余時刻輸入的數(shù)據(jù)無效,,相當于一個握手信號。sdram模式寄存器配置的是突發(fā)長度為1,,所以這里單次寫突發(fā)長度是沒有大小限制的,。

  sdram_write

  (

  input               sdram_clk,

  input               rst_n,

  input               sdram_write_req,            //寫請求

  output              sdram_write_ack,            //寫響應

  input               sdram_write_pause,          //寫暫停信號,,轉去刷新操作

  output  reg         sdram_write_pause_ack,      //寫暫停響應,,成功暫停

  input[24:0]         write_addr,                 //寫入地址

  input[15:0]         write_data,                 //寫入數(shù)據(jù)      {bank[1:0s],row[12:0],clo[9:0]}

  input[9:0]          write_burst_length,         //單次寫突發(fā)長度    //可以為sdram大小

  output              write_data_en,              //寫入數(shù)據(jù)有效輸出

  //sdram接口

  output[3:0]         sdram_write_cmd,

  output[12:0]        sdram_write_addr,

  output[1:0]         sdram_write_ba,

  output[15:0]        sdram_write_data

  ),;

  localparam      S_IDEL                  =   'd0;        //空閑態(tài)

  localparam      S_ACTIVE                =   'd1;        //激活態(tài)

  localparam      S_WRITE                 =   'd2;        //寫數(shù)據(jù)

  localparam      S_PAUSE                 =   'd3;        //寫暫停

  localparam      S_ALTERNATE             =   'd4;        //換行換bank緩存

  localparam      S_PRECHARGE             =   'd5;        //寫結束后或切換行列地址,,發(fā)送precharge命令

  localparam      S_END                   =   'd6;        //寫結束

  always@(*)

  begin

  case(state)

  S_IDEL:

  if( sdram_write_req == 1'b1 )

  next_state <= S_ACTIVE;

  else

  next_state <= S_IDEL;

  S_ACTIVE:

  if( sdram_write_pause == 1'b1 )     //寫暫停信號,轉去刷新操作

  next_state <= S_PAUSE;

  else if( time_cnt == `tRCD )

  next_state <= S_WRITE;

  else

  next_state <= S_ACTIVE;

  S_WRITE:

  if( sdram_write_pause == 1'b1 )     //寫暫停信號,,轉去刷新操作

  next_state <= S_PAUSE;

  else if( alternating_bank_row_en == 1'b1)

  next_state <= S_PRECHARGE;

  else if( write_burst_length_cnt == write_burst_length )

  next_state <= S_PRECHARGE;

  else

  next_state <= S_WRITE;

  S_PAUSE:

  if( sdram_write_pause == 1'b0 )     //刷新操作結束

  next_state <= S_ACTIVE;

  else

  next_state <= S_PAUSE;

  S_ALTERNATE:

  if( time_cnt == `tRCD)

  next_state <= S_ACTIVE;

  else

  next_state <= S_ALTERNATE;

  S_PRECHARGE:

  if( time_cnt == `tRP + `tWR)

  if( write_burst_length_cnt >= write_burst_length)

  next_state <= S_END;

  else

  next_state <= S_ALTERNATE;

  else

  next_state <= S_PRECHARGE;

  S_END:

  next_state <= S_IDEL;

  default :  next_state <= S_IDEL;

  endcase

  end

  最后通過仿真,,確認實現(xiàn)正確,第一幅圖是寫過程進行刷新操作,,第二幅圖是,,寫過程切換行地址

037.JPG

  六. 讀模塊

  讀模塊過程的編寫和寫模塊是一模一樣的,不過需要注意的是讀模塊有潛伏期,命令發(fā)送和數(shù)據(jù)輸出相差CL個時鐘周期,,讀數(shù)據(jù)的時候,,需要將這個延時加入其中,可以看到接口信號和寫模塊是一樣,。不過對數(shù)據(jù)進行采樣的時候,,需要使用輸入到sdram中的時鐘,這需要注意,。

  036.JPG

  sdram_read

 ?。?/p>

  input               sdram_clk,

  input               rst_n,

  input               sdram_read_req,            //讀請求

  output              sdram_read_ack,            //讀響應

  input               sdram_read_pause,          //讀暫停信號,轉去刷新操作

  output  reg         sdram_read_pause_ack,      //讀暫停響應,,成功暫停

  input[24:0]         read_addr,                 //讀入地址

  output[15:0]        read_data,                 //讀出數(shù)據(jù)      {bank[1:0s],row[12:0],clo[9:0]}

  input[9:0]          read_burst_length,         //單次讀突發(fā)長度    //可以為sdram大小

  output              read_data_en,              //讀數(shù)據(jù)有效輸出

  //sdram接口

  output[3:0]         sdram_read_cmd,

  output[12:0]        sdram_read_addr,

  output[1:0]         sdram_read_ba,

  input[15:0]        sdram_read_data

 ?。?/p>

  通過仿真輸出,,確定突發(fā)讀期間,,換行以及刷新完全正確

 035.JPG

  至此SDRAM模塊的編寫就完成了,頂層框圖如下,,至于在外部如何進行封裝,,那就看不同的需求了。

  SDRAM_TOP(

  input                       sys_clk,                    //sdram的系統(tǒng)時鐘 100M

  input                       rst_n,                      //異步復位信號

  //讀接口

  input                       read_req,

  output                      read_ack,

  input[24:0]                 read_addr,

  input[9:0]                  read_burst_length,

  output[15:0]                read_data,

  output                      read_data_en,

  //寫接口

  input                       write_req,

  output                      write_ack,

  input[24:0]                 write_addr,

  input[9:0]                  write_burst_length,

  input[15:0]                 write_data,

  output                      write_data_en,

  //sdram接口

  output                      sdram_clk,         //sdram clock

  output                      sdram_cke,         //sdram clock enable

  output                      sdram_cs_n,        //sdram chip select

  output                      sdram_we_n,        //sdram write enable

  output                      sdram_cas_n,       //sdram column address strobe

  output                      sdram_ras_n,       //sdram row address strobe

  output[1:0]                 sdram_dqm,         //sdram data enable

  output[1:0]                 sdram_ba,          //sdram bank address

  output[12:0]                sdram_addr,        //sdram address

  inout[15:0]                 sdram_dq           //sdram data

 ?。?;

  結束



更多信息可以來這里獲取==>>電子技術應用-AET<<

mmexport1621241704608.jpg

本站內容除特別聲明的原創(chuàng)文章之外,轉載內容只為傳遞更多信息,,并不代表本網(wǎng)站贊同其觀點,。轉載的所有的文章、圖片,、音/視頻文件等資料的版權歸版權所有權人所有,。本站采用的非本站原創(chuàng)文章及圖片等內容無法一一聯(lián)系確認版權者。如涉及作品內容,、版權和其它問題,請及時通過電子郵件或電話通知我們,,以便迅速采取適當措施,,避免給雙方造成不必要的經(jīng)濟損失。聯(lián)系電話:010-82306118,;郵箱:[email protected],。