ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

FPGA 開発 - 反省


最近は FPGA を弄ってていろいろしてみてるわけですが、
いろいろハマったので反省点をまとめ。

マルチクロックなんて二度とやらない


メインクロック 50MHz があって、ここから分周して 1MHz のクロックがあるわけです。

reg  [7:0] clk_cnt;
wire       low_clk;

assign low_clk = ( clk_cnt < 25 );

always @ ( posedge CLK, negedge RST_X ) begin
  if( ~RST_X ) begin
    clk_cnt <= 8'd0;
  end else begin
    if( clk_cnt >= 8'd49 ) begin
      clk_cnt <= 8'd0;
    end else begin
      clk_cnt <= clk_cnt + 8'd1;
    end
  end
end

で、遅い方のクロックで外部の素子を駆動するために

always @ ( posedge low_clk, negedge RST_X ) begin
  if( ~RST_X ) begin
    // : snip
  end else begin
    // : snip
  end
end

こうやって low_clk を FF の CLK として供給したら、
中身に何もない if 文(本来何の意味もない)の有無でタイミングが変わったり
いろいろとよくわからない怪しい現象に悩まされました。


ちょっと面倒だけども同期微分を使って立ち上がり検出をする…
以下のようにするとナイス。

reg b4clk;
wire pedge;

assign pedge = ( ~b4clk && low_clk );

always @ ( posedge CLK, negedge RST_X ) begin
  if( ~RST_X ) begin
    b4clk <= 1'b0;
  end else begin
    b4clk <= low_clk;
  end
end

always @ ( posedge CLK, negedge RST_X ) begin
  if( ~RST_X ) begin
    // : snip
  end else if( pedge ) begin
    // : snip
  end
end

ちょっと面倒なんだよねーと思ってマルチクロックの回路にしたのが
決定的に裏目に出たパターン。もう二度としません。

できる限り同期回路で設計


「1clk余分にかかるの無駄だよね!」と思って非同期SRAMを使ってみました。


うん、おかげでえらい目にあったよ。
1clk の浪費で確実に動くならその方がいいよね…


「タイミングチャート見ればOKOK」そう思っていた時期が私にもありました。

ACスペックはきちんと確認しよう


FF のサンプリングの都合などで、tsuやtcoなどが決まってるので、
きちんとそれを満たすようにタイミングの設計をする必要があります。


たとえば相手の素子が「クロックの立ち上がりで読み込む」ならば、
こっちは「クロックの立ち下がりで状態を遷移させる」ように。


相手が「立ち上がり」で読むのにこっちも「立ち上がり」でバスのレベルが変わると
「どっち!?」ってなってしまいます...

ACスペックは余裕をもって見積もろう


例の非同期SRAM。アドレスバスの遷移からIOバスへの出力までの遅延が15ns。
逆数は 66MHz。なんだ、50MHz で駆動するなら余裕余裕。


…と思ったら甘かった。
FPGA から出力する tco、入力する tsu だけで 10ns 程度になるので25ns≒40MHz が限界。
結局 FF を挿入して読み込みに 2clk かけることで 50MHz で動作させることに。


あれ、はじめからおとなしく50MHz動作の同期SRAM使った方が速かったんじゃね??


ちなみに書き込みはほかの信号も一斉に遅延するので 66MHz まで動きます。