前回の続きで、もう少し掘り下げて見る。
まず基本のパイプライン構成だが、前回の構成でパイプラインを深くしていくと、下図のようにREADYの論理がどんどん深くなっていき、タイミングクローズしにくくなってくる。
まずはこの問題のシンプルな解決策だが、READYを下図のように簡略化してしまうことだ。
このように簡略化してしまうと、最終段がBUSYだと途中のパイプラインが空(いわゆるバブルがある状態)でも全体が止まってしまうというちょっともったいないことが起こるが、多くの場合あまり問題にならない。
もうひとつの解決方法が、途中のREADYにFFを打つという方法である。
以下にその例を示す。
=============================================== // READY に FF挿入 module insert_ff_ready ( // system input wire clk, input wire reset, // slave port input wire [7:0] s_data, input wire s_valid, reg wire s_ready, // master port output wire [7:0] m_data, output wire m_valid, input wire m_ready ); reg [7:0] t_data; reg t_valid; always @(posedge clk) begin if ( reset ) begin s_ready <= 1'b1; t_data <= 8'bxx; t_valid <= 1'b0; end else begin s_ready <= m_ready | ~t_valid; if ( m_ready ) begin t_data <= 8'bxx; t_valid <= 1'b0; end else begin if ( s_ready ) begin t_data <= s_data; t_valid <= s_valid; end end end assign m_data = t_valid ? t_data : s_data; assign m_valid = t_valid | s_valid; end endmodule ===============================================
READYにFFを打つ場合に解決しなければならないのは、READYが落ちるのに1サイクルかかる為、前段のパイプラインストールが1サイクル遅れることである。
対処方法としてはパイプライン1段分のテンポラリのレジスタを設けて、止め切れなかった分をそこに一時的にバッファリングするというものである。(追記:スキッドバッファと呼ぶそうです)
ちなみにこれも絵を描いて見たがこのあたりになるとVerilogソースのほうが何がしたいのかわかりやすい。
ちなみにこのソースや図はなんら検証していないので、間違いやバグがあっても責任は持てませんので悪しからずご了承ください(ご指摘は歓迎です)。
コメント