公開日:2022/02/05
title.png

19th Season


#19-7 SDRAMを使って見よう(1)

 FPGAボード(Sipeed Lichee Tang Primer)には、SDRAMが搭載されていることが1つのセールスポイントになっていました。
 ここまで、FPGAボードを使って、オリジナル16ビットCPUコアMoscoviumマイコンを作って来たのだけど、FPGAボードに搭載されていた様々なマクロセル(RAM、ROM、FIFO、AD変換器、PLL、等)を使って来て、「そろそろSDRAMにもアクセスしてみようか」と、思い立ちました。

 Moscoviumマイコンのデザインデータは、以下リンクよりダウンロードして使うことが出来ます。

btn_moscovium.png


 さて、SDRAMですか……。FPGAボードのデータシートを見ても、必要な情報が全く見つからなくて、どう使ったら良いものか?まずは調査からスタートです。

そもそも、SDRAMとは?

 SDRAM(Synchronous Dynamic Random Access Memory)は、クロックに同期(Synchronous)してアクセス可能なDRAMの事です。ご存知、PCやスマホなどのメインメモリとして使われているメモリです。
 PC等だと、DDR(Double Data Rate)-SDRAMが主流です。クロックの立ち上がり/立ち下がりエッジの2つのタイミングで出力データが変化する、高速メモリです。敢えてDDRの付かないSDRAMは、恐らくSDR(Single Data Rate)タイプと思われます。

ダイナミック?

 D=Dynamicに対義する言葉はStaticです。SRAMとか言いますよね?そのS=Staticです。
 普通のSRAMは、電源を切ったら記憶していたデータは消えてしまう揮発性(Volatile)ですが、電源さえ供給している限り、一度記憶したデータは消えません。
 しかし、DRAM(Dynamic RAM)と言うやつは、電源を供給していても、時間が経つと記憶していたデータが消えてしまうRAMなのです。ここがStaticとDynamicを隔てる大きな分岐点です。

 DRAMのメモリセルは、1トランジスタ+1容量(コンデンサ)で構成されています。
 SRAMのメモリセルは、6トランジスタですので、DRAMの方がメモリセルが小さく、同じ面積の中に沢山のメモリセルを配置することが出来て、大容量化し易いことが特長です。

データの書き込み

 SDRAMへのデータ書き込みは、コンデンサに電荷を充電(チャージ)するか、放電(ディスチャージ)するか?で、0/1のデータを表現しています。
 どのコンデンサに充放電するのか選択するためのスイッチとして、トランジスタが1個、コンデンサに対となって配置されており、この2素子が1個のメモリセルを構成します。

 ところが、半導体素子にはリーク電流パスが存在するので、充電したコンデンサから電荷が抜けてしまったり、逆に放電したコンデンサに電荷が蓄積されてしまったりして、時間が経つと記憶したデータは消えてしまいます。
 SDRAMでは、時間経過によってデータが消えてしまう前に、一度読み出して再書き込みする手順が必要となります。

  SDRAMは、一定の間隔で全メモリセルの読み出し/再書き込みを実行しなければならない。
    → この作業のことをリフレッシュと呼ぶ。

 リフレッシュは、使用者が明示的にリフレッシュコマンドを発行しないと実行されません。リフレッシュについては後の節で解説します。

データの読み出し

 データの読み出しは、コンデンサが充電されているかどうか?を知ることと等価で、それを知ろうとすると、コンデンサの電荷が失われてしまいます。つまり、データを読み出すと、メモリセルのデータは消えてしまうのです。

  SDRAMは、データを読み出すと記憶していたデータは消えてしまう。
    → 破壊読み出し。

 SDRAMはデータを読み出すと、再び同じデータを書き戻すという作業を、人知れず裏側で実行しています。この作業はSDRAM内部で自動的に実行されるので、使用者が意識する必要はありません。

アドレス端子数

 例えば、8Mバイト(32ビット幅)のSDRAMでは、本来、アドレス端子として21本が必要です。
 SDRAMは、行(ロウ、row)アドレスと列(カラム、column)アドレスと言う二次元のマトリクス方式でアクセス対象アドレスを特定し、行と列アドレスを時分割でマルチプレクスしています。

 例として、行アドレスが2,048個(アドレス端子は11本)、列アドレスが256個(同8本)のマトリクスとして、そのマトリクスが4バンク(同2本)ある場合を考えます。メモリ空間は、32ビットデータ×2,048ロウ×256カラム×4バンク=8Mバイトです。
 行アドレスと列アドレスは同じaddr[10:0]端子に割り当てられる(マルチプレクス)ので、バンクアドレス端子ba[1:0]と合わせて合計13本のアドレス端子となります。

 21本必要だったアドレス信号線が、13本に減りました。こうすることで、プリント基板上を這い回るアドレスバスの信号線数を減らすことができ、実装面積の低減等に寄与するのです。

コマンド

 SDRAMに動作を指示するには、コマンドを使います。コマンド指定に使うのは、RAS#,CAS#,WE#の3本のストローブ信号線です(#は負論理の意味。0でアサート、1でネゲート)。下表に一般的なコマンドを示しておきます。

command RAS# CAS# WE#
No operation NOP 1 1 1
Burst stop STP 1 1 0
Read RDC 1 0 1
Write WRC 1 0 0
Bank active ACT 0 1 1
Bank precharge PRE 0 1 0
Auto refresh CBR 0 0 1
Mode register set MRS 0 0 0

 信号線3本の組み合わせでは高々8通りのコマンドしか指定できないため、コマンド発行時のアドレス最上位ビット(A10等)を使って、追加のコマンド動作が割り当たっていたりします。詳しくはSDRAMのデータシートを参照してください。

アクセスプロトコル

 SDRAMにアクセスするためには、色々と細かいお作法(プロトコル)が有って、プロトコルに従った方法でアクセスしないと、言う事を聞いてくれません。
 それはSDRAMに関わらず、どんな機器も同じなのですが、SDRAMの場合、制御方法その物の単純さに比べて、その裏に隠れたアクセスタイミング規定が難解で複雑なので、慣れるまでは大変です。以下にSDRAMとSRAMマクロへのアクセス例を示して説明します。

a197_accsdram.png
a197_accsram.png

 アクセスは速いけど小容量なSRAMに対して、大容量だけど遅いのがSDRAMですね。アクセスの遅さをカバーするためのクロック周波数高速化や、バーストアクセスなどがSDRAMの特徴の一つとなります。

タイミング規定

 前節のアクセスタイミング例を再掲(下図)して、SDRAMのタイミング規定について解説します。

a197_accsdram.png

 SDRAMには、色々なタイミング規定があって、これを満たして使わないと、正常動作してくれません。以下、上図に記載のあるタイミング規定について解説します。

 tRCDやtRAS等のタイミング規定は、例えば「54ns」の様に実時間で規定されます。従って、クロック周波数次第で、待ち時間のサイクル数が変わることになります。……「200MHzなら11サイクル待ち、100MHzなら6サイクル待ち」等。

 他にも色々なタイミング規定があるので、各自、使用するSDRAMのデータシートで確認してください。

リフレッシュ

 時間の経過によって記憶したデータが消えて行くSDRAMは、定期的に読み出し/再書き込みを実行する必要があり、この作業をリフレッシュと言います。

 リフレッシュのための読み出し/再書き込みは、CPUが面倒見る必要は無く、オートリフレッシュCBRコマンドをSDRAMに発行すると、SDRAMが内部で自動的に読み出し/再書き込みを実行してくれます。
 一般的なSDRAMでは、「64msの間に4,096回のオートリフレッシュCBRコマンド」を実行するように規定されています。これを遵守しないと、知らない内にデータが消えてしまいます!

 普通は、64ms/4,096回≒15.6μs毎にCBRコマンドを実行する様に制御するのが良いでしょう。

※MAX規定なので、上の時間にマージンを取って、少し短い間隔でリフレッシュを実行すべきかもしれません。
※蛇足ですが、自動車向けのSDRAMでは、リフレッシュサイクルが16ms/4,096回の規定となっている物を見かけました。リフレッシュの負荷率が×4倍に増加します。自動車用途だと民生用途と比べて使用温度の上限が125℃と高いので、リーク電流が流れやすくなり、リフレッシュ間隔が短くなってしまうのでしょう。


 15.6μs毎に割り込みをかけ、一々CPUにCBRコマンドを実行させるのはバカなので、一定時間毎にCBRコマンドを実行するのは、通常SDRAMコントローラが担当します。

 SDRAMのプロトコルでCBRコマンドを実行するためには、全バンクがアイドル状態になっている必要があり、CBRコマンドの実行からtRC時間の間は、SDRAM内部でリフレッシュ処理(読み出し/再書き込み)が実行されているので、次のコマンドを実行できません。
 通常のデータリード/ライトサイクルの最後にPREコマンドを実行してプリチャージ→アイドル状態へ遷移している場合には、すぐさまCBRコマンドを実行できます。リード/ライトサイクルの後でPREコマンドを実行せず、アクティブ状態に留まる制御とする場合には、CBRコマンドの実行前に全バンクをプリチャージするPREコマンドの実行と、tRP時間の経過を待つ必要があります。

FPGAボードのSDRAM調査

 一般的なSDRAMについて調査(おさらい)が終わったところで、肝心なFPGAボード(Anlogic社EG4S20BG256チップ)に搭載されたSDRAMの情報を調査して行きましょう。

 Anlogic社TD IDE等のデータシートにちらほらとSDRAMの記述があるのですが、全く不足です。制御に必要な情報が見つかりませんでした。以下の様にインターネットで探してみました。

  FPGAチップ(EG4S20BG256)のSDRAMについて検索する(別ウインドウが開きます)

 すると、FPGAボードの販売元Sipeed社HPでは配布されていなかったAnlogic社のドキュメントを見つけました。そのドキュメントによると、EG4S20BG256に搭載されたSDRAMは以下の通りです。

 SDRAMの型番が判ったので、今度は型番でデータシートを検索してみました。

  EM638325のデータシートを検索する(別ウインドウが開きます)

 EM638325は、台湾EtronTech社のSDRAMだったみたいです。

  EM638325の概要:

 以下表に、EM638325のAC特性規定📏をまとめておきます。

A.C. parameter symbol min max unit
Row cycle time tRC 55   ns
Row activate to row activate delay tRRD 10   ns
RAS# to CAS# delay tRCD 18   ns
Precharge to refresh/row activate command tRP 15   ns
Row activate to precharge time tRAS 35 100,000 ns
Clock cycle time (CL=3) tCK3 5   ns
Access time from CLK (CL=3) tAC3   4.5 ns
Data output hold time tOH 2   ns
Clock high time tCH 2   ns
Clock low time tCL 2   ns
Data/Address/Control Input set-up time tIS 1.5   ns
Data/Address/Control Input hold time tIH 1   ns
Data output low impedance tLZ 1   ns
Data output high impedance (CL=3) tHZ3   4.5 ns
Write recovery time tWR 2   cycle
CAS# to CAS# delay time tCCD 2   cycle
Mode Register Set cycle time tMRS 2   cycle
CAS# Latency (Anlogic document) CL 3   cycle

 これでようやく、FPGAボードのSDRAMを制御する情報が出そろいました。


 TD IDEのIP Generatorで、以下図の様にSDRAMマクロを生成して使います。

a197_sdrmcr.png

 特に変更可能なパラメータは無いので、モジュール名だけ指定したらOKボタンを押して終了します。

 なお、生成されたVerilogファイルには、単にEG_PHY_SDRAMと言う名前のマクロセルが1個インスタンスされているだけです。TD IDEのセルライブラリを参照してみると、EG_PHY_SDRAMマクロセルの中身は空っぽでした。シミュレーションモデルが入っていないので、SDRAMにアクセスする様なシミュレーションは、実行してもSDRAMから何の反応も返ってきません。
 SDRAMメーカからSDRAMのVerilogシミュレーションモデルが提供されている場合があるので、どうしてもシミュレーションする必要が生じた場合は、そういったモデルを活用してください。


 今回は、FPGAボード搭載のSDRAMについて調査しただけで終わってしまいました。まず、「敵を知ること」が攻略の第一段階です。次回、詳細設計を進めて行きたいと思います。


btn_arduino.png

btn_prev.png btn_next.png

home