In Verilog and SystemVerilog, always
blocks describe hardware behaviour sequentially, similar to how software is written. Statements are evaluated in the order that they’re written. Take this module, describing a multiplexer.
All signals assigned a value in always
must be of type reg
, but cannot be assigned outside of the block. In SystemVerilog, we can define signals of a type logic
, which don’t have this restriction.
If we have multiple statements in a block, then we must use the keywords begin
and end
. We cannot use wire
within always. Modules can only be instantiated outside always blocks, not inside. A workaround is to call always
within the sub-module.1 Or to use generate
statements.
Sensitivity list
Whatever parameters are in the always
statement describe a “sensitivity list”, i.e., where the code in the always block is sensitive to changes in the signals. We can also instead put an asterisk in the sensitivity list — what this means is that we let Verilog figure out the sensitivity list. For combinational circuits, we should only pass in an asterisk.
For sequential circuits, we want to be able to pass in a clock edge. Oftentimes we explicitly put in:
In SystemVerilog, it’s best practice to specify combinational logic with always_comb
(no sensitivity list), and edge-sensitive logic with always_ff
(sensitivity list requires edges).
Enabled features
Certain language constructs are only enabled within always
blocks.
- Regular conditionals, like
if
andelse
statements. case
statements, analogous to switch statements
Footnotes
-
There’s a really good explanation on StackOverflow on other possible things you can do. ↩