代入のセマンティクス

Verylはすべての代入に単一の = 演算子を使用します。実際のセマンティクス — ブロッキングかノンブロッキングか — は代入コンテキストにより自動的に決定されます。これにより、設計者が手動で従うべきSystemVerilogのベストプラクティスが強制されます。

ブロッキング代入

always_comb ブロックと assign 宣言では、=ブロッキング代入を行います。代入された値は同一評価パス内の後続の読み取りから即座に参照可能です。

module ModuleA {
    let a: logic<8> = 1;
    var b: logic<8>;
    var c: logic<8>;

    always_comb {
        b = a + 1; // b は即座に 2 に更新される
        c = b + 1; // c は b の新しい値 (2) を読むため、c = 3
    }
}

ノンブロッキング代入

always_ff ブロック内では、モジュールレベル変数に対する =ノンブロッキング代入を行います。代入された値はNBA更新フェーズにスケジュールされ、FFコミットまで反映されません。

module ModuleA (
    i_clk: input clock,
) {
    var a: logic<8>;
    var b: logic<8>;

    always_ff {
        // a.next = 1(このフェーズ中 current の a は変化しない)
        a = 1;
        // a.current を読む(a.next ではない)ため、b.next = a.current + 1
        b = a + 1;
    }
}

always_ff 内のローカル束縛

always_ff 内の let 束縛は常にブロッキングセマンティクスを使用します。ローカル束縛はブロック内の一時的な値であり、フリップフロップにマップされることはありません。

module ModuleA (
    i_clk: input clock,
) {
    var a     : logic<8>;
    var result: logic<8>;

    always_ff {
        // ブロッキング:doubled は即座に利用可能
        let doubled: logic<8> = a * 2;
        // ノンブロッキング:result.next = doubled + 1
        result = doubled + 1;
    }
}

SystemVerilogへの対応

VerylコンテキストVeryl構文SystemVerilog相当
always_combx = expr;x = expr;(ブロッキング)
assignassign x = expr;assign x = expr;(continuous assignment)
always_ff、モジュールレベル変数x = expr;x <= expr;(ノンブロッキング)
always_ff、ローカル letlet x: T = expr;x = expr;(ブロッキング)
always_ff、複合代入x += expr;x <= x + expr;(ノンブロッキング)