FC2カウンター FPGAの部屋 Vivado HLSの高位合成結果をHDLとして利用する4(register その2、ap_hs)

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vivado HLSの高位合成結果をHDLとして利用する4(register その2、ap_hs)

Vivado HLSの高位合成結果をHDLとして利用する3(register その1)”の続き。

前回は、INTERFACE ディレクティブに register オプションを付けることで、入出力ポートにFFを付けた。これは、IPとして必要な処理を行ったということだ。レイテンシは大きくなるが、動作周波数は上がる可能性がある。

register オプションについては、ツィッターで tu1978 さんと Vengineer さんに教えて頂きました。ありがとうございました。


入出力ポートにFFを付けるというか、組み合わせ回路で無くなると、入力データを入れてから何クロック後に出力データが出てくるかが問題となる。ap_none では、入力データを入れてクロックから正しい出力データが出てくるクロックをカウントして、出力データを受ける必要がある。つまり、自分でクロックをカウントする必要がある。
そこで、制御信号が出ているINTERFACE として、ap_vld と ap_hs がある。ap_vld はvalid 信号のみがあるINTERFACE で、ap_hs は valid 信号と ack 信号があるINTERFACE となっている。

さて、それでは、前回の続きということで、ブロックレベルのINTERFACE を ap_ctrl_none に戻して、PIPELINE ディレクティブを追加してやってみよう。入出力ポートのINTERFACE は ap_none のままだ。
C2HDL_27_150520.png

C Synthesis ボタンをクリックして、高位合成を行った。
C2HDL_35_150521.png

Target の 10 ns に対して、Estimated は 1.72 ns で、前回の時と変わらない。Latency は 2 クロックで、Interval は 1 クロックとなった。

Run C/RTL Cosimulation ボタンをクリックして、C/RTL コシミュレーションを行った。
C2HDL_28_150520.png

Vivado 2015.1 を立ちあげて、例によってTCLコマンドとして、以下のコマンドを入力した。

cd C:/Users/Masaaki/Documents/Vivado_HLS/study/handshake_test/solution1/sim/verilog
current_fileset
open_wave_database handshake_test.wdb
open_wave_config handshake_test.wcfg

C/RTL コシミュレーション波形が表示された。
C2HDL_29_150521.png

上の図の cntin_V と cntout_V 信号を見ると、cntin_V 入力FF にデータがラッチされてから、2 クロック後に cntout_V に出力されている。

次に、PIPELINE ディレクティブはそのままに、 ap_none を valid 信号と ack 信号があるINTERFACE の ap_hs に変更した。
C2HDL_30_150521.png

C Synthesis ボタンをクリックして、高位合成を行った。
C2HDL_31_150521.png

Target の 10 ns に対して、Estimated は 1.72 ns で、Latency は 2 クロックで、Interval は 1 クロックとなった。これは、前回の時と変わらない値だ。

高位合成結果の handshake_test.v を見ると、ポートとして、

cntin_V_ap_vld
cntin_V_ap_ack
cntout_V_ap_vld
cntout_V_ap_ack

が追加されているのが分かる。
C2HDL_32_150521.png

Run C/RTL Cosimulation ボタンをクリックして、C/RTL コシミュレーションを行った。
C2HDL_33_150521.png

Vivado 2015.1 を立ちあげて、例によってTCLコマンドを入力して、C/RTL コシミュレーション波形を表示させた。
C2HDL_34_150521.png

入力も出力も vld と ack が両方共 1 になった時が、データが有効な時だ。入力されてから 2 クロック後に出力されているのが分かる。

これだけでは、vld と ack の関係を確かめることができないので、Vivado 2015.1 でプロジェクトを作製して、高位合成された handshake_test.v をプロジェクトに入れて、テストベンチを作製してシミュレーションしてみた。cntin_V_ap_vld と cntout_V_ap_ack は M系列を使用してランダム値を入力した。
シミュレーションした結果を下に示す。
C2HDL_36_150522.png

上の波形の一部を拡大する。
C2HDL_37_150522.png

vld, ack とデータの関係が良くわかると思う。

最後に、テストベンチ handshake_test_tb.v を貼っておく。

// 
// handshake_test_tb.v
// 2015/05/18
// by marsee
//

`default_nettype none

`timescale 100ps / 1ps

module handshake_test_tb;

    function [7:0] mseqf8_0(input [7:0] din);
        reg xor_result;
        begin
            xor_result = din[7] ^ din[3] ^ din[2] ^ din[1];
            mseqf8_0 = {din[6:0], xor_result};
        end
    endfunction

    function [7:0] mseqf8_1(input [7:0] din);
        reg xor_result;
        begin
            xor_result = din[7] ^ din[5] ^ din[4] ^ din[1];
            mseqf8_1 = {din[6:0], xor_result};
        end
    endfunction

    wire ap_clk;
    wire ap_rst;
    reg [7:0] cntin_V;
    wire cntin_V_ap_vld;
    wire cntin_V_ap_ack;
    wire [7:0] cntout_V;
    wire cntout_V_ap_vld;
    wire cntout_V_ap_ack;
    reg [7:0] random8_0;
    reg [7:0] random8_1;

    handshake_test uut (
        .ap_clk(ap_clk),
        .ap_rst(ap_rst),
        .cntin_V(cntin_V),
        .cntin_V_ap_vld(cntin_V_ap_vld),
        .cntin_V_ap_ack(cntin_V_ap_ack),
        .cntout_V(cntout_V),
        .cntout_V_ap_vld(cntout_V_ap_vld),
        .cntout_V_ap_ack(cntout_V_ap_ack)
    );

    always @(posedge ap_clk) begin
        if (ap_rst) begin
            random8_0 <= 8'd1;
        end else begin
            random8_0 <= mseqf8_0(random8_0);
        end
    end
    always @(posedge ap_clk) begin
        if (ap_rst) begin
            random8_1 <= 8'd1;
        end else begin
            random8_1 <= mseqf8_1(random8_1);
        end
    end

    assign  cntin_V_ap_vld = random8_0[0];
    assign  cntout_V_ap_ack = random8_1[0];

    always @(posedge ap_clk) begin
        if (ap_rst) begin
            cntin_V <= 8'd0;
        end else if (cntin_V_ap_vld & cntin_V_ap_ack) begin
            cntin_V <= cntin_V + 8'd1;
        end
    end

    // ap_clk
    clk_gen #(
        .CLK_PERIOD(100),    // 10.0nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ap_clk_i (
        .clk_out(ap_clk)
    );

    // ap_rst
    reset_gen #(
        .RESET_STATE(1'b1),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(ap_rst)
    );
    
endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out
);
    begin
        initial begin
            reset_out = RESET_STATE;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
        end
    end
endmodule

`default_nettype wire

  1. 2015年05月22日 04:06 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3159-196fb437
この記事にトラックバックする(FC2ブログユーザー)