Assignment Semantics
Veryl uses a single = operator for all assignments.
The semantics — blocking or non-blocking — are automatically determined by context, enforcing SystemVerilog best practices.
Blocking Assignment
In always_comb and assign, = performs a blocking assignment — the value is immediately visible to subsequent reads.
module ModuleA {
let a: logic<8> = 1;
var b: logic<8>;
var c: logic<8>;
always_comb {
b = a + 1; // b is immediately updated to 2
c = b + 1; // c reads the new value of b (2), so c = 3
}
}
Non-Blocking Assignment
In always_ff, = for module-level variables performs a non-blocking assignment — the value does not take effect until the FF commit.
module ModuleA (
i_clk: input clock,
) {
var a: logic<8>;
var b: logic<8>;
always_ff {
// a.next = 1 (current a is unchanged during this phase)
a = 1;
// reads a.current (not a.next), so b.next = a.current + 1
b = a + 1;
}
}
Local Bindings in always_ff
A let inside always_ff uses blocking semantics and is never mapped to a flip-flop.
module ModuleA (
i_clk: input clock,
) {
var a : logic<8>;
var result: logic<8>;
always_ff {
// blocking: doubled is immediately available
let doubled: logic<8> = a * 2;
// non-blocking: result.next = doubled + 1
result = doubled + 1;
}
}
Function Calls in always_ff
A function called from always_ff can’t write an HDL object outside the function.
An output parameter which is written by the function must be connected to a variable
declared inside the always_ff process. The result can then be assigned explicitly using
the non-blocking semantics of the process.
module ModuleA (
i_clk : input clock ,
a : input logic<8>,
result: output logic<8>,
) {
function increment (
value: input logic<8>,
next : output logic<8>,
) {
next = value + 1;
}
always_ff {
var next: logic<8>;
increment(a, next);
result = next;
}
}
This restriction keeps all writes to HDL objects that participate in the simulation cycle
visible in the always_ff process. A function may still modify its local variables and
written output parameters as shown above. System functions such as $display and
$assert don’t write such HDL objects and aren’t affected by this restriction.
Mapping to SystemVerilog
| Veryl context | Veryl syntax | SystemVerilog equivalent |
|---|---|---|
always_comb | x = expr; | x = expr; (blocking) |
assign | assign x = expr; | assign x = expr; (continuous) |
always_ff, module-level var | x = expr; | x <= expr; (non-blocking) |
always_ff, local let | let x: T = expr; | x = expr; (blocking) |
always_ff, compound | x += expr; | x <= x + expr; (non-blocking) |