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
driver
orsource
, 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 !!!.
assign
describe connections between things, not the action of copying a value from one thing to another. And it must be highlighted thatassign
are not creating wires but creating the connections between wires.An
assign
statement 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 wire
or 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
3
wire [3:0] vec1; //little-endian
wire [0:3] vec2; //big-endian
assign vec1[0:3] = {1,0,0} //bad
NOTE
Implicit nets are often a source of hard-to-detect bugs. Net-type signals can be implicitly created by:
- an
assign
statement- 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
a
and 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.
NOTE
Concatenation 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, true for 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
compiler
knows 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 name
of “instance1” - connects signal
wa
,wb
andwc
to the first, second and third ports (in1
,in2
andout
) of the new module.
Drawbacks
If 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 name
of “*instance 2” - connects signal
wa
,wb
andwc
to the ports namedin1
,in2
andout
of the module.
Advantages
It allows wires to remain correctly connected even if the port list changes. This syntax is more verbose, although.
Note
The 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-padding
ortrucation
will work to make them match).