Verilog is a hardware description language (HDL) used to model, design, and simulate digital systems such as integrated circuits (ICs), microprocessors, and Field Programmable Gate Arrays (FPGAs). It allows engineers to describe the structure, behavior, and functionality of digital hardware at various levels of abstraction, including:
Verilog is widely used in electronic design automation (EDA) and is an IEEE standard (IEEE 1364).
Hardware Design:
Simulation and Debugging:
Synthesis to Hardware:
Support for Different Abstractions:
Standardized Language:
Portability and Reusability:
Extensive Tool Support:
Ease of Use:
Testbench Creation:
Timing and Delay Modeling:
Verilog supports several levels of abstraction that allow engineers to design and describe hardware systems at varying degrees of detail. These levels range from high-level behavioral descriptions to low-level physical implementation. Each level serves a specific purpose in the hardware design and verification process.
initial
and always
if
, case
, for
, while
always @(posedge clk) begin
if (reset)
count <= 0;
else
count <= count + 1;
end
?
assign
)always @(posedge clk or posedge reset) begin
if (reset)
q <= 0;
else
q <= d;
end
?
and
, or
, nand
, nor
, xor
, xnor
, buf
, not
and G1 (out, a, b);
or G2 (out, c, d);
not G3 (out_inv, out);?
nmos
, pmos
, cmos
nmos (out, in, control);
pmos (out, in, control);?
VHDL |
Verilog |
---|---|
It was established in 1980, making it an older language. |
It was formed between late 1983 and early 1984. |
It uses the base languages, Ada and Pascal |
The base language is C. |
The VHDL language is more compact. |
It contains comparatively more LOCs or lines of code. |
As a language that encompasses more extensive capabilities than just modeling systems, VHDL is more reliable and developed. |
Considered to be of considerably lower level as a language mainly used for modeling, |
VHDL is not case sensitive |
Verilog is case sensitive |
VHDL analyses and simulates the behavior of the digital system in addition to describing its structure. |
They are only applied to describe digital systems. |
== |
=== |
Output can be 1,0 or X |
Output can be 0 or 1 |
It can compare 1s and 0s but not Xs |
Can also compare Xs |
In Verilog, wire
and reg
are fundamental data types with distinct characteristics:
Wire
wire
cannot store a value on its own. It simply transmits the value it receives from its source.wire
s are typically driven by continuous assignments (assign
) or as outputs of modules.Reg
reg
can hold a value and retain it until a new value is assigned.reg
s are primarily used within procedural blocks (like always
blocks) to model registers, flip-flops, and other memory elements.reg
can also be used for combinational logic within procedural blocks.// Wire declaration
wire a, b, c;
assign c = a & b;
// Reg declaration
reg d;
always @ (posedge clk) begin
d <= a | b;
end
In this example :
a
, b
, and c
are declared as wire
s. The assign
statement defines a continuous assignment, meaning the value of c
is always updated based on the values of a
and b
.d
is declared as a reg
. The always
block defines a sequential assignment, meaning the value of d
is updated only on the rising edge of the clock signal (posedge clk
).By understanding the distinctions between wire
and reg
, you can effectively model various hardware components and behaviors in Verilog.
In Verilog, initial
and always
blocks are both procedural constructs used to describe the behavior of digital circuits. However, they have key differences in their execution:
initial Block
initial
block are executed only at the beginning of the simulation, and then the block terminates.initial
blocks are primarily used in testbenches and are not typically synthesizable into hardware.always Block
always
block are executed repeatedly, based on the specified sensitivity list or timing control.always
blocks are essential for synthesizing hardware designs.// Initial block to set initial value of register
initial begin
reg_a = 1'b0;
end
// Always block for a D flip-flop
always @ (posedge clk) begin
if (reset)
reg_b <= 1'b0;
else
reg_b <= data;
end
In this example :
initial
block sets the initial value of reg_a
to 0 at the start of the simulation.always
block describes the behavior of a D flip-flop, where the value of reg_b
is updated on the rising edge of the clock signal (posedge clk
).By understanding the differences between initial
and always
blocks, you can effectively model and simulate digital circuits in Verilog.
In Verilog, blocking and non-blocking assignments are two distinct ways to assign values to variables within procedural blocks (like always
blocks). They have significant implications for how your Verilog code simulates and synthesizes.
Blocking Assignment (=
)
reg a, b, c;
always @ (posedge clk) begin
a = 1; // Assign 1 to a
b = a; // Assign the current value of a (which is now 1) to b
c = b; // Assign the current value of b (which is 1) to c
end
In this example, a
is assigned 1 first. Then, b
is assigned the current value of a
, which is 1. Finally, c
is assigned the current value of b
, which is also 1.
Non-Blocking Assignment (<=
)
reg a, b, c;
always @ (posedge clk) begin
a <= 1;
b <= a;
c <= b;
end
In this example :
a
is scheduled to be assigned 1.b
is scheduled to be assigned the current value of a
(which is its previous value).c
is scheduled to be assigned the current value of b
(which is its previous value).In Verilog, posedge
and negedge
are keywords used within always
blocks to specify the edge-triggered events that should trigger the execution of the block's statements.
posedge
:
always
block will execute only when the specified signal transitions from 0 to 1.negedge
:
always
block will execute only when the specified signal transitions from 1 to 0.Example :
always @ (posedge clk) begin
// Code to be executed on the rising edge of the clock signal
end
always @ (negedge rst_n) begin
// Code to be executed on the falling edge of the reset signal
end
Key Points :
posedge
and negedge
are crucial for designing synchronous circuits where events are triggered by specific transitions of a clock signal.always
blocks to create flip-flops, registers, and other sequential logic elements.posedge
and negedge
depends on the specific requirements of your design and the desired behavior of the circuit.By understanding the use of posedge
and negedge
, you can effectively model and design digital circuits with precise timing and synchronization in Verilog.
module DFF (
input clk,
input d,
output reg q
);
always @(posedge clk) begin
q <= d;
end
endmodule
$monitor, $display,
and $strobe
commands all have a similar syntax and display text on the screen while a simulation is ongoing. Compared to waveform tools like cwaves, these commands are often less user-friendly. $Monitor(<format_string>,<parameter>,<parameter>)
$Monitor
is used, it will execute and display the parameters each time one of the parameters is modified, that is, each time a new value for the parameter is displayed. Signals can be expressions, variables, or strings, and signal values can be changed using the $Monitor
command.$display(<list of arguments>);
$display
, which also aids debugging.$display
will always append a newline to the end of the string while showing the arguments.$display(<list of arguments>);
$strobe
is quite similar to $display
; however, it will only display all of its arguments after the current time unit.
Task |
Function |
---|---|
In Verilog, tasks can activate both additional tasks and functions. |
A function in Verilog can enable other functions but cannot allow a task.
|
A task is permitted to contain any event, delay, or timing control statement. |
Event, delay, or timing control statements are not allowed. Hence they cannot be contained in a function. |
The simulation for tasks is also zero. However, they can also be carried out in a simulation time that is not zero if necessary. |
Because the program time is not increased during the function routine, a function can do its required task in zero simulation time. |
A task may employ zero or more arguments of the output or input types arguments. |
A function must receive at least one parameter when it is invoked. |
Using the output and input statements, a task can pass multiple values but cannot return a value. |
Functions cannot employ either output or input statements and only return a single value. |
repeat(<no. of times the loop will run>) <statement to be repeated>?
always @ (posedge clock)
begin
temp=y;
y=x;
x=temp;
end. ?
always @ (posedge clock)
begin
x <= y;
y <= x;
end?
module my_module #(parameter WIDTH = 8)(input [WIDTH-1:0] data_in, output [WIDTH-1:0] data_out);
assign data_out = data_in;
endmodule?
Virtual |
Pure virtual |
It allows the overriding of a function in a derived class |
It has only declaration and no implementation |
The base class doesn’t need to implement a virtual function |
Any derivative class must implement the function |
module synchronizer (
input clk_dest, reset,
input signal_in,
output reg signal_out
);
reg meta;
always @(posedge clk_dest or posedge reset) begin
if (reset) begin
meta <= 1'b0;
signal_out <= 1'b0;
end else begin
meta <= signal_in;
signal_out <= meta;
end
end
endmodule?
module handshake_cdc (
input clk_src, clk_dest, reset,
input [7:0] data_in,
input send,
output reg [7:0] data_out,
output reg received
);
reg [7:0] data_reg;
reg send_toggle, recv_toggle;
wire send_sync, recv_sync;
// Source domain
always @(posedge clk_src or posedge reset) begin
if (reset) begin
data_reg <= 8'b0;
send_toggle <= 1'b0;
end else if (send) begin
data_reg <= data_in;
send_toggle <= ~send_toggle;
end
end
// Destination domain
always @(posedge clk_dest or posedge reset) begin
if (reset) begin
data_out <= 8'b0;
received <= 1'b0;
recv_toggle <= 1'b0;
end else if (send_sync != recv_toggle) begin
data_out <= data_reg;
received <= 1'b1;
recv_toggle <= send_sync;
end else begin
received <= 1'b0;
end
end
// Synchronizers
synchronizer sync_send (.clk_dest(clk_dest), .reset(reset), .signal_in(send_toggle), .signal_out(send_sync));
synchronizer sync_recv (.clk_dest(clk_src), .reset(reset), .signal_in(recv_toggle), .signal_out(recv_sync));
endmodule?
$
and are primarily used for simulation and debugging. Examples include $display
(for printing messages) and $monitor (for continuously monitoring and printing signals).$display("Simulation Time: %0d, Data: %b", $time, data);
reg [7:0] memory_array [0:255]; // 256x8 memory array
module mux (
input a, b, sel,
output y
);
assign y = sel ? b : a;
endmodule
inout
ports.module bidirectional (
inout wire bus,
input enable,
input data_in,
output data_out
);
assign bus = enable ? data_in : 1'bz;
assign data_out = bus;
endmodule?
module testbench;
reg clk, d;
wire q;
// Instantiate the DUT
DFF dut (.clk(clk), .d(d), .q(q));
initial begin
clk = 0; d = 0;
#5 d = 1;
#10 d = 0;
#20 $finish;
end
always #5 clk = ~clk; // Clock generation
endmodule
.vcd
(Value Change Dump) format. Example:initial begin
$dumpfile("waveform.vcd");
$dumpvars(0, testbench);
end?