基於FPGA 的SDRAM控制器

13tree發表於2023-09-23

SDRAM基本資訊

儲存能力計算

  • 4X16X4=256(Mbit),注意不是MByte

SDRAM控制

sdram包含兩個部分:sdram_ctrl、fifo_ctrl。

  • sdram_ctrl:其頂層為SDRAM的控制模組內部例項化了5個模組,有初始化、自重新整理、寫和讀模組,還有一個仲裁模組對這四個不同操作進行分配;
  • fifo_ctrl:其頂層為SDRAM的資料輸入輸出,內部例項化了兩個用於連線SDRAM輸入和輸出端的FIFO,以及控制程式

sdram_ctrl模組內部例化了四個模組

初始化模組sdram_init

  • SDRAM在上電後首先需要執行初始化操作,才可執行其他操作。

  • 配置暫存器模式

  • 潛伏期為三個週期

  • 突發長度為頁突發

  • 突發型別為順序型別

  • 寫模式為頁突發寫模式

  • 訊號操作:

    1. 正常載入時鐘訊號:設定CKE時鐘使能為高電平CKE = 1
    2. 等待Vdd和CLK訊號穩定:等待T= 200us
    3. 進行預充電操作,對所有L-Bank進行預充電:cmd = PRECHARGE,A10 = 1
    4. 等待預充電操作:cmd = NOP,TRP =20ns
    5. 自動重新整理命令:cmd = AUTO REFRESH
    6. 等待自動重新整理:cmd = NOP,TRFC = 70ns
    7. 重複多次自動重新整理操作:重複8次
    8. 配置模式暫存器:cmd = LOAD MODE REGISTER,address= ,A10 = ,bank = 0
    9. 等待配置模式暫存器完成,TMRD = 30ns
  • 總體採用狀態機來設計,分為以下幾個狀態:

    1. 初始化
    2. 預充電
    3. 預充電等待
    4. 自動重新整理
    5. 自動重新整理等待
    6. 配置模式暫存器
    7. 配置模式暫存器等待
    8. 初始化完成
  • 為了防止亞穩態的產生,狀態機編碼均使用格雷碼

  • 跳轉條件使用計數器進行計數完成判斷

    • cnt_clk,等待狀態的計數器
    • cnt_clk_rst,負責等待計數器的清零操作
  • 另外為了跳轉操作程式碼簡潔,宣告組合邏輯的訊號完成各個狀態的跳轉

    • trp_end
    • trc_end
    • tmrd_end
  • 由於自動重新整理訊號需要重複進行,因此使用計數器完成自動重新整理操作計數

    • cnt_init_aref,計數自動重新整理操作的重複個數
  • 最終按照各個狀態完成輸出訊號的幅值,注意使用的為時序邏輯,因此輸出相比狀態跳轉延遲一拍

自動重新整理模組sdram_a_ref

  • SDRAM重新整理有兩種操作方式:
    • 自重新整理:用於休眠模式可以低功耗的儲存資料
      • 操作:CKR訊號為低電平時,寫入重新整理指令,進入自重新整理模式,當CKE訊號拉高時,退出自重新整理模式;
    • 自動重新整理模式:由於SDRAM動態特性,使用電容來儲存資料,因此需要不斷對電容進行充放電,以此保證資料不丟失。本文主要討論自動重新整理。
  • 自動重新整理操作需要不斷的迴圈操作,是一個週期操作,至少需要每64ms完成一次。
  • 自動重新整理時間計算
    • 儲存體中電容的資料有效儲存期上限是 64ms那麼使用的SDRAM的地址位寬為13位,共有2^13=8192行。
    • 那麼每行重新整理的時間為:64ms/8192=64*1000000ns/8192=7812.5ns。
    • SDRAM的時鐘為100MHz,週期為10ns,那麼計數器最大值為:7812.5/10=781.25個。
    • 但是由於自動重新整理操作和寫讀請求會產生衝突,會出現不會立即重新整理的情況,因此需要保留一段時間,那麼設定計數器最大值為750個,要求在7500ns中完成其中一行的重新整理。
  • 訊號操作
    1. 預充電操作:cmd = PRECHARGE、A10 = 1、bank = 2'b11
    2. 預充電等待:cmd = NOP,TRP = 20ns
    3. 自動重新整理:cmd = PRECHARGE
    4. 自動重新整理等待:cmd = NOP,TRFC = 70ns
    5. 自動重新整理重複兩次
  • 初始化模組為所有訊號的首位,因此需要初始化訊號拉高後在開始執行
    • init_end = 1時,模組開始正常工作
  • 由於是一個週期訊號,那麼需要一個計數器進行週期計數,並以此訊號完成狀態機的啟動。
    • cnt_ref作為計數器,最大值經計算為750-1,並且達到最大值後清零繼續計數
  • 其餘訊號需要在狀態機跳轉下進行操作:
    1. 初始
    2. 預充電
    3. 預充電等待
    4. 自動重新整理
    5. 自動重新整理等待
    6. 自動重新整理結束
  • 另外自動重新整理需要和仲裁模組進行握手,當仲裁模組同意進行重新整理操作時,才可進行該操作
    • 當內部計數器cnt_ref達到最大值時,此時需要自動重新整理,拉高自動刷洗請求訊號aref_req = 1,仲裁模組接受該訊號,進行判斷若同意則拉高自動重新整理使能訊號,aref_en = 1。
    • 當自動重新整理完成,拉高自動重新整理結束訊號,aref_end= 1,仲裁模組接受該訊號,拉低自動重新整理使能訊號,aref_en = 0;

寫操作模組sdram_write

  • 本模組使用的寫操作模式為:不自動進行預充電的頁突發寫模式
  • 訊號操作
    1. 啟用L-Bank特定行:
      1. cmd = ACTIVE
      2. address = 特定寫入行地址
      3. bank = 特定寫入bank地址
    2. 等待啟用
      1. cmd = NOP
    3. 寫資料命令
      1. cmd = WRITE
      2. address = 特定寫入列地址
      3. DQ = 寫入第一個資料
    4. 寫入資料中
      1. cmd = NOP
      2. DQ = 開始寫入第二個資料,每隔一個週期寫入一個資料
    5. 突發終止命令
      1. cmd = BURST TERM
      2. DQ = 不寫入資料
    6. 預充電命令
      1. cmd = PRECHARGE
      2. A10 = 1
      3. bank = 2'b11
    7. 預充電等待
      1. cmd = NOP
      2. TRP = 20ns
  • 當初始化模組完成初始化後才可以SDRAM才可以正常操作
    • init_end = 1,此時寫模組才可以正常開始工作
  • sdram模組的寫操作是由SDRAM上端的fifo模組發起請求,經過sdram仲裁器同意後開始執行寫操作的
    • SDRAM仲裁器判斷可以寫入時拉高,wr_en = 1
  • 當寫資料操作執行完畢後狀態機跳轉至寫結束狀態時,透過組合邏輯賦值將寫結束訊號拉高
    • wr_end = 1
  • 另外當FIFO請求向SDRAM寫入資料時,SDRAM並不能直接開始寫入,因此當真正開始寫入資料時需要一個提前一拍的響應訊號告知fifo可以輸出資料
    • wr_ack = 1
    • 相比於寫資料的同步訊號需要提前一拍,作為FIFO的讀出資料的讀請求訊號
  • 其餘訊號在狀態機下完成
    1. 初始狀態
    2. 啟用命令
    3. 啟用等待
    4. 寫命令
    5. 寫等待
    6. 預充電
    7. 預充電等待
    8. 寫結束
  • 寫入資料的資訊由外部訊號傳入,具體為輸入端的FIFO傳入
    • [23:0] wr_addr:寫入資料的地址,可以分割為:2bit bank地址、13bit 行地址、9bit 列地址
    • [15:0] wr_data,寫入資料
    • [9:0] wr_burst_len,寫入資料個數
  • 除了常規控制訊號輸出外還有一個,控制SDRAM資料匯流排輸出使能訊號,該訊號和真正寫入sdram的資料同步。

讀操作模組 sdram_read

  • SDRAM資料讀方式為:不帶自動預充電的頁突發讀模式
  • 訊號操作
    1. 啟用L-Bank的特定行
      1. cmd = ACTIVe
      2. address = Row
      3. bank = 2‘b11
    2. 等待啟用
      1. CMD = NOP
      2. TRCD =
    3. 讀命令
      1. CMD = READ
      2. address = column
    4. 讀出資料
      1. cmd = NOP
      2. 潛伏期設定為3,因此在寫入讀命令後的間隔3個週期,會有讀資料的輸出
    5. 突發終止
      1. cmd = BURST TERM
  • 讀資料操作需要在初始化操作完成後進行
    • 當init_end = 1 時,sdram_read進入正常工作模式
  • sdram讀資料操作是由外部訊號發起的,具體而言是SDRAM下端FIFO發出的讀請求訊號,並且該訊號需要經過仲裁器判斷後生效,仲裁器拉高讀使能訊號
    • rd_en = 1,讀模組開始進行讀操作
  • 當sdram_read讀操作完成後,狀態機進入結束狀態,使用組合邏輯同步拉高讀結束訊號
    • rd_end = 1
  • 由於資料需要存入下端FIFO模組因此需要輸出一個讀模組工作響應訊號,並且需要與資料同步,作為FIFO輸入的寫請求訊號
    • rd_ack = 1,需要和輸出資料同步
  • 其餘訊號在狀態機下完成
    1. 空閒狀態
    2. 啟用
    3. 啟用等待
    4. 讀命令
    5. 潛伏期
    6. 讀資料
    7. 預充電
    8. 預充電等待
    9. 讀結束
  • 並且為了儘可能的滿足建立時間,SDRAM真正的驅動訊號相比SDRAM的控制訊號有-75°的相移,因此為了將SDRAM的輸入資料納入本時鐘域,需要對SDRAM的輸出資料進行打拍操作,因此看起來並不會有一拍的延遲,因為SDRAM的輸出本身就是提前了一些。
    • 75°相移更多的是時序上的考量,本質上是犧牲了保持時間換取建立時間的冗餘
  • 最終SDRAM讀出的資料和其同步訊號輸出至下端的FIFO
    • rd_sdram_data
    • rd_ack

仲裁模組 sdram_arbit

  • SDRAM共有四種操作模式,且有著明確的執行 優先順序要求,其中初始化最高,次之自動重新整理,最後是寫讀操作。在實際使用中不免會遇到多個模組同時需要執行或者當前執行過程中有新的請求需要執行這兩種情況,此時就需要仲裁器來保證SDRAM收到的請求正常被執行。
  • 同時優先順序的判斷在狀態跳轉條件處體現,以及在各個操作模組的使能訊號判斷條件處體現

相關文章