What SystemVerilog features should be avoided in synthesis?
SystemVerilog(SV) can be used both as a HDL (Hardware Description Language) and HVL (Hardware Verification Language) and that is why it is often termed an "HDVL".
There are several interesting design constructs in SV which are synthesizable and can be used instead instead of older Verilog constructs, which are helpful in optimizing code and achieving faster results.
enum
of SV vsparameter
of Verilog while modelling FSM.- Use of
logic
instead ofreg
andwire
. - Use of
always_ff
,always_comb
,always_latch
in place of singlealways
blocks in Verilog. - Use of the
unique
andpriority
statements instead of Verilog'sfull
andparallel
case statements. - Wide range of data types available in SV.
Now what I have discussed above are those constructs of SystemVerilog which are used in RTL design.
But, the constructs which are used in the Verification Environment are non-synthesizable. They are as follows:
- Dynamic arrays and associative arrays.
- Program Blocks and Clocking blocks.
- Mailboxes
- Semaphores
- Classes and all their related features.
- Tasks
- Chandle data types.
- Queues.
- Constrained random features.
- Delay, wait, and event control statements.
Theoretically, if you can write software that is synthesized into machine code to run on a piece of hardware, that software can be synthesized into hardware. And conversely, there are hardware constructs in Verilog-1995 that are not considered synthesizable simply because none of the major vendors ever got around to supporting it (e.g. assign
/deassign
). We still have people using //synopsis translate on/off
because it took so long for them to support `ifdef SYNOPSYS
.
Most of what I consider to be safe for synthesis in SystemVerilog is what I call syntactic sugar for Verilog. This is just more convenient ways of writing the same Verilog code with a lot less typing. Examples would be:
- data types: typedef, struct, enum, int, byte
- use of those types as ports, arguments and function return values
- assignment operators: ++ -- +=
- type casting and bit-streaming
- packages
- interfaces
- port connection shortcuts
- defaults for function/tasks/macro arguments, and port connections
Most of the constructs that fall into this category are taken from C and don't really change how the code gets synthesized. It's just more convenient to define and reference signals.
The place it gets difficult to synthesize is where there is dynamically allocated storage. This would be class objects, queues, dynamic arrays, and strings. as well as dynamically created processes with fork/join.
I think some people have a misconception about SystemVerilog thinking it is only for Verification when in fact the first version of the standard was the synthesizable subset, and Intel was one of the first users of it as a language for Design.