ECE 5745 Complex Digital ASIC Design Verilog Usage Rules
ECE 5745 Complex Digital ASIC Design Verilog Usage Rules
revision: 2019-02-03-22-53
Verilog is a powerful language that was originally intended for building simulators of hardware as
opposed to models that could automatically be transformed into hardware (e.g., synthesized to an
FPGA or ASIC). Given this, it is very easy to write Verilog code that does not actually model any kind
of realistic hardware. Indeed, we actually need this feature to be able to write clean and productive
assertions and line tracing. Non-synthesizable Verilog modeling is also critical when implementing
test harnesses. So students must be very diligent in actively deciding whether or not they are
writing synthesizable register-transfer-level models or non-synthesizable code. Students must
always keep in mind what hardware they are modeling and how they are modeling it!
Students’ design work will almost exclusively use synthesizable register-transfer-level (RTL) models.
It is acceptable to include a limited amount of non-synthesizable code in students’ designs for the
sole purpose of debugging, assertions, or line tracing. If the student includes non-synthesizable code
in their actual design (i.e., not the test harness), they must explicitly demarcate this code by wrapping
it in ‘ifndef SYNTHESIS and ‘endif. This explicitly documents the code as non-synthesizable and
aids automated tools in removing this code before synthesizing the design. If at any time students
are unclear about whether a specific construct is allowed in a synthesizable RTL, they should ask
the instructors.
The next page includes a table that outlines which Verilog constructs are allowed in synthesizable
RTL, which constructs are allowed in synthesizable RTL with limitations, and which constructs are
explicitly not allowed in synthesizable RTL. There are no limits on using the Verilog preprocessor,
since the preprocessing step happens at compile time.
Unlike ECE 4750, these rules are more of a suggestion than hard rules. Students are allowed to use
anything that Synopsys Design Compiler can synthesize. If you figure out that Synopsys Design
Compiler can synthesize a more sophisticated syntax that significantly simplifies your design,
then by all means use that syntax.
1
ECE 5745 Complex Digital ASIC Design Verilog Usage Rules
Allowed in Explicitly
Always Allowed in Synthesizable RTL Not Allowed in
Synthesizable RTL With Limitations Synthesizable RTL
logic always1 wire, reg13
logic [N-1:0] enum2 integer, real, time, realtime
& | ^ ^~ ~ (bitwise) struct3 signed14
&& || ! casez, endcase4 ===, !==
& ~& | ~| ^ ^~ (reduction) task, endtask5 * / % ** 15
+ - function, endfunction5 #N (delay statements)
>> << >>> = (blocking assignment)6 inout16
== != > <= < <= <= (non-blocking assignment)7 initial
{} typedef8 variable initialization17
{N{}} (repeat) packed9 negedge18
?: $clog2()10 casex, endcase
always_ff, always_comb $bits()10 for, while, repeat, forever19
if else $signed()11 fork, join
case, endcase read-modify-write signal12 deassign, force, release
begin, end specify, endspecify
module, endmodule nmos, pmos, cmos
input, output rnmos, rpmos, rcmos
assign tran, tranif0, tranif1
parameter rtran, rtranif0, rtranif1
localparam supply0, supply1
genvar strong0, strong1
generate, endgenerate weak0, weak1
generate for primitive, endprimitive
generate if else defparam
generate case unnamed port connections20
named port connections unnamed parameter passing21
named parameter passing all other keywords
all other system tasks
1 Students should prefer using always_ff and always_comb instead of always. If students insist on using
always, then it can only be used in one of the following two constructs: always @(posedge clk) for se-
quential logic, and always @(*) for combinational logic. Students are not allowed to trigger sequential
blocks off of the negative edge of the clock or create asynchronous resets, nor use explicit sensitivity lists.
2 enum can only be used with an explicit base type of logic and explicitly setting the bitwidth using the fol-
lowing syntax: typedef enum logic [$clog2(N)-1:0] { ... } type_t; where N is the number of labels
in the enum. Anonymous enums are not allowed.
3 struct can only be used with the packed qualifier (i.e., unpacked structs are not allowed) using the follow-
ing syntax: typedef struct packed { ... } type_t; Anonymous structs are not allowed.
4 casez can only be used in very specific situations to compactly implement priority encoder style hardware
structures.
5 task and function blocks must themselves contain only synthesizable RTL.
6 Blocking assignments should only be used in always_comb blocks and are explicitly not allowed in
always_ff blocks.
2
ECE 5745 Complex Digital ASIC Design Verilog Usage Rules
7 Non-blocking assignments should only be used in always_ff blocks and are explicitly not allowed in
always_comb blocks.
8 typedef should only be used in conjunction with enum and struct.
9 packed should only be used in conjunction with struct.
10 The input to $clog2/$bits must be a static-elaboration-time constant. The input to $clog2/$bits cannot
be a signal (i.e., a wire or a port). In other words, $clog2/$bits can only be used for static elaboration and
cannot be used to model actual hardware.
11 $signed() can only be used around the operands to >>>, >, >=, <, <= to ensure that these operators perform
the signed equivalents.
12 Reading a signal, performing some arithmetic on the corresponding value, and then writing this value back
to the same signal (i.e., read-modify-write) is not allowed within an always_comb concurrent block. This is
a combinational loop and does not model valid hardware. Read-modify-write is allowed in an always_ff
concurrent block with a non-blocking assignment, although we urge students to consider separating the
sequential and combinational logic. Students can use an always_comb concurrent block to read the sig-
nal, perform some arithmetic on the corresponding value, and then write a temporary wire; and use an
always_ff concurrent block to flop the temporary wire into the destination signal.
13 wire and reg are perfectly valid, synthesizable constructs, but logic is much cleaner. So we would like
students to avoid using wire and reg.
14 signed types can sometimes be synthesized, but we do not allow this construct in the course.
15 Multipliers can be synthesized and small multipliers can even be synthesized efficiently, but we do not
allow this construct in the course. If you need to multiply or divide by a power of two, then you can use
the left and right shift operators.
16 Ports with inout can be used to create tri-state buses, but tools often have trouble synthesizing hardware
from these kinds of models.
17 Variable initialization means assigning an initial value to a logic variable when you declare the variable.
This is not synthesizable; it is not modeling real hardware. If you need to set some state to an initial
condition, you must explicitly use the reset signal.
18 Triggering a sequential block off of the negedge of a signal is certainly synthesizable, but we will be exclu-
sively using a positive-edge-triggered flip-flop-based design style.
19 If you would like to generate hardware using loops, then you should use generate blocks.
20 In very specific, rare cases unnamed port connections might make sense, usually when there are just one or
two ports and there purpose is obvious from the context.
21 In very specific, rare cases unnamed parameter passing might make sense, usually when there are just one
or two parameters and their purpose is obvious from the context.