HDLbits Problem set
Verilog Language
Basics
Wire
Wires (and other signals) in Verilog are directional: information flows in only one direction, from (usually one, often called a driver that drives a value onto a wire) source to the sinks.
A module with 1 input and 1 output behaves like a
wire.The ports on a module also have a direction. An input port is driven by something from outside the module, while an output port drives something outside. Viewed from inside the module, an input port is a
driverorsource, while an output port is asink.
A wire cannot have more than one driver. A wire that has no drivers will have an undefined value (often treated as 0 when synthesizing hardware).
Declaration
Any wire(or other ypes) to connect internal components together needs to be declared in the body of the module before it is first used.
continuous assignment
In a Verilog “continuous assignment” (assign left_side = right_side;), the value of the signal on the right side is driven onto the wire on the left side. The assignment is “continuous” because the assignment continues all the time even if the right side’s value changes. (Not a one-time event.)
The order of multiple assign statements in which they appear in the code does not matter !!!.
assigndescribe connections between things, not the action of copying a value from one thing to another. And it must be highlighted thatassignare not creating wires but creating the connections between wires.An
assignstatement drives a wire with a value. This value can be any as long as it’s a combinational function.
Gate
NOT Gate/Inverter
1 | |
And Gate
Verilog has separate bitwise-AND (
&) and logical-AND (&&) operators.
1 | |
Or/Nor Gate
Verilog has separate bitwise-OR (
|) and logical-OR (||) operators.
1 | |
Xor/ Xnor Gate
1 | |
Vectors
Vectors are used to group related signals using one name to make it more convenient to manipulate.
1 | |
Declaration
Vectors must be declared
1 | |
where type specifies the datatype of the vector, usually wireor reg, and additionallyinput and output (port type).
The endianness of a vector is whether little-endian(the the least significant bit has a lower index
e.g.[3:0]) or big-endian(,e.g.[0:3]). But it must always be the same way once a vector is declared with a particular endianness.
1
2
3wire [3:0] vec1; //little-endian
wire [0:3] vec2; //big-endian
assign vec1[0:3] = {1,0,0} //bad
NOTEImplicit nets are often a source of hard-to-detect bugs. Net-type signals can be implicitly created by:
- an
assignstatement- 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.
Unpacked vs. Packed Arrays
| Packed dimensions | Unpacked dimensions | |
|---|---|---|
| declared | before the vector name | after the name |
| The bits are packed together into a blob | ||
NOTE |
relevant in a simulator but not in hardware | used to declare memory arrays |
Access
Accessing an entire vector is done using the vector name.
1 | |
It takes the entire 4-bit vector
aand assigns it to the entire 8-bit vectorw. It is zero-extended or truncated as appropriate If the lengths of the right and left sides don’t match.
Accessing a portion of a vector is done bypart-select.
1 | |
Concatenation and replication
The concatenation operator {,} is used to create larger vectors by concatenating smaller portions of a vector together.
NOTEConcatenation needs to know the width of every component. Thus{1, 2, 3}is illegal and results in the error message:unsized constants are not allowed in concatenations.
1 | |
The replication operator allows repeating a vector and concatenating them together when sometimes you want the same thing concatenated together many times.
1 | |
num must be a constant and both sets of braces are required.
1 | |
Bitwise vs. Logical Operators
| between | Description | Output | |
|---|---|---|---|
bitwise operation |
2 N-bit vectors | replicates the operation for each bit | 1 N-bit output |
logical operation |
2 N-bit vectors | treats the entire vector as a boolean value, truefor non-zero and false for zero. |
1-bit output |
Module
A module is a circuit that interacts with its outside through input and output ports. Larger and more complex circuits are built by composing bigger modules out of smaller modules and other pieces (e.g. assign and always blocks) i.e. hierarchy.
Modules can contain instances of other modules as long as all of the modules used belong to the same project (so the
compilerknows where to find them all).Code for different modules are not nested.
When connecting modules, only the ports on the module are important.
Connecting Signals to Ports
By position
Ports are connected left to right according to the module’s declaration when instantiating a module.
1 | |
- instantiates a module of type
mod_a - gives an
instance nameof “instance1” - connects signal
wa,wbandwcto the first, second and third ports (in1,in2andout) of the new module.
DrawbacksIf the module’s port list changes, all instantiations of the module will also need to be found and changed to match.
By name
1 | |
- instantiates a module of type
mod_a - gives an
instance nameof “*instance 2” - connects signal
wa,wbandwcto the ports namedin1,in2andoutof the module.
AdvantagesIt allows wires to remain correctly connected even if the port list changes. This syntax is more verbose, although.
NoteThe ordering of ports is irrelevant because the connection will be made to the correct name, regardless of its position in the sub-module’s port list.
Multiple-signal ports: Like everywhere else in Verilog, the vector length of the port does not have to match the wire connecting to it(
zero-paddingortrucationwill work to make them match).