FC2カウンター FPGAの部屋 Verilog HDL で unsigned, signed の演算をする2(実践編)
FC2ブログ

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

FPGAの部屋

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

Verilog HDL で unsigned, signed の演算をする2(実践編)

”Verilog HDL で unsigned, signed の演算をする1”の続き。

ISE14.7 の Project Navigator でプロジェクトを作って、確かめた。

下にProject Navigator のプロジェクトを示す。
Verilog_Signed_1_131205.png

下に、Verilog HDLの calculation_test.v を示す。

`default_nettype none

module calculation_test(

    input    wire            [7:0]    a,
    input    wire            [7:0]    b,
    input    wire    signed    [7:0]    sc,
    input    wire    signed    [7:0]    sd,
    input   wire            [7:0]   e,
    input   wire    signed  [7:0]   sf,

    output    wire            [7:0]    x1,
    output    wire            [8:0]    x2,
    output    wire    signed    [8:0]    sy1,
    output    wire    signed    [8:0]    sy2,
    output  wire    signed  [8:0]   sz1,
    output  wire    signed  [8:0]   sz2
);
    // unsigned - unsigned
    assign    x1 = a - b;
    assign    x2 = {1'b0, a} - {1'b0, b};    // ビット幅を合わせた

    // signed - signed
    assign    sy1 = sc - sd;
    assign    sy2 = {sc[7], sc} - {sd[7], sd};    // 明示的に符号拡張

    // signed - $signed(unsigned)
    assign  sz1 = sf - $signed(e);
    assign  sz2 = sf - $signed({1'b0, e[6:0]});
endmodule


下に、テストベンチの calculation_test_tb.v を示す。

`timescale 1ns / 1ps

module calculation_test_tb;

    parameter    DELAY =    10;

    // Inputs
    reg             [7:0] a;
    reg             [7:0] b;
    reg        signed    [7:0] sc;
    reg     signed    [7:0] sd;
    reg             [7:0] e;
    reg     signed    [7:0] sf;

    // Outputs
    wire             [7:0] x1;
    wire             [8:0] x2;
    wire    signed    [8:0] sy1;
    wire     signed    [8:0] sy2;
    wire     signed    [8:0] sz1;
    wire     signed    [8:0] sz2;

    // Instantiate the Unit Under Test (UUT)
    calculation_test uut (
        .a(a),
        .b(b),
        .sc(sc),
        .sd(sd),
        .e(e),
        .sf(sf),
        .x1(x1),
        .x2(x2),
        .sy1(sy1),
        .sy2(sy2),
        .sz1(sz1),
        .sz2(sz2)
    );

    initial begin
        // Initialize Inputs
        a = 0;
        b = 0;
        sc = 0;
        sd = 0;
        e = 0;
        sf = 0;

        // Wait 100 ns for global reset to finish
        #100;

        // Add stimulus here
        a = 3; b = 2;
        #DELAY;
        $display("x = a - b");
        if (x1>=0)
            $display("a=%d, b=%d, x1=%d, x1>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x1=%d, x1<0", a, b,x1);
        if (x2>=0)
            $display("a=%d, b=%d, x2=%d, x2>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x2=%d, x2<0", a, b,x1);

        sc = 3; sd = 2;
        #DELAY;
        $display("sy = sc - sd");
        if (sy1>=0)
            $display("sc=%d, sd=%d, sy1=%d, sy1>=0", sc, sd, sy1);
        else
            $display("sc=%d, sd=%d, sy1=%d, sy1<0", sc, sd, sy1);
        if (sy2>=0)
            $display("sc=%d, sd=%d, sy2=%d, sy2>=0", sc, sd, sy2);
        else
            $display("sc=%d, sd=%d, sy2=%d, sy2<0", sc, sd, sy2);

        sf = 3; e = 2;
        #DELAY;
        $display("sz = sf - e");
        if (sz1>=0)
            $display("sf=%d, e=%d, sz1=%d, sz1>=0", sf, e, sz1);
        else
            $display("sf=%d, e=%d, sz1=%d, sz1<0", sf, e, sz1);
        if (sz2>=0)
            $display("sf=%d, e=%d, sz2=%d, sz2>=0", sf, e, sz2);
        else
            $display("sf=%d, e=%d, sz2=%d, sz2<0", sf, e, sz2);

        $display("");

        a = 2; b = 3;
        #DELAY;
        $display("x = a - b");
        if (x1>=0)
            $display("a=%d, b=%d, x1=%d, x1>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x1=%d, x1<0", a, b,x1);
        if (x2>=0)
            $display("a=%d, b=%d, x2=%d, x2>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x2=%d, x2<0", a, b,x1);

        sc = 2; sd = 3;
        #DELAY;
        $display("sy = sc - sd");
        if (sy1>=0)
            $display("sc=%d, sd=%d, sy1=%d, sy1>=0", sc, sd, sy1);
        else
            $display("sc=%d, sd=%d, sy1=%d, sy1<0", sc, sd, sy1);
        if (sy2>=0)
            $display("sc=%d, sd=%d, sy2=%d, sy2>=0", sc, sd, sy2);
        else
            $display("sc=%d, sd=%d, sy2=%d, sy2<0", sc, sd, sy2);

        sf = 2; e = 3;
        #DELAY;
        $display("sz = sf - e");
        if (sz1>=0)
            $display("sf=%d, e=%d, sz1=%d, sz1>=0", sf, e, sz1);
        else
            $display("sf=%d, e=%d, sz1=%d, sz1<0", sf, e, sz1);
        if (sz2>=0)
            $display("sf=%d, e=%d, sz2=%d, sz2>=0", sf, e, sz2);
        else
            $display("sf=%d, e=%d, sz2=%d, sz2<0", sf, e, sz2);

        $display("");

        a = -128; b = 128;
        #DELAY;
        $display("x = a - b");
        if (x1>=0)
            $display("a=%d, b=%d, x1=%d, x1>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x1=%d, x1<0", a, b,x1);
        if (x2>=0)
            $display("a=%d, b=%d, x2=%d, x2>=0", a, b,x1);
        else
            $display("a=%d, b=%d, x2=%d, x2<0", a, b,x1);

        sc = -128; sd = 128;
        #DELAY;
        $display("sy = sc - sd");
        if (sy1>=0)
            $display("sc=%d, sd=%d, sy1=%d, sy1>=0", sc, sd, sy1);
        else
            $display("sc=%d, sd=%d, sy1=%d, sy1<0", sc, sd, sy1);
        if (sy2>=0)
            $display("sc=%d, sd=%d, sy2=%d, sy2>=0", sc, sd, sy2);
        else
            $display("sc=%d, sd=%d, sy2=%d, sy2<0", sc, sd, sy2);

        sf = -128; e = 127;
        #DELAY;
        $display("sz = sf - e");
        if (sz1>=0)
            $display("sf=%d, e=%d, sz1=%d, sz1>=0", sf, e, sz1);
        else
            $display("sf=%d, e=%d, sz1=%d, sz1<0", sf, e, sz1);
        if (sz2>=0)
            $display("sf=%d, e=%d, sz2=%d, sz2>=0", sf, e, sz2);
        else
            $display("sf=%d, e=%d, sz2=%d, sz2<0", sf, e, sz2);
    end

endmodule


これらの Verilog HDL ファイルを ISim でコンパイルしたところ以下の出力が得られた。

x = a - b
a= 3, b= 2, x1= 1, x1>=0
a= 3, b= 2, x2= 1, x2>=0
sy = sc - sd
sc= 3, sd= 2, sy1= 1, sy1>=0
sc= 3, sd= 2, sy2= 1, sy2>=0
sz = sf - e
sf= 3, e= 2, sz1= 1, sz1>=0
sf= 3, e= 2, sz2= 1, sz2>=0

x = a - b
a= 2, b= 3, x1=255, x1>=0
a= 2, b= 3, x2=255, x2>=0
sy = sc - sd
sc= 2, sd= 3, sy1= -1, sy1<0
sc= 2, sd= 3, sy2= -1, sy2<0
sz = sf - e
sf= 2, e= 3, sz1= -1, sz1<0
sf= 2, e= 3, sz2= -1, sz2<0

x = a - b
a=128, b=128, x1= 0, x1>=0
a=128, b=128, x2= 0, x2>=0
sy = sc - sd
sc=-128, sd=-128, sy1= 0, sy1>=0
sc=-128, sd=-128, sy2= 0, sy2>=0
sz = sf - e
sf=-128, e=127, sz1=-255, sz1<0
sf=-128, e=127, sz2=-255, sz2<0


最後の sc に 128 を入れて演算している例では、128は8ビットの符号付きの数値として表すことはできないが、integer の値をそのまま代入して計算されているので、常にデータのビット幅について注意が必要のようだ。
sc = 127とすれば、正常に -255 が計算された。

下に、ISim のタイミング波形を示す。
Verilog_Signed_2_131205.png

これで、シミュレーションは終了した。Verilog HDLでも signed を使うことができそうだ。

次は、論理合成、インプリメントを行った。成功した。FPGAはZedBoardのZynqだ。
Verilog_Signed_3_131205.png

RTL View で見ると、x1とx2は統合されていたが、他は別々に実装してあった。
Verilog_Signed_4_131205.png
Verilog_Signed_5_131205.png

FPGA Editor でPlace and Route 後の結果を見ると、sy2も削除されているようだ。
Verilog_Signed_6_131205.png

次に、Post-Map Simulation Model を生成した。
Verilog_Signed_7_131205.png

これで、Post-Map Simulationを実行することができる。Simulation モードで、Post-Map を指定してシミュレーションを行った。
Verilog_Signed_8_131205.png

シミュレーション結果を下に示す。
Verilog_Signed_9_131205.png

シミュレーションの出力は、Behavioral Simulation の結果と同様だった。

ちなみに、Post-Route のシミュレーション出力は違っていた。遅延の影響だと思われる。遅延を計算して、テストベンチを作製する必要があるようだ。
  1. 2013年12月05日 05:24 |
  2. 入門Verilog
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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