Ryuz's tech blog

FPGAなどの技術ブログ

スキッドバッファ再考

はじめに

私が FPGA に興味を持ち Verilog を勉強し始めたころこんなブログを書いていました。

遥か昔、「モジュールは全部FF出ししないとだめよ」という事を言っていた先輩の言葉を真に受けて、何とかして ready も FF 出ししようと、無い知恵を絞って作っていたわけです。

今になって、それはスキッドバッファという名前がついていることを X で知ったのですが、「そもそも、どのぐらい効果があるのか?」という疑問から少し実験を行ってみました。

やった実験

スキッドバッファを入れずに、下記のような論理を何段も積み上げていくとどれぐらい性能が落ちていくのでしょうか?

今回は下記のようなデータが流れてきたら足し込むというアキュミュレータを作成して、スキッドバッファ無しでどんどん多段に積み上げていく、という実験をしてみました。

// パイプライン用アキュミュレータ
module acc_pipe
        #(
            parameter   int     DATA_BITS = 32                          ,
            parameter   type    data_t   = logic    [DATA_BITS-1:0] 
        )
        (
            input   var logic   reset   ,   // リセット
            input   var logic   clk     ,   // クロック
            input   var logic   cke     ,   // クロックイネーブル

            // input
            input   var data_t  s_data  ,
            input   var logic   s_valid ,
            output  var logic   s_ready ,

            // output
            output  var data_t  m_data  ,
            output  var logic   m_valid ,
            input   var logic   m_ready 
        );

    // リタイミングを抑止
    (* DONT_TOUCH = "yes" *)    data_t  reg_data;
    (* DONT_TOUCH = "yes" *)    logic   reg_valid;
    always_ff @( posedge clk ) begin
        if ( reset ) begin
            reg_data  <= '0;
            reg_valid <= '0;
        end
        else if ( cke ) begin
            if ( m_ready ) begin
                reg_valid <= 0;  // output 出来たら倒す
            end            
            if ( s_valid && s_ready ) begin
                reg_data  <= reg_data + s_data; // input があれば積算
                reg_valid <= 1'b1;
            end
        end
    end

    assign s_ready = !m_valid || m_ready;

    assign m_data  = reg_data;
    assign m_valid = reg_valid;

endmodule

幸い このブログを書いた時に最大周波数の見積もりを調べていたので、その方法で効果を調べてみました。 Vivado で一部のモジュールだけの合成評価を行う

実験結果

KV260 向けの合成結果です。

pipelines Period(ns) Frequency(MHz) WNS(ns) Estimated Minimum Period(ns) Estimated Maximum Frequency(ns)
1 2 500 0.484 1.516 659.631
2 2 500 0.434 1.566 638.57
3 2 500 0.339 1.661 602.047
4 2 500 0.301 1.699 588.582
5 2 500 0.17 1.83 546.448
6 2 500 0.155 1.845 542.005
7 2 500 0.195 1.805 554.017
8 2 500 0.202 1.798 556.174
9 2 500 0.144 1.856 538.793
10 2 500 0.126 1.874 533.618
11 2 500 0.068 1.932 517.598
12 2 500 0.081 1.919 521.105
13 2 500 0.009 1.991 502.26
14 2 500 0.006 1.994 501.505
15 2 500 0.028 1.972 507.099
16 2 500 0.004 1.996 501.002
17 2 500 0.005 1.995 501.253
18 2 500 0.007 1.993 501.756
19 2 500 -0.093 2.093 477.783
20 2 500 -0.202 2.202 454.133
21 2 500 -0.025 2.025 493.827
22 2 500 -0.165 2.165 461.894
23 2 500 -0.305 2.305 433.839
24 2 500 -0.197 2.197 455.166
25 2 500 -0.159 2.159 463.177
26 2 500 -0.285 2.285 437.637
27 2 500 -0.293 2.293 436.11
28 2 500 -0.719 2.719 367.782
29 2 500 -0.376 2.376 420.875
30 2 500 -0.325 2.325 430.108
31 2 500 -0.429 2.429 411.692
32 2 500 -0.678 2.678 373.413
33 2 500 -0.494 2.494 400.962
34 2 500 -0.567 2.567 389.56
35 2 500 -0.679 2.679 373.274
36 2 500 -0.805 2.805 356.506
37 2 500 -1.074 3.074 325.309
38 2 500 -0.897 2.897 345.185
39 2 500 -1.18 3.18 314.465
40 2 500 -0.661 2.661 375.799
41 2 500 -1.048 3.048 328.084
42 2 500 -1.042 3.042 328.731
43 2 500 -0.957 2.957 338.181
44 2 500 -1.01 3.01 332.226
45 2 500 -1.152 3.152 317.259
46 2 500 -1.084 3.084 324.254
47 2 500 -1.143 3.143 318.167
48 2 500 -1.295 3.295 303.49
49 2 500 -1.187 3.187 313.775
50 2 500 -1.728 3.728 268.24
51 2 500 -1.352 3.352 298.329
52 2 500 -1.368 3.368 296.912
53 2 500 -1.31 3.31 302.115
54 2 500 -1.429 3.429 291.63
55 2 500 -1.301 3.301 302.939
56 2 500 -1.476 3.476 287.687
57 2 500 -1.331 3.331 300.21
58 2 500 -1.686 3.686 271.297
59 2 500 -1.526 3.526 283.607
60 2 500 -1.942 3.942 253.678
61 2 500 -1.694 3.694 270.709
62 2 500 -1.821 3.821 261.712
63 2 500 -2.037 4.037 247.709
64 2 500 -2.081 4.081 245.038

おわりに

どのぐらいの周波数を目指すかにもよるのですが、案外 300MHz ぐらいで動かす程度のことを考える際は、そこまで神経質にならなくても案外何とかなるのかもしれません。 もっとも実際の回路ではもっと複雑な事は起こるとは思いますが、一つの参考として。