Designing a circuit requires several steps:
1. Writing HDL (Verilog) code,
2. compiling the code to produce a circuit,
3. then simulating the circuit and fixing bugs.
When we say “compile Verilog HDL to
produce a circuit”, the circuit refers to
the digital hardware design that your
code describes.
A virtual representation of logic gates
and wires inside your computer.
•In software programming (C++/Python):
>Code compiles into instructions that a processor
executes.
•In hardware design (HDL):
>Code compiles into a network of logic gates, flip-
flops, and connections that can actually exist in silicon
(IC, FPGA, or ASIC).
Sample HDL code
1. module top_module(...)
• In Verilog, everything starts with a module — like a "box" that represents a
circuit.
• top_module is just the name. (This could be any name, but “top_module”
is often used as the main entry point in tutorials.)
• Inside the parentheses, we declare the inputs/outputs (the pins of this
circuit).
• Here: it has one output called one.
Sample HDL code
2. assign one = 1;
• assign is a continuous assignment statement.
• It says: the output signal one is always equal to logic value 1 (HIGH).
• In hardware: this means we are connecting the output pin directly to Vcc
(constant logic HIGH).
Sample HDL code
3. Endmodule
• Marks the end of the module definition.
Sample HDL code
Module Body
What hardware does this describe?
• A circuit with a single output pin.
• That pin is hardwired to logic HIGH (1).
• In reality, this is just like connecting an LED to a battery — the LED will
always stay ON, no matter what.
Sample HDL code
or
circuit with no inputs and one output that outputs a constant 0
Hardware meaning
This is equivalent to a constant 0 signal source.
• If you connect zero to an LED, the LED will always stay OFF.
• If you connect zero to part of a larger circuit, that part always sees a logic
LOW.
Simple Wire
Unlike physical wires, wires (and other signals) in Verilog
are directional. This means information flows in only one direction,
from (usually one) source to the sinks (The source is also often called
a driver that drives a value onto a wire). 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. A continuous
assignment is not a one-time event.
Simple Wire
In Verilog (Hardware with assign)
In Software (C++/Python) When you write:
When you write:
assign x = y + 1;
int x = y + 1;
This is a continuous assignment.
This runs once, at that exact It means:
moment in time. • "Wire x is always equal to y +
If y later changes, x does not 1."
automatically update unless • If y changes at any time, x
you reassign it again. instantly changes too.
It’s a one-time event. This is not one-time — it’s like a
live, permanent wiring connection.
Simple Wire
The diagram below illustrates
how each part of the circuit
corresponds to each bit of
Verilog code. The module and
port declarations create the black
portions of the circuit. Your task
is to create a wire (in green) by
adding an assign statement to
connect in to out. The parts
outside the box are not your
concern, but you should know
that your circuit is tested by
connecting signals from our test
harness to the ports on
your top_module.
Simple Wire
Simple Wire
Create a module with one input and one output that behaves like a wire.
Think of this like:
• Water pipe analogy: Pour water (in), it flows straight through to the output
(out).
• Light switch analogy: The output bulb (out) is wired directly to the input
switch (in).
4 Wire
Create a module with 3 inputs and 4 outputs that behaves like wires that
makes these connections:
a -> w
b -> x The diagram below illustrates how each part of
b -> y the circuit corresponds to each bit of Verilog
c -> z code. From outside the module, there are three
input ports and four output ports.
4 Wire
When you have multiple assign statements, the order in which they appear in the code does not matter.
Unlike a programming language, assign statements ("continuous assignments") describe connections between
things, not the action of copying a value from one thing to another.
One potential source of confusion that should perhaps be clarified now: The green arrows here represent
connections between wires, but are not wires in themselves. The module itself already has 7 wires declared
(named a, b, c, w, x, y, and z). This is because input and output declarations actually declare a wire unless
otherwise specified. Writing input wire a is the same as input a. Thus, the assign statements are not creating
wires, they are creating the connections between the 7 wires that already exist.
4 Wire
Create a module with 3 inputs and 4 outputs that behaves like wires that
makes these connections:
a -> w
b -> x
b -> y
c -> z
Notgate
This circuit is similar to wire, but
with a slight difference. When
making the connection from the
wire in to the wire out we're
going to implement an inverter
(or "NOT-gate") instead of a
plain wire.
Use an assign statement. The
assign statement will
continuously drive the inverse
of in onto wire out.
Notgate
Create a module that implements a NOT gate.
Andgate
This circuit now has three wires (a, b, and out). Wires a and b already have values driven onto them by the
input ports. But wire out currently is not driven by anything. Write an assign statement that drives out with
the AND of signals a and b.
Note that this circuit is very similar to the NOT gate, just with one more input. If it sounds different, it's
because I've started describing signals as being driven (has a known value determined by something attached
to it) or not driven by something. Input wires are driven by something outside the module. assign statements
will drive a logic level onto a wire. As you might expect, a wire cannot have more than one driver (what is its
logic level if there is?), and a wire that has no drivers will have an undefined value (often treated as 0 when
synthesizing hardware).
Andgate
Create a module that implements an AND gate.
Norgate
An assign statement drives a wire (or "net", as it's more formally called) with a value. This
value can be as complex a function as you want, as long as it's a combinational (i.e.,
memory-less, with no hidden state) function. An assign statement is a continuous
assignment because the output is "recomputed" whenever any of its inputs change,
forever, much like a simple logic gate.
Norgate
Create a module that implements a NOR gate. A NOR gate is an OR gate with its output
inverted. A NOR function needs two operators when written in Verilog.
Xnorgate
• XNOR stands for Exclusive-NOR. It is the inverse of XOR (Exclusive-OR).
• An XNOR gate checks for equality of two inputs. It’s often called the “equivalence gate”
because it outputs HIGH when inputs are equal.
Xnorgate
Create a module that implements an XNOR gate.
Wire Declaration
The circuits so far have been simple enough that the outputs are simple
functions of the inputs. As circuits become more complex, you will need wires
to connect internal components together. When you need to use a wire, you
should declare it in the body of the module, somewhere before it is first used.
(In the future, you will encounter more types of signals and variables that are
also declared the same way, but for now, we'll start with a signal of type wire).
Wire Declaration
Wire Declaration
In the above module, there are three wires (in, out, and not_in), two of which
are already declared as part of the module's input and output ports (This is
why you didn't need to declare any wires in the earlier exercises). The
wire not_in needs to be declared inside the module. It is not visible from
outside the module. Then, two NOT gates are created using
two assign statements. Note that it doesn't matter which of the NOT gates you
create first: You still end up with the same circuit.
Wire Declaration Practice
Implement the following circuit. Create two intermediate wires (named anything you want) to connect the
AND and OR gates together. Note that the wire that feeds the NOT gate is really wire out, so you do not
necessarily need to declare a third wire here. Notice how wires are driven by exactly one source (output of a
gate), but can feed multiple inputs.
If you're following the circuit structure in the diagram, you should end up with four assign statements, as
there are four signals that need a value assigned.
Wire Declaration Practice
• Inputs: a, b, c, d
• Outputs: out, out_n
• Circuit:
> Two AND gates (a & b, c & d)
> Their outputs go into an OR gate
> The OR gate output is out
> That same output goes into a NOT gate to produce out_n
Wire Declaration Practice
`default_nettype none
module top_module(
input a,
input b,
input c,
input d,
output out,
output out_n );
endmodule
7458 chip
The 7458 is a chip with four AND gates and two OR gates. The 7458 IC is a
specialty logic chip that implements AND-OR-Invert functions efficiently,
saving space when you need sum-of-products logic with inversion.
7458 chip
Create a module with the same functionality as the 7458 chip
Practice: Draw the Logic Gate Block of the following Circuits
1. Simple XOR + NOT Circuit 2. 3-input Majority Circuit
Inputs: a, b Inputs: a, b, c
Outputs: out, out_n Output: out
Circuit: Circuit:
out = a ^ b (XOR gate) out = (a & b) | (b & c) | (a & c)
out_n = ~out (NOT gate) This is called a majority function →
output is 1 when at least two
inputs are 1.