SystemVerilog Tips

はじめに

時々必要になるが、その時には多分忘れているであろう知識を書き残しておく。

‘signal kind’ と ‘data type’

wire, reg, logic, … といった混乱させるキーワードが厳密にはどのように定義されているのが、次の URL に解りやすい解説がある。

Usage of Var

二項演算とビット幅の規則

次の Web ページが詳しい。特に最後の例が興味深い。式の木構造を深さ優先探索しながらビット幅を決めていると理解される。

Expression Bit Widths

interface の信号を覗き見る

interface のインスタンスの中の個々の信号を引き出して読める。具体例は https://github.com/motchy869/code-fractions の use_vivado-sim_from_cmd_line/src/top.sv/w_monit_addr, w_monit_rd_data である。

多次元配列の次元の大きさを得る system function

次の Stack Overflow の質問と回答が非常に参考になる。

explanation of arrays in systemVerilog

array of packed struct

packed な struct の配列について web 情報が見つからなかったので自分で確かめた結果を記しておく。結論:ビット・ベクタとして観測できる。

typedef struct packed {
    logic [3:0] b;
    logic [1:0] a;
} my_t;

module main();

    var my_t [2:0] array_a_0;
    wire logic [3*6-1:0] array_a_1 = array_a_0;

    initial begin
        array_a_0[0] = '{a: 2'b00, b: 4'b1111};
        array_a_0[1] = '{a: 2'b01, b: 4'b1110};
        array_a_0[2] = '{a: 2'b10, b: 4'b1101};
        $display("array_a_0[0].a: 0b%02b", array_a_0[0].a);
        $display("array_a_0[0].b: 0b%04b", array_a_0[0].b);
        $display("array_a_0[2].a: 0b%02b", array_a_0[2].a);
        $display("array_a_0[2].b: 0b%04b", array_a_0[2].b);
        $display("array_a_1: 0b%018b", array_a_1);
    end

endmodule

実行結果

# array_0[0].a: 0b00
# array_0[0].b: 0b1111
# array_0[2].a: 0b10
# array_0[2].b: 0b1101
# array_1: 0b110110111001111100

queue

queue について判っていることをメモしておく。

  • size メソッドの戻り値の型は int である($typename を用いて確かめられる)。

module 定義にマッチする正規表現

module #(...)(); にマッチする正規表現は下記である。module を 1 個だけ含む .sv ファイルから .svh ファイルを自動生成するときに使える。

^module \s[a-zA-Z\d_]+(\s#([.\s\n\w=,/!*:)]+)){0,1}\s*([.\s\n\w=,/!*:()[]$-]+);

これは例えば下記の全体にマッチする。

module ram_sp_wf #(
    parameter int DATA_BIT_WIDTH = 8, //! data bit width
    parameter int DEPTH = 8, //! depth of RAM, **must be power of 2**
    parameter int USE_OUTPUT_REG = 0 //! output register option, 0/1: use/not use
)(
    input wire i_clk, //! clock signal
    input wire i_sync_rst, //! synchronous reset signal
    input wire i_we, //! write enable signal
    input wire [$clog2(DEPTH)-1:0] i_word_addr, //! word address
    input wire [DATA_BIT_WIDTH-1:0] i_data, //! input data
    output wire [DATA_BIT_WIDTH-1:0] o_data //! output data
);

ビット幅と符号とキャスト

自分がいつも「どうだったっけな?」となるパターンを書いておく。

initial begin
    automatic logic unsigned [8-1:0] a = 8'h80;
    automatic logic signed [8-1:0] b = a;
    automatic logic signed [12-1:0] c = a;
    automatic logic signed [12-1:0] d = signed'(a);
    automatic logic signed [12-1:0] e = 12'(signed'(a));
    $display("a = %d\nb = %d\nc = %d\nd = %d\ne = %d\n", a, b, c, d, e);
end

実行結果

a = 128
b = -128
c =   128
d =  -128
e =  -128

自分が経験した間違い

シミュレーションの結果が期待通りでないときには下記を疑おう。

  1. 症状:符号がおかしい
    確認:signed で定義された FF に unsigned な値(特に多次元ベクタの input に多い)を入力していないか?(負数が正数に化ける)
  2. 症状:符号がおかしい
    確認:>>> (算術右シフト)すべきところを >> (論理右シフト)していないか?(負数が正数に化ける)

投稿者: motchy

An embedded software and FPGA engineer for measuring instrument.

コメントを残す