Introduction to Verilog HDL
Basic Concepts
Fundamental Modules
// Constant output module
module constant_output (
output logic one
);
assign one = 1'b1;
endmodule
// Zero output module
module zero_output (
output logic zero
);
assign zero = 1'b0;
endmodule
Wire Connections
// Signal passthrough
module signal_passthrough (
input in,
output out
);
assign out = in;
endmodule
// Multiple wire connections
module wire_connections (
input a, b, c,
output w, x, y, z
);
assign w = a;
assign x = b;
assign y = b;
assign z = c;
endmodule
Basic Gates
// NOT gate implementation
module not_gate (
input in,
output out
);
assign out = ~in;
endmodule
// AND gate implementation
module and_gate (
input a,
input b,
output out
);
assign out = a & b;
endmodule
// NOR gate implementation
module nor_gate (
input a,
input b,
output out
);
assign out = ~(a | b);
endmodule
// XNOR gate implementation
module xnor_gate (
input a,
input b,
output out
);
assign out = a ~^ b;
endmodule
Vector Operations
Vector Basics
// Vector handling
module vector_basic (
input [2:0] vec,
output [2:0] outv,
output o2,
output o1,
output o0
);
assign outv = vec;
assign o2 = vec[2];
assign o1 = vec[1];
assign o0 = vec[0];
endmodule
Vector Manipulation
// Byte selection
module byte_selector (
input [15:0] in,
output [7:0] upper_byte,
output [7:0] lower_byte
);
assign upper_byte = in[15:8];
assign lower_byte = in[7:0];
endmodule
// Vector reversal
module vector_reverse (
input [31:0] in,
output [31:0] out
);
assign out = {in[7:0], in[15:8], in[23:16], in[31:24]};
endmodule
Module Hierarchy
Module Instantiation
// Named port connection
module named_port (
input a,
input b,
output out
);
submodule u_sub (
.in1(a),
.in2(b),
.out(out)
);
endmodule
Sequential Module Chain
// Three-stage pipeline
module three_stage (
input clk,
input d,
output q
);
wire stage1, stage2;
dff_stage u1 (clk, d, stage1);
dff_stage u2 (clk, stage1, stage2);
dff_stage u3 (clk, stage2, q);
endmodule
Procedural Blocks
Combinational Logic
// Always block for combinational logic
module combo_logic (
input a,
input b,
output logic result
);
always_comb begin
result = a & b;
end
endmodule
Sequential Logic
// Clocked always block
module clocked_logic (
input clk,
input a,
input b,
output logic q
);
always_ff @(posedge clk) begin
q <= a ^ b;
end
endmodule
Conditional Logic
// If statement implementation
module conditional_logic (
input a,
input b,
input select1,
input select2,
output logic out
);
always_comb begin
if (select1 && select2)
out = b;
else
out = a;
end
endmodule
Case Statement
// Multiplexer using case
module case_mux (
input [2:0] sel,
input [3:0] data0,
input [3:0] data1,
input [3:0] data2,
input [3:0] data3,
input [3:0] data4,
input [3:0] data5,
output logic [3:0] out
);
always_comb begin
case (sel)
3'd0: out = data0;
3'd1: out = data1;
3'd2: out = data2;
3'd3: out = data3;
3'd4: out = data4;
3'd5: out = data5;
default: out = 4'b0000;
endcase
end
endmodule
Advanced Verilog Features
Ternary Operator
// Minimum finder
module minimum_finder (
input [7:0] a, b, c, d,
output [7:0] min_val
);
wire [7:0] min_ab, min_cd;
assign min_ab = (a < b) ? a : b;
assign min_cd = (c < d) ? c : d;
assign min_val = (min_ab < min_cd) ? min_ab : min_cd;
endmodule
Reduction Operators
// Parity calculator
module parity_calc (
input [7:0] in,
output parity
);
assign parity = ^in;
endmodule
Generate Blocks
// 100-bit adder using generate
module wide_adder (
input [99:0] a, b,
input carry_in,
output [99:0] sum,
output carry_out
);
wire [99:0] carries;
full_adder fa0 (.a(a[0]), .b(b[0]), .cin(carry_in), .sum(sum[0]), .cout(carries[0]));
genvar i;
generate
for (i = 1; i < 100; i++) begin : adder_loop
full_adder fi (.a(a[i]), .b(b[i]), .cin(carries[i-1]), .sum(sum[i]), .cout(carries[i]));
end
endgenerate
assign carry_out = carries[99];
endmodule
// Full adder sub-module
module full_adder (
input a, b, cin,
output sum, cout
);
assign {cout, sum} = a + b + cin;
endmodule
Combinational Circuits
Multiplexers
// 2-to-1 multiplexer
module mux2to1 (
input a, b,
input sel,
output out
);
assign out = sel ? b : a;
endmodule
// 256-to-1 multiplexer
module mux256to1 (
input [255:0] in,
input [7:0] sel,
output out
);
assign out = in[sel];
endmodule
// 4-bit wide 256-to-1 mux
module wide_mux256to1 (
input [1023:0] in,
input [7:0] sel,
output [3:0] out
);
assign out = in[sel*4 +: 4];
endmodule
Arithmetic Circuits
// Half adder
module half_adder (
input a, b,
output sum,
output carry
);
assign sum = a ^ b;
assign carry = a & b;
endmodule
// Full adder
module full_adder (
input a, b, cin,
output sum,
output cout
);
assign {cout, sum} = a + b + cin;
endmodule
// Signed overflow detection
module signed_adder (
input [7:0] a, b,
output [7:0] sum,
output overflow
);
assign sum = a + b;
assign overflow = (a[7] & b[7] & ~sum[7]) | (~a[7] & ~b[7] & sum[7]);
endmodule
Karnaugh Map Implementation
// 3-variable function
module kmap_3var (
input a, b, c,
output out
);
assign out = a | b | c;
endmodule
// 4-variable function
module kmap_4var (
input a, b, c, d,
output out
);
assign out = (~b & ~c) | (~a & ~d) | (a & c & d) | (b & c & d);
endmodule
Sequential Circuits
Latches and Flip-Flops
// D flip-flop with sync reset
module dff_sync_reset (
input clk,
input reset,
input [7:0] d,
output logic [7:0] q
);
always_ff @(posedge clk) begin
if (reset)
q <= 8'b0;
else
q <= d;
end
endmodule
// D flip-flop with async reset
module dff_async_reset (
input clk,
input areset,
input [7:0] d,
output logic [7:0] q
);
always_ff @(posedge clk or posedge areset) begin
if (areset)
q <= 8'b0;
else
q <= d;
end
endmodule
// D latch
module d_latch (
input d,
input enable,
output logic q
);
always_latch begin
if (enable)
q <= d;
end
endmodule
Counters
// 4-bit binary counter
module binary_counter (
input clk,
input reset,
output logic [3:0] count
);
always_ff @(posedge clk) begin
if (reset)
count <= 4'b0;
else
count <= count + 1;
end
endmodule
// Decade counter (0-9)
module decade_counter (
input clk,
input reset,
output logic [3:0] count
);
always_ff @(posedge clk) begin
if (reset)
count <= 4'b0;
else if (count < 9)
count <= count + 1;
else
count <= 4'b0;
end
endmodule
Shift Registers
// 4-bit shift register
module shift_reg_4bit (
input clk,
input areset,
input load,
input enable,
input [3:0] data,
output logic [3:0] q
);
always_ff @(posedge clk or posedge areset) begin
if (areset)
q <= 4'b0;
else if (load)
q <= data;
else if (enable)
q <= {1'b0, q[3:1]};
end
endmodule
// LFSR implementation
module lfsr_5bit (
input clk,
input reset,
output logic [4:0] q
);
always_ff @(posedge clk) begin
if (reset)
q <= 5'h1;
else begin
q <= {q[3:0], q[4] ^ q[2]};
end
end
endmodule
Finite State Machines
Simple FSMs
// Two-state FSM
module two_state_fsm (
input clk,
input reset,
input in,
output out
);
typedef enum logic [1:0] {
STATE_A = 2'b00,
STATE_B = 2'b01
} state_t;
state_t current_state, next_state;
always_ff @(posedge clk) begin
if (reset)
current_state <= STATE_B;
else
current_state <= next_state;
end
always_comb begin
case (current_state)
STATE_A: next_state = in ? STATE_A : STATE_B;
STATE_B: next_state = in ? STATE_B : STATE_A;
endcase
end
assign out = (current_state == STATE_B);
endmodule
Complex FSMs
// Lemmings behavior FSM
module lemmings_fsm (
input clk,
input areset,
input bump_left,
input bump_right,
input ground,
output logic walk_left,
output logic walk_right,
output logic falling
);
typedef enum logic [1:0] {
LEFT = 2'b00,
RIGHT = 2'b01,
FALL_L = 2'b10,
FALL_R = 2'b11
} state_t;
state_t state, next_state;
always_ff @(posedge clk or posedge areset) begin
if (areset)
state <= LEFT;
else
state <= next_state;
end
always_comb begin
case (state)
LEFT: next_state = ground ? (bump_left ? RIGHT : LEFT) : FALL_L;
RIGHT: next_state = ground ? (bump_right ? LEFT : RIGHT) : FALL_R;
FALL_L: next_state = ground ? LEFT : FALL_L;
FALL_R: next_state = ground ? RIGHT : FALL_R;
endcase
end
assign walk_left = (state == LEFT);
assign walk_right = (state == RIGHT);
assign falling = (state == FALL_L) || (state == FALL_R);
endmodule
Verification and Testbenches
Clock Generation
`timescale 1ns/1ps
module clock_generator;
reg clk;
initial begin
clk = 0;
forever #5 clk = ~clk;
end
dut test_dut (.clk(clk));
endmodule
Basic Testbench
`timescale 1ns/1ps
module basic_tb;
reg a, b;
wire out;
initial begin
a = 0; b = 0;
#10 a = 1;
#10 b = 1;
#10 a = 0;
#20 b = 0;
end
and_gate u_and (.a(a), .b(b), .out(out));
endmodule
Sequential Circuit Test
`timescale 1ns/1ps
module sequential_tb;
reg clk, reset, t;
wire q;
initial begin
clk = 0;
reset = 1;
t = 0;
#10 reset = 0;
#5 t = 1;
end
always #5 clk = ~clk;
t_flip_flop u_tff (.clk(clk), .reset(reset), .t(t), .q(q));
endmodule