Verilog language
Implicit nets¶
Implicit nets are often a source of hard-to-detect bugs. In Verilog, net-type signals can be implicitly created by an assign statement or by attaching something undeclared to a module port. Implicit nets are always one-bit wires and causes bugs if you had intended to use a vector. Disabling creation of implicit nets can be done using the `default_nettype none directive.
Verilog | |
---|---|
1 2 3 4 5 6 |
|
Adding `default_nettype none would make the second line of code an error, which makes the bug more visible.
Unpacked vs. Packed Arrays¶
You may have noticed that in declarations, the vector indices are written before the vector name. This declares the "packed" dimensions of the array, where the bits are "packed" together into a blob (this is relevant in a simulator, but not in hardware). The unpacked dimensions are declared after the name. They are generally used to declare memory arrays. Since ECE253 didn't cover memory arrays, we have not used packed arrays in this course. See http://www.asic-world.com/systemverilog/data_types10.html for more details.
Verilog | |
---|---|
1 2 |
|
| and ||¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
The concatenation operator¶
The concatenation operator allowed concatenating together vectors to form a larger vector. But sometimes you want the same thing concatenated together many times, and it is still tedious to do something like assign a = {b,b,b,b,b,b};. The replication operator allows repeating a vector and concatenating them together:
{num{vector}} This replicates vector by num times. num must be a constant. Both sets of braces are required.
Examples:
Verilog | |
---|---|
1 2 3 4 |
|
Module pos & Module name¶
pos¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
name¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Substractor¶
An adder-subtractor can be built from an adder by optionally negating one of the inputs, which is equivalent to inverting the input then adding 1. The net result is a circuit that can do two operations: (a + b + 0) and (a + ~b + 1). See Wikipedia if you want a more detailed explanation of how this circuit works.
Use a 32-bit wide XOR gate to invert the b input whenever sub is 1.
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
wire and reg¶
A note on wire vs. reg: The left-hand-side of an assign statement must be a net type (e.g., wire), while the left-hand-side of a procedural assignment (in an always block) must be a variable type (e.g., reg). These types (wire vs. reg) have nothing to do with what hardware is synthesized, and is just syntax left over from Verilog's use as a hardware simulation language.
Blocking vs. Non-Blocking Assignment¶
There are three types of assignments in Verilog:
- Continuous assignments (assign x = y;). Can only be used when not inside a procedure ("always block").
- Procedural blocking assignment: (x = y;). Can only be used inside a procedure.
- Procedural non-blocking assignment: (x <= y;). Can only be used inside a procedure.
In a combinational always block, use blocking assignments. In a clocked always block, use non-blocking assignments. A full understanding of why is not particularly useful for hardware design and requires a good understanding of how Verilog simulators keep track of events. Not following this rule results in extremely hard to find errors that are both non-deterministic and differ between simulation and synthesized hardware.
Always if¶
An if statement usually creates a 2-to-1 multiplexer, selecting one input if the condition is true, and the other input if the condition is false.
Verilog | |
---|---|
1 2 3 4 5 6 7 8 |
|
Verilog | |
---|---|
1 |
|
How to avoid making latches¶
Syntactically-correct code does not necessarily result in a reasonable circuit (combinational logic + flip-flops). The usual reason is: "What happens in the cases other than those you specified?". Verilog's answer is: Keep the outputs unchanged.
This behaviour of "keep outputs unchanged" means the current state needs to be remembered, and thus produces a latch. Combinational logic (e.g., logic gates) cannot remember any state. Watch out for Warning (10240): ... inferring latch(es)" messages. Unless the latch was intentional, it almost always indicates a bug. Combinational circuits must have a value assigned to all outputs under all conditions. This usually means you always need else clauses or a default value assigned to the outputs.
Always case¶
Case statements in Verilog are nearly equivalent to a sequence of if-elseif-else that compares one expression to a list of others. Its syntax and functionality differs from the switch statement in C.
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
- The case statement begins with case and each "case item" ends with a colon. There is no "switch".
- Each case item can execute exactly one statement. This makes the "break" used in C unnecessary. But this means that if you need more than one statement, you must use begin ... end.
- Duplicate (and partially overlapping) case items are permitted. The first one that matches is used. C does not allow duplicate case items.
Always casez¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Reduction¶
You're already familiar with bitwise operations between two values, e.g., a & b or a ^ b. Sometimes, you want to create a wide gate that operates on all of the bits of one vector, like (a[0] & a[1] & a[2] & a[3] ... ), which gets tedious if the vector is long.
The reduction operators can do AND, OR, and XOR of the bits of a vector, producing one bit of output:
Verilog | |
---|---|
1 2 3 |
|
Error-prone points¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
- for循环必须在always块或者initial里面
- out = 0;
generate¶
Verilog | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|