FC2カウンター FPGAの部屋 Vivado HLS 2014.4 の高位合成テスト16(ラプラシアンフィルタ11、Clock Period = 4 ns の場合のインプリメント)
FC2ブログ

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

FPGAの部屋

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

Vivado HLS 2014.4 の高位合成テスト16(ラプラシアンフィルタ11、Clock Period = 4 ns の場合のインプリメント)

Vivado HLS 2014.4 の高位合成テスト15(ラプラシアンフィルタ10、Clock Period = 4 ns の場合のシミュレーション)”の続き。

前回は、Vivado HLS 2014.4 でラプラシアンフィルタのCソースから高位合成したVerilog HDLをシミュレーションした。
今回は、そのラプラシアンフィルタの Verilog HDLファイルをVivado 2014.4でインプリメントしてみた。
Clock Period = 4 ns の場合、つまり、Latency = 7 クロックの条件でラプラシアンフィルタのCソースからVivado HLS 2014.4 で高位合成されたVerilog HDLファイルをVivado 2014.4でインプリメントして、250MHzつまり 4 ns の遅延で実際に動作するようにインプリメントできるかを確認する。Vivado 2014.4のプロジェクトの使用するFPGAはZYBOに使用されている xc7z010clg400-1 とする。

前回の時に、Vivado 2014.4 のプロジェクトは作ってある。但し、ラプラシアンフィルタの Verilog HDLファイルの laplacian_filter.v は32ビット幅のデータ入力が 9 個もあるので、ZYBO の入出力ピンの総数を上まってしまう。そのために、32ビット1個の入力から、9タップのシフトレジスタを置いて、それぞれのタップからラプラシアンフィルタのデータ入力をすることにした。それに、高位合成したHDLファイルはデータ入力もデータ出力もFF出力ではなく、組み合わせ回路出力になっている。そこですべての入力、出力をFFでラッチすることにした。(一部の制御出力はFF出力があった)これらの機能をまとめて、laplacian_filter_top.v を作製した。なお、動作周波数が250MHzと高速だし、後で400MHzくらいでもやってみたいので、FFでラッチする段数はパラメータで入力できるようにしておいた。

次に論理合成を行って、成功した。下に論理合成後の回路を示す。
Vivado_HLS_Study_77_150122.png

右の箱の2列目の色の違いってい箱が laplacian_filter.v である。その他の黄色の箱はFFなので、ラプラシアンフィルタ本体がFFに囲まれているのが分かる。

次に、XDCファイルを作製した。ap_clk に クロック周期 4 ns の制約を与えた。

create_clock -period 4.000 -name ap_clk -waveform {0.000 2.000} [get_ports ap_clk]


インプリメントを行った。成功した。タイミング制約も満たされている。
Vivado_HLS_Study_78_150122.png

Implemented Design で Report Timing Summary をクリックして Timing Summary を見た。
Vivado_HLS_Study_79_150122.png

ラプラシアンフィルタ内のレジスタ間の遅延が最大 3.807 ns に収まっている。

最後に、laplacian_filter_top.v を貼っておく。

`default_nettype none

module laplcian_filter_top #(
    parameter    integer    INPUT_FF_NUMBER =    1,
    parameter    integer    OUTPUT_FF_NUMBER =    1
)(
    input    wire    ap_clk,
    input    wire    ap_rst,
    input    wire    ap_start,
    output    wire    ap_done,
    output    wire    ap_idle,
    output    wire    ap_ready,
    input    wire    [31:0]    xy,
    output    wire    [31:0]    ap_return
);
    wire    [31:0]  x0y0;
    wire    [31:0]  x1y0;
    wire    [31:0]  x2y0;
    wire    [31:0]  x0y1;
    wire    [31:0]  x1y1;
    wire    [31:0]  x2y1;
    wire    [31:0]  x0y2;
    wire    [31:0]  x1y2;
    wire    [31:0]  x2y2;
    reg     [31:0]  xy_d[8:0];
    wire    ap_done_node;
    wire    ap_idle_node;
    wire    ap_ready_node;
    wire    [31:0]    ap_return_node;
    reg        [31:0]    x0y0_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x1y0_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x2y0_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x0y1_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x1y1_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x2y1_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x0y2_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x1y2_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    x2y2_d [INPUT_FF_NUMBER-1:0];
    reg        [31:0]    ap_return_d [OUTPUT_FF_NUMBER-1:0];
    reg        [INPUT_FF_NUMBER-1:0]    ap_start_d;
    reg        [OUTPUT_FF_NUMBER-1:0]    ap_done_d;
    reg        [OUTPUT_FF_NUMBER-1:0]    ap_idle_d;
    reg        [OUTPUT_FF_NUMBER-1:0]    ap_ready_d;

    laplacian_filter lap_filter_inst (
        .ap_clk(ap_clk),
        .ap_rst(ap_rst),
        .ap_start(ap_start_d[0]),
        .ap_done(ap_done_node),
        .ap_idle(ap_idle_node),
        .ap_ready(ap_ready_node),
        .x0y0(x0y0_d[0]),
        .x1y0(x1y0_d[0]),
        .x2y0(x2y0_d[0]),
        .x0y1(x0y1_d[0]),
        .x1y1(x1y1_d[0]),
        .x2y1(x2y1_d[0]),
        .x0y2(x0y2_d[0]),
        .x1y2(x1y2_d[0]),
        .x2y2(x2y2_d[0]),
        .ap_return(ap_return_node)
    );

     always @(posedge ap_clk) begin : AP_XY_DELAY
        integer i;

        for(i=8; i>=0; i=i-1) begin
            if (ap_rst) begin
                xy_d[i] <= 32'd0;
            end else begin
                if (i == 8) begin
                    xy_d[i] <= xy;
                end else begin
                    xy_d[i] <= xy_d[i+1];
                end
            end
        end
    end
    assign x0y0 = xy_d[0];
    assign x1y0 = xy_d[1];
    assign x2y0 = xy_d[2];
    assign x0y1 = xy_d[3];
    assign x1y1 = xy_d[4];
    assign x2y1 = xy_d[5];
    assign x0y2 = xy_d[6];
    assign x1y2 = xy_d[7];
    assign x2y2 = xy_d[8];
   
    always @(posedge ap_clk) begin : AP_START_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                ap_start_d[i] <= 1'b0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    ap_start_d[i] <= ap_start;
                end else begin
                    ap_start_d[i] <= ap_start_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_DONE_DELAY
        integer i;

        for(i=OUTPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                ap_done_d[i] <= 1'b0;
            end else begin
                if (i == (OUTPUT_FF_NUMBER-1)) begin
                    ap_done_d[i] <= ap_done_node;
                end else begin
                    ap_done_d[i] <= ap_done_d[i+1];
                end
            end
        end
    end
    assign ap_done = ap_done_d[0];

    always @(posedge ap_clk) begin : AP_IDLE_DELAY
        integer i;

        for(i=OUTPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                ap_idle_d[i] <= 1'b0;
            end else begin
                if (i == (OUTPUT_FF_NUMBER-1)) begin
                    ap_idle_d[i] <= ap_idle_node;
                end else begin
                    ap_idle_d[i] <= ap_idle_d[i+1];
                end
            end
        end
    end
    assign ap_idle = ap_idle_d[0];

    always @(posedge ap_clk) begin : AP_READY_DELAY
        integer i;

        for(i=OUTPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                ap_ready_d[i] <= 1'b0;
            end else begin
                if (i == (OUTPUT_FF_NUMBER-1)) begin
                    ap_ready_d[i] <= ap_ready_node;
                end else begin
                    ap_ready_d[i] <= ap_ready_d[i+1];
                end
            end
        end
    end
    assign ap_ready = ap_ready_d[0];

    always @(posedge ap_clk) begin : AP_X0Y0_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x0y0_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x0y0_d[i] <= x0y0;
                end else begin
                    x0y0_d[i] <= x0y0_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X1Y0_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x1y0_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x1y0_d[i] <= x1y0;
                end else begin
                    x1y0_d[i] <= x1y0_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X2Y0_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x2y0_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x2y0_d[i] <= x2y0;
                end else begin
                    x2y0_d[i] <= x2y0_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X0Y1_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x0y1_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x0y1_d[i] <= x0y1;
                end else begin
                    x0y1_d[i] <= x0y1_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X1Y1_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x1y1_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x1y1_d[i] <= x1y1;
                end else begin
                    x1y1_d[i] <= x1y1_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X2Y1_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x2y1_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x2y1_d[i] <= x2y1;
                end else begin
                    x2y1_d[i] <= x2y1_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X0Y2_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x0y2_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x0y2_d[i] <= x0y2;
                end else begin
                    x0y2_d[i] <= x0y2_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X1Y2_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x1y2_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x1y2_d[i] <= x1y2;
                end else begin
                    x1y2_d[i] <= x1y2_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_X2Y2_DELAY
        integer i;

        for(i=INPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                x2y2_d[i] <= 32'd0;
            end else begin
                if (i == (INPUT_FF_NUMBER-1)) begin
                    x2y2_d[i] <= x2y2;
                end else begin
                    x2y2_d[i] <= x2y2_d[i+1];
                end
            end
        end
    end
    
    always @(posedge ap_clk) begin : AP_RETURN_DELAY
        integer i;

        for(i=OUTPUT_FF_NUMBER-1; i>=0; i=i-1) begin
            if (ap_rst) begin
                ap_return_d[i] <= 32'd0;
            end else begin
                if (i == (OUTPUT_FF_NUMBER-1)) begin
                    ap_return_d[i] <= ap_return_node;
                end else begin
                    ap_return_d[i] <= ap_return_d[i+1];
                end
            end
        end
    end
    assign ap_return = ap_return_d[0];

endmodule

`default_nettype wire

  1. 2015年01月23日 04:08 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/3054-80e88817
この記事にトラックバックする(FC2ブログユーザー)