nao-milkの経験ブログ

25年間の半導体エンジニア経験で知り得た内容を記載したブログです。

FRAMにアクセス (ブロック仕様編)

f:id:nao-milk:20210417123935p:plain

FRAM(強誘電体RAM)をアクセスするためのFPGAをテーマに、FPGAを設計するまでの一連の工程を記載して行こうと思います。

  1. ブロック仕様
  2. Verilog-HDLによるコーディング
  3. シミュレーション(RTLシミュレーション)
  4. Platform DesignerとFPGA Topの作成
  5. 論理合成とインプリメント
  6. NiosIIのコーディング
  7. NiosIIを含めたシミュレーション

 

本記事では、まずはブロックの仕様を記載します。

(後半に、FRAMとインターフェイスを行うSPIブロックのVerilogコードも記載しています。)

※FRAMのモデルは「CY15B102QN」となります。

 (ちょうど、verilogのシミュレーションモデルがあったので。。。)

 

【背景】

昔の案件でFRAMにアクセスする機能が必要で、しかも、アクセス時間を短くしたかったため、バーストアクセスができるIPを探したのですが、見当たらなかったため、verilogで作りました。

その時は、必要な機能に限定して作成しましたが、今回は依頼されたものではないので、私の好きなように作ろうと思います。

ポイントとしては、色々なコマンド(Opcode)が発行でき、且つ ブートローダとして使えそうな機能も考慮してしみました。

 

 

 

概要

FRAM(CY15B102QN)デバイスに対し、リード/ライトを行います。

リード/ライト方法はSPIプロトコルで行います。

 

以下にFRAMデバイスの通信フォーマット例を示します。

 

f:id:nao-milk:20210416131425p:plain

FRAMデバイス リード/ライト例


機能

【CPU I/F (Avalon-MM)】

  1. MasterとSlaveに分かれ、入力信号MST_SLV(0:Master 1:Slave)により選択が可能。
  2. Masterを選択した場合、入力信号PRM_???に従って、FRAMから取得したデータをAvalon-MM(Master側)のブロックから出力します。
  3. Slaveを選択した場合、Avalon-MM(Slave側)でCPUから設定されたレジスタ値に従い、アクセスを行います。
  4. FRAMへの転送が完了すると、割り込みを発生します。尚、割り込みマスクが可能であり、割り込みステータスに"1"を書き込むことでクリアします。(割り込み信号はレベル信号)

 

【FRAMデバイスI/F (SPIプロトコル)】

  1. アクセスバイト数(バーストサイズ)は、レジスタREG_ASC[20:0]又は入力信号PRM_ASC[20:0]で設定が可能。尚、スレーブモード時の最大アクセスバイト数は内蔵RAMサイズに依存します。
  2. 出力(送信)バイト数は、レジスタREG_OTC又は入力信号PRM_OTC[1:0]で設定が可能。
  3. シリアルクロック(出力信号FRAM_SCLK)は内部クロックSYS_SLK[200MHz]を分周して生成し、最大50MHz(SYS_CLKの1/4分周)を出力。
  4. シリアルクロックの周波数は、レジスタREG_DIV[3:0]又は入力信号PRM_DIV[3:0]で設定が可能。
  5. 入力シリアルデータ(入力信号FRAM_MISO)は、SYS_CLK↑に同期してラッチし、レジスタREG_TAK[1:0]又は入力信号PRM_TAK[1:0]により、取り込みタイミングを調整することが可能。

 

ブロック構成

FRAMとI/Fを行うブロック(ブロック名:NML_FRAMIF)の構成図を以下に示します。

※CPUブロックは50MHzで動作します。

※TOPは、FPGAのTOPを示します。

 

f:id:nao-milk:20210416124855p:plain

FRAM I/F ブロック構成

入出力信号一覧

FRAM I/Fブロックの入出力信号の一覧を以下に示します。

f:id:nao-milk:20210417112745p:plain

入出力信号一覧

入出力タイミング

FRAM I/Fブロックの入出力タイミングを以下に示します。

 

FRAM I/F信号

タイミング波形とレジスタ設定値との関係を以下に示します。

f:id:nao-milk:20210416151845p:plain

入出力タイミング (FRAMデバイス用 SPI I/F信号タイミング)

※出力信号FRAM_OUTEは、FRAMへのシリアルデータを出力しない場合はHi-Zしたいことも想定して補足信号としてあります。

 

FRAMデータ取り込みタイミング

シリアルクロックの最大周波数は50MHz[最小周期は20ns]となるため、FFから出力してFRAMへ届くまでの時間(シリアルクロックが届くまでの時間) と 届いてからFRAM I/Fブロックの入力FFまでの届く時間の合計が20ns以上の場合もあると考え、基準取り込みポイントから最大3クロック遅延させて取り込むことが可能です。

以下に経路遅延イメージを示します。また、取り込みタイミング図も示します。

f:id:nao-milk:20210416154102p:plain

FRAMデータ取得までの経路遅延イメージ

 

f:id:nao-milk:20210416151959p:plain

入出力タイミング (FRAMデバイス用 SPI取り込みタイミング)

 

Avalon-MM(Slave側)

リード時は、出力データを準備するためにWait信号(出力信号SAV_WIT)をアサートします。

また、レジスタと内蔵RAMをリードする場合でWait信号のアサート期間が変わります。

 

f:id:nao-milk:20210416154722p:plain

入出力タイミング(Avalon-MM Slave)

 

Avalon-MM(Master側)

wait信号(入力信号MAV_WIT)のアサート期間中は出力を保持します。

f:id:nao-milk:20210416155022p:plain

入出力タイミング(Avalon-MM Master)

 

動作説明

FRAM I/Fブロックの動作に関して説明します。

 

マスタモード(入力信号MST_SLV=0)

マスタモードは入力信号による制御を可能とし、FRAMからの取得したデータをAvalon-MM Masterとしてライト制御します。

尚、このモードはFRAMのリード系コマンド(READ,SSRDなど)のみを想定しています。

  1. 入力信号PRM_DIV、PRM_POL、PRM_TAK、PRM_ACS、PRM_OTC、PRM_STA、PRM_CMD、PRM_ADDを設定します。
  2. PRM_ENBを"0"から"1"に設定します。これにより、動作を開始します。
  3. FRAMへコマンド(PRM_CMDの内容)発行を行い、PRM_OTC[1:0]に応じてアドレス発行(PRM_ADDの内容)を行います。
  4. FRAMから取得したシリアルデータを8bitパラレルデータに変換し、FIFOに格納します。
  5. FIFOがNot Emptyになると、Avalon-MM I/F(Master側)がFIFOをリードし、Avalon-MMライト動作を行います。尚、ライトアドレスは入力信号PRM_STAを加算して出力します。
  6. FRAMへのアクセスが完了すると、出力信号CPU_IRQをアサートします。尚、PRM_CLRを"1"にすることでクリアします。

 ※動作中は、出力信号MON_ENBが"1"になります。

 

スレーブモード(入力信号MST_SLV=1)

CPUからのレジスタ設定に応じて動作を行い、内蔵RAMに格納されたデータをFRAMへ出力し、FRAMから出力したデータを内蔵RAMに格納します。

従って、1回のFRAMへのリード又はライトはRAMサイズに依存します。

(内蔵RAMのサイズを大きくすることで、アクセスバイト数は大きくできます)

尚、内蔵RAMサイズは4096バイトとしています。

  1. レジスタに初期設定を行います。(REG_DIV、REG_POL、REG_TAK、REG_ACS、REG_OTC)
  2. FRAMへ出力したいデータをCPUから内蔵RAMへ格納します。(コマンドやアドレス、ライトデータなど)
  3. 処理イネーブルを"1"にします(レジスタREG_ENB)。これにより、動作を開始します。
  4. FRAMへの出力時は内蔵RAMからデータを取得してFRAMへ出力します。またFRAMから取得したデータは、8bitのパラレルデータに変換してRAMへ保存します。
  5. FRAMへのアクセスが完了すると、出力信号CPU_IRQをアサートします。尚、レジスタREG_ENBも自動的に"0"になるため、割り込みマスクを行い、レジスタREG_ENBの状態をポーリングすることにより、動作中か否かを知ることが可能です。
  6. CPUがFRAMから取得したデータを内蔵RAMから読み出す。(レジスタREG_BDT)

 

内蔵RAMとFRAMアクセスの関係

スレーブモード時の内蔵RAMとFRAM SPI通信のデータ構成の関係を以下に示します。

尚、FRAMアクセスの最初はCommand(Opcode)の出力となります。

 

f:id:nao-milk:20210416171505p:plain

内蔵RAMとFRAM SPI通信との関係

 ※Command= "SSWR"と"SSRD"は特殊セクタアクセスとなり、256バイト以上のアクセスを行った場合は、特殊セクタの先頭アドレスに戻るため、グレーにしています。

 

マスタモード時は、内蔵RAMを介さず、取得したデータをそのままAvalon-MM Master側でFRAM I/Fブロック外部にライトします。

 

レジスタ詳細

FRAM I/Fのレジスタ詳細を以下に示します。

f:id:nao-milk:20210417200626p:plain


f:id:nao-milk:20210416175005p:plain

f:id:nao-milk:20210416175103p:plain

 

f:id:nao-milk:20210416175203p:plain

 設定例

FRAM SPI通信のバイト数設定例を以下に示します。

 スレーブモード

f:id:nao-milk:20210416175515p:plain

設定例 (スレーブモード)

 マスタモード

f:id:nao-milk:20210416175634p:plain

設定例 (マスタモード)

 

SPI I/Fのソースコード(記述:verilog-HDL)

FRAM I/Fの内部ブロックSPI I/F(モジュール名:NML_FRAMIF_SPI)のソースコードを以下に示します。

 

入出力信号の宣言と処理イネーブルがアサートされ内蔵RAMから最初のデータ(Command)をリードするための期間を生成します。

f:id:nao-milk:20210416180839p:plain

 

SPI通信期間を示すasc_enblを生成し、またアクセス終了後のWait期間を生成します。

f:id:nao-milk:20210416181007p:plain

 

シリアルクロックの生成、bitカウンタとByteカウンタを生成します。

尚、Byteカウンタは、CY16B102以上のデバイスでも対応できるよう、余分にbit幅をとっています。

f:id:nao-milk:20210416181057p:plain

 

SPI通信の出力と入力を示すフラグを生成し、内蔵RAMのアクセス制御を行います。

f:id:nao-milk:20210416181145p:plain

 

ベースとなるFRAM制御信号(base_*)を生成し、FFでラッチして出力します。

これにより、FPGAの出力FFを使用します。

f:id:nao-milk:20210416181231p:plain

 

FRAMからの入力シリアルデータラッチ(in_miso)し、基準取り込みタイミング信号を生成します。(入力FFを使用します)

f:id:nao-milk:20210416181400p:plain

 

基準取り込みタイミングを遅延します。

f:id:nao-milk:20210416181456p:plain

 

レジスタREG_TAKの設定値に応じて、取り込みタイミングを選択し、シリアルデータをパラレルデータに変換します。

変換したデータは、上記BUF_WDTでラッチします。

f:id:nao-milk:20210416181540p:plain

 

FRAMアクセス完了後、レジスタREG_ENBを"0"にするための信号REG_FINを生成します。

尚、この信号は後段ブロックでCPU_CLK(50MHz)で使用するため、High幅をSYS_CLKの8クロック分にしています。(CPU_CLKの2クロック分)

f:id:nao-milk:20210416181619p:plain

 

使用ツール

  • 言語:verilog-HDL(ハードウェア用)、C言語(ソフトウェア用[NiosII用])
  • シミュレータ:ModelSim Intel FPGA Starter Edition 10.5b
  • 論理合成/インプリメント:Quartus Prime 18.1 Lite Edition

 

最後に

マスタモードとスレーブモードに分けたのは、試作を意図しています。

FRAMへのライトとリードも、マスタモードで行うことも可能ですが、リードだけに止めました。

機能試作や基板試作時は、スレーブモードを使ってFRAMに対して色々なコマンドを発行して、機能検討や基板変更を考えると思います。

その為、なるべく自由度が高いと思われるスレーブモードを入れました。