« 組み込み屋の為のVerilog入門 | トップページ | FPGAはチューリングマシンか? »

2011年12月11日 (日)

組み込み屋の為のVerilog入門 その2

組み込み屋は必要とあれば、もともとGPIOなどポート制御でなんでもやってしまう。
そういった意味で、クロック単位で自在に入出力を制御するコードをかけてしまうFPGAのRTL設計は非常に強力なツールだ。
そもそもVerilogなどの言語もチューリング完全な言語であって、非ノイマン型にもなりうる反面、よく整理して使えば、ノイマン型以上に整理された体系が作れる。
# というか、意外にに自由度はある。

ソフトウェアでの制御に慣れてしまった人間にとって、同じノリで書くと嵌りやすい要素が、パイプライン制御である。
今回はそれを取り上げる。よくバケツリレーに例えられる制御であり、演算中に次のDMAを複数発行するなど組み込み屋にはそれなりに概念はあたまにあったりするが、クロックサイクル単位でのパイプラインにはそれなりに嵌り余地がある。
特にしょうも無いバグを作りこんでしまうのがハンドシェークである。私は嵌りまくった。が、こにはある程度落ち着くべき定型的なテクニックが存在するので紹介したい。

個人的にはXILINXが最近採用している、ARM社のAMBAバス仕様の1つである、AXIバス仕様などででてくる、valid と ready の組み合わせによるハンドシェークを好んで使っている。Jellyの各種ライブラリも極力この方式に統一の方向である。
  valid と ready が同時に1のときにクロックエッジが来ると処理が受け付けられるというものである。スレーブ側は処理を受け付けられないときは、マスターに対して ready を落としてやればいいという単純なハンドシェーク機構である。

パイプラインの処理はあくまで1サイクルで実施する処理の単位である。ここを混同して複数のステージの記述を混ぜて考えないようにするのが最初のうちは重要と思う(検証時に何とかしつつ、まざったコードを書いて嵌るのを私は何度もやりました)。

データをスレーブポートから入力して、マスターポートにデータを吐くという一般的なモデルを考える。

module hoge(
   input wire reset,
   input wire clk,

   // スレーブポート(入力)
   input wire [31:0]  s_data,
   input wire          s_valid,
   output wire       s_ready,

   // マスターポート(出力)
   output reg  [31:0]  s_data,
   output reg           s_valid,
    input wire           s_ready
);

always @(posedge clk) begin
  if ( reset ) begin
    m_valid <= 1'b0;
    m_data <= {32{1'bx}};
  end
  else begin
    if ( s_ready ) begin  // cke
      m_valid <= s_valid;
      m_data <= hoge(s_data);  // s_dataを演算した何か
    end
  end
end

assign s_ready = m_ready | !m_valid;   // m_ready のみでも可

endmodule

こんな感じである。
FPGAのフリップフロップには、通常 CKE 端子(つまりは現状値維持=インターロック)があり、これが s_ready にあたる。つまり、送り先にデータが遅れなければ有無を言わさず一括でそのステージのそのサイクルの処理を止めてしまう。
XILINXな話になるが、BRAMのENや、DSPのCEも同じ意味であり、ALTERAなどでも同じ意
味合いの端子はあり、インターロック機構ののリソース消費は極めて少ない。
最後の s_ready に対する assign 文の式は m_readyだけでも構わない。この場合、受け側がBUSYだと、パイプラインがすべて止まる。上のコードは一応、バブル(空いているステージ)があればそこを詰めていくような制御である。
  ただし注意点として、確かAXIバスなどは、validを受けてからreadyを上げるなどの処理を許容しているため、そのようなケースでは !m_validを省略するとデッドロックに陥る恐れもある。使う場合は受け側の仕様を良く理解しておくことも重要だ。

データの流れる方向に関しては、FFを介して1サイクルに1ステージ進行するだけだが、ハンドシェーク信号が、逆方向に伝播するのがソフトから転向組みの初心者を混乱させがちだ。そこでここはreadyだけassign記述として0サイクル伝播として混乱の余地を排除する。

難を言えばパイプラインが複雑に深くなった場合に、ready系の組み合わせ回路がタイミング収束しにくくなることだが、必要に応じてFIFOを挟めばすむ。もっとシンプルにサイズ1のFIFOをFFだけで構成して挟むだけでも良い。タイミング収束のために挟み込むFFを非常に秩序だって管理することが可能となる。

  人間が一度に頭にいれて考えることのできるスコープは狭い。なので分割して考えられるコーディングをするのがソフト/ハードともに重要なことである。
  ソフトウェアでマルチスレッドが難しいのと同様に、RTLは並列要素が多くて混乱する。格ステージで、そのステージのことだけ考えて書けるように、余計な要素は極力テンプレートかするのが余計なトラブルを生まず、効率よく開発できるコツである。
  おそらくセルベースのLSIを設計するのと違い、FPGA開発のそれはソフトウェアにかなり近く、求められるのはコードの効率以上に生産性に移っていくであろうと私は考える。

 

« 組み込み屋の為のVerilog入門 | トップページ | FPGAはチューリングマシンか? »

FPGA」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/560384/53461106

この記事へのトラックバック一覧です: 組み込み屋の為のVerilog入門 その2:

« 組み込み屋の為のVerilog入門 | トップページ | FPGAはチューリングマシンか? »