0% found this document useful (0 votes)
25 views298 pages

1746025839080

The document is a comprehensive guide on Verilog, a Hardware Description Language essential for digital circuit design and verification. It targets students, job seekers, and professionals, offering a blend of theory, practical implementation, and over 200 interview questions. The book aims to provide conceptual clarity and real-world interview preparation, making it a valuable resource for aspiring VLSI and embedded systems engineers.

Uploaded by

santhosh mb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
25 views298 pages

1746025839080

The document is a comprehensive guide on Verilog, a Hardware Description Language essential for digital circuit design and verification. It targets students, job seekers, and professionals, offering a blend of theory, practical implementation, and over 200 interview questions. The book aims to provide conceptual clarity and real-world interview preparation, making it a valuable resource for aspiring VLSI and embedded systems engineers.

Uploaded by

santhosh mb
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 298

VeriCore VLSI Design

Preface

Introduction
Verilog is a Hardware Description Language (HDL) widely used in the design and veri-
fication of digital circuits, including FPGAs and ASICs. It enables designers to model,
simulate, and synthesize hardware systems from simple gates to complex SoCs. Under-
standing Verilog is a critical skill for any aspiring VLSI or embedded systems engineer.

Target Audience
This book is crafted for:

• Undergraduate and postgraduate students in Electronics, Electrical, and Computer


Engineering.

• Freshers preparing for VLSI job interviews and internship placements.

• Hobbyists and professionals looking to build or refresh their Verilog skills.

Rationale Behind Writing This Book


While many resources exist for learning Verilog, few strike a balance between conceptual
clarity and real-world interview preparation. This book aims to bridge that gap—serving
as both a learning companion and an interview guide, backed by years of academic expe-
rience and industry insights.

About the Book


"RTL to Real Job: Verilog Concepts & Interview Essentials" is a unique blend of theory,
practical implementation, and 200+ hand-picked interview questions. The content flows
logically from beginner topics to advanced modeling and simulation practices, ensuring a
smooth learning curve.

2
VeriCore VLSI Design

How to Use This Book


• Start with foundational chapters if you’re new to Verilog.

• Refer to summary sections and pro tips for quick revision.

• Use the interview questions for self-assessment and mock interviews.

• Build projects or snippets based on the solved examples to deepen understanding.

Salient Features
• 100+ conceptual explanations with real-world analogies.

• 200+ Verilog interview questions (without answers for challenge-based prep).

• LaTeX-formatted, professional layout suitable for academic use.

• Structured flow from RTL design to simulation and synthesis.

• Bonus “Pro Tips” and Mnemonics for memory aid.

Online Resources for Instructors


Instructors can request presentation slides, chapter-wise summaries, and editable quizzes
to accompany the book by emailing us at: infoex31@gmail.com

Online Resources for Students


Students can access:

• Code examples on GitHub (link to be added in next release)

• Free webinars via Vericore YouTube channel

• Go through NPTEL Lectures

3
VeriCore VLSI Design

Acknowledgement
I would like to express my heartfelt gratitude to everyone who encouraged me during the
creation of this book. A special thanks to Vishal Moladiya and Harekrishna Ray for
their invaluable guidance, peer reviews, and support. This book would not have reached
its current form without your honest feedback and motivation.

Feedback
Your suggestions and corrections are highly appreciated. Please share your feedback with
us at: infoex31@gmail.com

“From RTL to your first real job—this book is your companion in silicon success.”

4
Contents

Preface 2

Chapter 1: Overview of Digital Design with Verilog 9


1.1 Evolution of Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.2 Emergence as an Industry Standard . . . . . . . . . . . . . . . . . . . . . . 10
1.3 Typical Digital Design Flow . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.4 Importance of Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.5 Popularity and Trends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.6 Real-World Applications of Verilog . . . . . . . . . . . . . . . . . . . . . 11
1.7 Practice Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

Chapter 2: Hierarchical Modeling 14


2.1 Design Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2 Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3 Instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.4 Component of Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.5 Simulation Block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.6 Practice Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Chapter 3: Basic Concept 23


3.1 Lexical Conventions and Constants . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Lexical Conventions in Verilog . . . . . . . . . . . . . . . . . . . . . . . . 25
3.3 Data Types in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.4 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.5 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.6 Memories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.7 Parameters in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

5
Contents VeriCore VLSI Design

3.8 System Tasks and Functions . . . . . . . . . . . . . . . . . . . . . . . . . 33


3.9 Compiler Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Chapter 4: Modules and Ports 36


4.1 What is a Module? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.2 Types of Ports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.3 Port Connection Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.4 Hierarchical Name Referencing . . . . . . . . . . . . . . . . . . . . . . . . 39

Chapter 5: Gate Level Modelling 42


5.1 Gate Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.2 Gate Delays in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.3 Gates with Different Delays . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.4 Practice and Interview Questions . . . . . . . . . . . . . . . . . . . . . . . 45
5.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

Chapter 6: Data Flow Modelling 47


6.1 Continuous Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
6.2 Delays in Dataflow Modeling . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.3: Expression Operators and Operands . . . . . . . . . . . . . . . . . . . . . 56
6.4 20 Solved Examples (Problems with Solutions) . . . . . . . . . . . . . . . 60
6.5 Practice Questions (30 Problems) . . . . . . . . . . . . . . . . . . . . . . . 64
6.6 Pro Tips for Dataflow Modeling . . . . . . . . . . . . . . . . . . . . . . . 66
6.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

Chapter 7: Behavioral Modeling 71


7.1 Structured Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2 Procedural Assignment (Blocking and Non-Blocking Assignments) . . . . 78
7.3 Conditional Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.4 Multiway Branching in Verilog . . . . . . . . . . . . . . . . . . . . . . . . 83
7.5 Loops in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
7.6 Case Statements in Verilog (case, casex, casez) . . . . . . . . . . . . . . . 87
7.7 Loops in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
7.8 Sequential and Parallel Blocks . . . . . . . . . . . . . . . . . . . . . . . . 93
7.9 Timing and Event Control in Behavioral Modeling . . . . . . . . . . . . . 97
7.10 Summary of Behavioral Modeling in Verilog . . . . . . . . . . . . . . . . 100

6
Contents VeriCore VLSI Design

Chapter 8: Task and Function 102


8.1 Tasks in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.2 Functions in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
8.3 20 Examples of Tasks and Functions in Verilog . . . . . . . . . . . . . . . 109
8.4 30 Practice and Interview Questions on Tasks and Functions . . . . . . . . 115
8.5 Pro Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
8.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Chapter 9 : Useful Modelling Technique 121


9.1 Procedural Continuous Assignment . . . . . . . . . . . . . . . . . . . . . . 121
9.2 Conditional Compilation and Execution . . . . . . . . . . . . . . . . . . . 123
9.3 Timescale Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
9.4 Value Change Dump (VCD) File in Verilog . . . . . . . . . . . . . . . . . 130
9.5 10 Practical Examples of Useful Modeling Techniques . . . . . . . . . . . 133
9.6 30 Practice and Interview Questions . . . . . . . . . . . . . . . . . . . . . 137
9.7 Pro Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

Chapter 10 : Finite State Machines (FSM) in Verilog 140


10.1 What is an FSM? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.2 Types of FSMs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
10.3 Moore FSM in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
10.4 Melay FSM in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
10.5 FSM Coding Styles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
10.6 State Encoding Techniques . . . . . . . . . . . . . . . . . . . . . . . . . 150
10.7 FSM Design Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
10.8 Practice and Interview Questions . . . . . . . . . . . . . . . . . . . . . . 156
10.9 Pro Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
10.10 Mindmap: FSM Design Concepts . . . . . . . . . . . . . . . . . . . . . 159

Chapter 11: Memory Modeling in Verilog 160


11.1 Memory Declaration and Types . . . . . . . . . . . . . . . . . . . . . . . 161
11.2 Read and Write Operations . . . . . . . . . . . . . . . . . . . . . . . . . 163
6.1 Continuous Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
11.4 Testbench for 2R1W Register File . . . . . . . . . . . . . . . . . . . . . . 169
11.5 Summary and Pro Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Chapter 12: User Defined Primitive (UDP) 173


12.1 Theory and Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
12.2 Practice and Interview Questions . . . . . . . . . . . . . . . . . . . . . . 176

7
Contents VeriCore VLSI Design

Chapter 13: Event Scheduler 179


13.1 Detailed Theory with Flowchart . . . . . . . . . . . . . . . . . . . . . . . 180
13.2 Example: Event Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . 181

Chapter 14: Efficient Testbench Writing 184


14.1 Testbench Examples with Theory . . . . . . . . . . . . . . . . . . . . . . 185
14.2 Practice and Interview Questions . . . . . . . . . . . . . . . . . . . . . . 192
14.3 Pro Tips for Efficient Testbench Writing . . . . . . . . . . . . . . . . . . 194
14.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195

Chapter 15: 200 Verilog Interview Questions (Without Answers) 196


15.1 Questions 1–40: Verilog Basics and Syntax . . . . . . . . . . . . . . . . . 196
15.2 Questions 41–202: Modeling, Operators, and Control Structures . . . . . . 198

Chapter 16 : Problems with Solutions 206

A Commonly Used Verilog Syntax 325

B Tools and Simulators 326

C Online Resources for Learning 327

D Interview Preparation Tips 328

E Recommended Books 331

F Final Note to Readers 332

8
Chapter 1 : Overview of Digital Design
with Verilog

Introduction
Verilog is a Hardware Description Language (HDL) that provides a means to describe,
simulate, and synthesize digital systems such as microprocessors, memory units, and cus-
tom ASICs. This chapter presents a comprehensive overview of digital design through the
lens of Verilog.

Learning Objectives
By the end of this chapter, you should be able to:
• Understand the history and rise of Verilog.
• Describe the standard digital design workflow.
• Recognize Verilog’s role in modern hardware design.
• Identify current trends in HDL-based development.

1.1 Evolution of Verilog


Verilog was developed in 1984 by Gateway Design Automation and later acquired by
Cadence Design Systems. Its simplicity and resemblance to C helped make it a favorite
among designers.
Pro Tip
This is a helpful tip using the reusable style option.

9
Chapter 1 Overview of Digital Design with Verilog

Pro Tip: If you know C or JavaScript, Verilog’s syntax will feel familiar—making the
learning curve smoother!
In 1995, Verilog was standardized as IEEE 1364. The evolution continued with en-
hancements in Verilog-2001 and later SystemVerilog, which added features for testbenches,
assertions, and classes.

1.2 Emergence as an Industry Standard


With increasing design complexity, traditional schematic design became infeasible. Ver-
ilog allowed abstraction, modularity, and rapid simulation. Its ability to describe systems
behaviorally and structurally set a new industry norm.

1.3 Typical Digital Design Flow


The Verilog-based design flow can be visualized in the following flowchart:

1. Specification: Define system behavior

2. Modeling: Write Verilog code at RTL level

3. Simulation: Verify logi-


cal correctness with testbenches

4. Synthesis: Convert RTL


to gate-level representation

5. Implementation: Place and


route logic on target device

6. Fabrication: Manufac-
ture chip or burn into FPGA

7. Testing: Validate with real-time data

10
Chapter 1 Overview of Digital Design with Verilog

Pro Tip
Mnemonic Trick: “Smart Men Simulate Systems In Fabricated
Factories” — One word per step in the design flow.

1.4 Importance of Verilog


Verilog’s significance lies in its:

• High simulation speed and tool compatibility.

• Versatile use in behavioral, dataflow, gate-level, and switch-level modeling.

• Built-in support for testbenches and assertions.

• Compact syntax for describing complex digital structures.

1.5 Popularity and Trends


More than 90% of modern ASIC/FPGA design workflows use Verilog or SystemVerilog.
Its enduring presence is because of:

• Industry-standard simulation tools like ModelSim, VCS, and XSIM.

• Integration with high-level verification methodologies like UVM.

• Use in RISC-V processor design, AI accelerators, and SoC validation.

Pro Tip
Career Tip: Verilog is your ticket to internships and full-time VLSI roles. Start projects
and share them on GitHub and LinkedIn!

1.6 Real-World Applications of Verilog


• Designing pipelined CPUs and GPUs

• Building finite state machines (FSMs)

• Coding digital filters and communication IPs

11
Chapter 1 Overview of Digital Design with Verilog

• Modeling and synthesizing memory blocks

• Implementing RISC-V cores from scratch

1.7 Practice Questions


Theory
1. Describe the historical evolution of Verilog.

2. What are the major milestones in Verilog standardization?

3. Explain why simulation precedes synthesis.

4. List and describe the steps in digital design flow.

5. Discuss the impact of Verilog on modern VLSI systems.

Output-Based
1. Predict the behavior of a Verilog ‘always‘ block with blocking assignment.

2. Determine the output of a simple 2-input gate module.

3. Given a waveform, identify the corresponding Verilog construct.

4. Debug a snippet of Verilog code and point out errors.

5. Analyze the simulation result with ‘x‘ and ‘z‘ values.

Summary
• Verilog is a widely used HDL for modeling digital systems.

• Understanding its flow and structure is crucial for hardware design.

• It provides flexibility across abstraction levels.

12
Chapter 1 Overview of Digital Design with Verilog

Pro Tip
Final Insight: Focus on simulation and modeling first. Don’t rush into synthesis—get
your logic right!

Learning Outcome Recap:

1. You now understand the complete Verilog design flow.

2. You are aware of real-world uses and career impact of Verilog.

3. You can identify common trends and tools in the industry.

“Digital design begins with logic—but thrives on imagination.”

13
Chapter 2: Hierarchical Modeling

Introduction
Hierarchical modeling is a foundational concept in digital design, where systems are bro-
ken down into smaller, manageable components called modules. This enables the de-
signer to approach complex problems with modular design principles, enhancing readabil-
ity, reusability, and scalability of Verilog code.
Verilog’s support for hierarchy allows us to:

• Organize complex circuits in a structured way.

• Simulate individual blocks or the entire system.

• Encourage top-down and bottom-up design methodologies.

Learning Objectives
• Understand the principle and benefits of hierarchical modeling.

• Learn how to define and instantiate modules in Verilog.

• Explore simulation block components within a hierarchy.

• Identify best practices in structuring a Verilog project.

2.1 Design Methodology


Verilog supports both:

14
Chapter 2 Hierarchical Modeling

• Top-down design: Starting with the system-level architecture, we decompose the


design into smaller modules.

• Bottom-up design: Smaller blocks are designed first, then integrated to form the
complete system.

Top-Level System

Module A Module C

Module B

Figure 1: Hierarchical Block Diagram (Top-Down Design)

Pro Tip
Pro Tip: Modularize your code as early as possible! This helps you simulate and debug
each block independently.

Benefits of Hierarchical Design


• Easier to debug and simulate.

• Encourages code reuse across projects.

• Enhances readability and team collaboration.

Analogy:
Imagine you’re building a car. You wouldn’t design it as one massive blueprint—you’d
create separate designs for the engine, wheels, and electronics, then assemble them. That’s
hierarchical modeling in action!

15
Chapter 2 Hierarchical Modeling

2.2 Module
A module is the fundamental building block in Verilog. Every hardware component or
system is described as a module. It may represent a logic gate, an ALU, or even a full
CPU.

Syntax of a Module
module module_name (input_ports, output_ports);
// declarations
// functionality
endmodule

Example: Basic AND Gate Module


module and_gate (
input wire a,
input wire b,
output wire y
);
assign y = a & b;
endmodule

Pro Tip
Pro Tip: Always use meaningful names for ports and modules. It helps when you
debug large designs!

2.3 Instance
Instantiation is the process of using one module inside another. You can think of it like
calling a function in programming—only here, you’re plugging in hardware blocks.

Analogy:
If a module is a blueprint of a house, instantiation is like building actual houses from
the same blueprint but placing them in different locations with different paint colors or
features.

16
Chapter 2 Hierarchical Modeling

Syntax for Instantiation


module_name instance_name (
.port1(signal1),
.port2(signal2)
);

Example: Instantiating and_gate


module top_module (
input wire p, q,
output wire r
);
and_gate u1 (
.a(p),
.b(q),
.y(r)
);
endmodule

Pro Tip
Pro Tip: Prefix your instance names (like u1, inst_) to track them easily during
simulation and debugging.

Nesting Modules (Multilevel Hierarchy)


Modules can instantiate other modules which can, in turn, instantiate others—forming a
hierarchy tree.

Best Practices
• Keep each module focused on a single function.

• Use parameters for module customization.

• Ensure ports and signal types match during instantiation.

17
Chapter 2 Hierarchical Modeling

Top Module

Control Unit ALU

Decoder Adder

Figure 2: Multi-level Hierarchical Modeling

2.4 Component of Simulation


Verilog simulation involves several key components that work together to mimic the be-
havior of the digital system.

1. Design Under Test (DUT)


This is the core Verilog module being tested in the simulation.

2. Testbench
A non-synthesizable module that drives the inputs to the DUT and monitors the outputs.

3. Stimulus Generator
Provides changing input values to the DUT to validate different functionalities.

4. Monitor
Watches the output signals of the DUT and logs or displays them.

5. Checker
Compares DUT outputs with expected values and flags errors.

18
Chapter 2 Hierarchical Modeling

Pro Tip
Pro Tip: Break your testbench into generator, monitor, and checker blocks
for better modularity and reuse.

Testbench DUT

Stimulus Generator Monitor


Checker

Figure 3: Simulation Components Interconnection

2.5 Simulation Block


The simulation block is a Verilog section that controls simulation timing, value changes,
and procedural events. The most common simulation blocks are:

1. initial Block
Executes once at simulation start.

initial begin
// Simulation-only behavior
end

2. always Block
Executes indefinitely in a loop as long as simulation runs.

always @(posedge clk) begin


// Repetitive behavior
end
Pro Tip
Trick to Remember:
initial – like a “main()” in C, runs once.
always – like a “while(1)” loop, runs forever!

19
Chapter 2 Hierarchical Modeling

3. Delay and Event Control


Delays (#) and event controls (@) let you mimic timing behavior:

#10 a = 1; // wait 10 time units


@(posedge clk); // wait for positive clock edge

4. Simulation Time Units


Simulation operates on virtual time units defined by ‘timescale‘:

‘timescale 1ns/1ps

Common Use-Cases
• Apply stimulus to DUT

• Monitor output waveforms

• Model real-world delays

Pro Tip
Pro Tip: Use waveform viewers (like GTKWave) to visualize the simulation time-
line—great for debugging!

2.6 Practice Questions


Theoretical Questions
1. What is hierarchical modeling in Verilog?

2. Explain the structure of a Verilog module.

3. Describe the process of instantiating one module into another.

4. What is the purpose of simulation in Verilog?

5. Compare and contrast the initial and always blocks.

20
Chapter 2 Hierarchical Modeling

Code-Based Questions
1. Write a Verilog code for a 4-bit ripple carry adder using hierarchical modules.

2. Modify a testbench to toggle the reset signal after 10 time units.

3. Create a module and instantiate it twice in a top-level design.

4. Use delays and event controls to simulate a D Flip-Flop.

5. Debug a hierarchical design with incorrect instance connections.

Pro Tip
Pro Tip: For each Verilog module you write, create a testbench that stimulates *all*
input cases for maximum coverage.

2.7 Summary
In this chapter, we explored hierarchical modeling in Verilog, one of the most powerful
ways to scale designs. Here’s what we covered:

• Modules in Verilog are like reusable building blocks.

• Hierarchy is established by instantiating modules within other modules.

• The simulation process requires a testbench, a DUT, and simulation tools.

• initial and always blocks form the heart of Verilog simulations.

• Delays and event controls allow temporal modeling.

Pro Tip
Trick: Always begin designing from the bottom-up (build modules) or top-down (de-
fine structure first)—but never both at the same time!

21
Chapter 3 Basic Concepts

Learning Outcomes
• Understand and use hierarchical modeling in Verilog.

• Create, instantiate, and simulate Verilog modules.

• Use simulation blocks like initial, always, and delays properly.

• Build structured testbenches that interact with DUTs efficiently.

“Think modular, code reusable, simulate always — that’s the Verilog way!”

22
Chapter 3: Basic Concept

Introduction
In digital design, mastering Verilog begins with understanding its basic building blocks.
This chapter covers the essential syntax, data types, variables, and structures used to write
functional and efficient code. A solid grasp of these concepts is vital before diving into
more complex design styles.

Learning Objectives
• Understand the lexical rules and conventions used in Verilog.

• Learn about different Verilog data types and their applications.

• Explore arrays, memories, vectors, and parameters in detail.

• Discover system tasks and compiler directives for efficient modeling.

3.1 Lexical Conventions and Constants


Verilog uses a syntax style similar to C. The following are some key lexical elements:

3.1.1 Escape Sequences


• \n – New Line

• \t – Horizontal Tab

• \b – Backspace

23
Chapter 3 Basic Concepts

Pro Tip
Use escape sequences while printing strings using system tasks like $display for
formatting output.

3.1.2 Special Values


Verilog uses two special values:
• x (unknown) – Represents an unknown logic value.
• z (high impedance) – Represents a floating or disconnected signal.

3.1.3 Signed vs Unsigned Numbers


By default, numbers in Verilog are unsigned. Use the signed keyword to explicitly
define signed variables.

reg signed [7:0] a; // Signed 8-bit number


reg [7:0] b; // Unsigned 8-bit number

3.1.4 Negative Numbers and Constants


Verilog supports negative constants using two’s complement representation:
reg signed [3:0] neg = -4; // stored as 1100

3.1.5 Strings and Identifiers


Strings are enclosed in double quotes:
$display("Hello, Verilog!");
Identifiers must begin with a letter or underscore and can contain letters, digits, under-
scores, or escaped characters:
reg [3:0] _a1; // valid
reg \abc 123; // escaped identifier
Pro Tip
Analogy: Think of ‘x‘ as a wire in smoke (uncertain) and ‘z‘ as a wire in air (discon-
nected)!

24
Chapter 3 Basic Concepts

3.1.6 Example: Handling Special Values


module special_val;
reg x, y, z;
initial begin
x = 1’bx; // unknown
y = 1’bz; // high impedance
$display("x = %b, y = %b", x, y);
end
endmodule

Verilog Special States


x = Unknown z = High-Z

Figure 4: Verilog ’x’ and ’z’ States

3.2 Lexical Conventions in Verilog


Lexical conventions define the basic language structure of Verilog. This includes whites-
pace, comments, identifiers, literals, operators, and more.

3.2.1 Whitespace Characters


Verilog ignores whitespace characters unless they are inside strings. Common whitespace
characters include:

• \n – Newline

• \t – Tab

• \b – Backspace

Pro Tip
Use whitespace generously to improve code readability. Although Verilog ignores it,
humans don’t!

25
Chapter 3 Basic Concepts

3.2.2 Comments
Verilog supports two types of comments:

• // Single-line comment

• /* Multi-line comment */

3.2.3 Identifiers and Escape Sequences


Identifiers name modules, variables, functions, etc. They must begin with a letter or un-
derscore and can include digits and underscores. Escape identifiers start with a backslash
and are followed by whitespace.

// Valid identifiers:
reg clk_1;
wire _enable;
integer \abc$def; // Escape identifier

3.2.4 Literals
Verilog literals can be signed or unsigned, and may also include undefined or high-impedance
states.
Examples:

• 4’b1010 – 4-bit binary number

• 8’hA3 – 8-bit hexadecimal number

• 6’d45 – 6-bit decimal number

3.2.5 Signed and Unsigned


By default, Verilog numbers are unsigned unless declared otherwise.
“‘verilog reg signed [7:0] num;

Pro Tip
Unsigned numbers roll over on overflow. Use signed when dealing with negative values!

26
Chapter 3 Basic Concepts

3.2.6 Special Values: x and z


• x – Unknown (used for simulation, uninitialized registers)

• z – High impedance (used in tri-state buffers)

3.2.7 Negative Numbers and Strings

Start Reading Code

Ignore Whitespace

Parse Identifiers

Parse Literals

Handle Comments

Lexical Analysis Done

Figure 5: Lexical Convention Flow in Verilog

3.3 Data Types in Verilog


Verilog provides several built-in data types to represent hardware signals and variables.
Understanding them is crucial for proper modeling and simulation.

27
Chapter 3 Basic Concepts

3.3.1 Net Type


Net types represent physical connections between components. They cannot store a value;
instead, they reflect the value being driven onto them.

• Common types: wire, tri, wand, wor

• No need to assign in procedural blocks

wire clk; // Clock signal


wire [3:0] data; // 4-bit bus

3.3.2 Reg Type


Reg is not a physical register. It holds a value assigned in a procedural block (like always
or initial).

reg clk;
reg [7:0] count;

Pro Tip
Use reg inside procedural blocks and wire outside them for connections!

3.3.3 Integer Type


Integer is a 32-bit signed data type used primarily for loop counters and calculations.

integer i;

Note: Can be used in loops but not synthesizable for hardware mapping.

3.3.4 Real Type


Used to represent floating-point values, mainly for testbenches.

real pi;
initial pi = 3.14159;

28
Chapter 3 Basic Concepts

3.3.5 Time Type


Used to store simulation time.

time delay;
delay = $time;


Difference Table

Type Usage Storage


wire Connection No
reg Procedural code Yes
integer Counters, calc Yes (32-bit signed)
real Decimal values Yes (testbenches only)
time Simulation time Yes (64-bit unsigned)
Table 1: Difference Between Common Data Types

Pro Tip
Always assign reg in initial or always blocks. Use assign only for wire
types.

Input Signal

Wire

Reg in Always Block

Output

Figure 6: Data Flow using Wire and Reg

29
Chapter 3 Basic Concepts

3.4 Vectors
In Verilog, vectors are used to represent buses or multi-bit signals. A vector groups multi-
ple scalar wires or regs into a single entity.

3.4.1 Syntax
wire [3:0] data; // 4-bit vector (data[3] down to data[0])
reg [7:0] count; // 8-bit register

Note: The index is specified as [MSB:LSB]. Verilog supports both big-endian (MSB
to LSB) and little-endian declarations.
Pro Tip
Tip: When using vectors, always double-check bit ordering. [7:0] counts from 7
down to 0!

3.4.2 Accessing Bits


assign data[0] = 1’b1;
assign data[3:2] = 2’b10;

3.5 Arrays
Verilog supports arrays of regs or nets (from Verilog-2001 onward). Arrays help in orga-
nizing repetitive hardware like registers, memory banks, etc.

3.5.1 1D Array Example


reg [7:0] register_file [0:15]; // 16 registers, each 8-bit wide

3.5.2 2D Array Example


reg [3:0] mem_2d [0:3][0:3]; // 4x4 4-bit matrix

Access:

30
Chapter 3 Basic Concepts

register_file[2] = 8’hFF;
mem_2d[1][2] = 4’b1010;

Pro Tip
Analogy: Think of a 2D array like an Excel sheet with rows and columns storing digital
data.

3.6 Memories
In Verilog, a memory is essentially a one-dimensional array of vectors.

3.6.1 Declaration
reg [7:0] memory [0:255]; // 256 locations, each 8-bit wide

3.6.2 Read/Write Operations


initial begin
memory[0] = 8’b10101010; // Write
$display("Data at mem[0] = %b", memory[0]); // Read
end

3.6.3 Synchronous Read Example


always @(posedge clk) begin
data_out <= memory[addr]; // Read on clock edge
end

Pro Tip
Pro Tip: Verilog memories do not support multi-port access by default — you must
model it!


Block Diagram – Memory Block Access

31
Chapter 3 Basic Concepts

Clock

Address (addr) Memory [0:255] Data Out

Figure 7: Simple Memory Access with Clock and Address

3.7 Parameters in Verilog


Parameters are constants used for defining values that can be changed during module in-
stantiation. They’re extremely useful for making modules reusable and configurable.

3.7.1 Syntax
parameter WIDTH = 8;
reg [WIDTH-1:0] data_bus;

3.7.2 Parameter Overriding


Parameters can be overridden using:

1. Named Parameter Override

my_module #(.WIDTH(16)) inst1 (...);

2. Positional Parameter Override

my_module #(16) inst2 (...);

3.7.3 Local Parameters


Local parameters cannot be overridden outside the module.

localparam MAX_SIZE = 256;

32
Chapter 3 Basic Concepts

3.7.4 defparam Usage


Legacy method of changing parameter values (not recommended in SystemVerilog):

defparam inst1.WIDTH = 32;

Pro Tip
Pro Tip: Always prefer named parameter overriding. Avoid using defparam in mod-
ern Verilog for better readability and tool support.

3.8 System Tasks and Functions


System tasks in Verilog begin with a $ and are used for simulation purposes like displaying
values, writing to files, or monitoring changes.

3.8.1 Common System Tasks


• $display – Displays a message.

• $monitor – Monitors changes and displays them.

• $finish – Ends simulation.

• $stop – Stops simulation for debugging.

• $time – Current simulation time.

initial begin
$display("Simulation starts at time %t", $time);
$monitor("a = %b, b = %b, out = %b", a, b, out);
end

3.9 Compiler Directives


Compiler directives start with a backtick (‘) and guide the compiler during simulation.

33
Chapter 3 Basic Concepts

3.9.1 Important Directives


• ‘define – Used to define a macro.

• ‘ifdef, ‘endif – Conditional compilation.

• ‘include – Include another Verilog file.

3.9.2 Example
‘define WIDTH 8
reg [‘WIDTH-1:0] my_bus;

Pro Tip
Trick to Remember: Think of ‘define like a search-and-replace command for your
code!


Practice Questions

3.9.3 Theoretical Questions


1. What is the difference between reg and wire?

2. How are parameters and localparams different?

3. Describe the usage of arrays and vectors in Verilog.

4. Explain how a memory block is read and written.

5. Differentiate between $display and $monitor.

3.9.4 Predict the Output


// Q1
reg [3:0] a;
initial begin
a = 4’b1100;
$display("a[2] = %b", a[2]);
end

34
Chapter 3 Basic Concepts

// Q2
parameter WIDTH = 4;
reg [WIDTH-1:0] b;
initial begin
b = 4’b1010;
$display("b = %b", b);
end


Summary

• Lexical conventions include special characters like , , and identifiers.

• Vectors represent multi-bit signals; arrays group similar data types.

• Memories store multiple data locations and are used for RAM/ROM models.

• Parameters increase reusability and flexibility of modules.

• System tasks like $display, $monitor are essential for simulation output.

• Compiler directives optimize your code compilation process.

Learning Outcome:

• You can now differentiate between data types and storage styles in Verilog.

• You know how to use parameters and directives effectively.

• You can apply arrays, vectors, and system tasks in simulation.

“In Verilog, simplicity lies in structure — think in modules, wires, and clocks.”

35
Chapter 4: Modules and Ports

Introduction
Verilog’s design structure is fundamentally based on the use of modules. Each design unit
is modeled as a module, containing ports for communication, and internal logic to define
its functionality. This modularity promotes reuse, readability, and scalability in digital
system design.

Learning Objectives
• Understand the structure and importance of Verilog modules.

• Learn the types of ports and how to use them effectively.

• Explore valid and invalid ways of port connection with examples.

• Understand hierarchical naming conventions in Verilog.

4.1 What is a Module?


A module in Verilog defines a hardware block. It is the basic building block and can
represent anything from a simple gate to a complex processor.

4.1.1 Syntax
verilog module (module name) (port list);
// Declarations
// Functionality

36
Chapter 4 Modules and Ports

endmodule

4.1.2 Example 1: AND Gate Module


module andgate ( input wire a, input wire b, output wire y ); assign y = a & b;
endmodule
Pro Tip
Pro Tip: Think of modules like LEGO blocks — you can build anything by combining
simple, reusable pieces!

4.2 Types of Ports


Ports are module interfaces used to interact with the external environment.

• Input: Takes signals into the module.

• Output: Sends signals out from the module.

• Inout: Bi-directional port.

4.2.1 Example 2: Using All Types of Ports


verilog Copy Edit module bidirexample(input a, output y, inout data); assign y = a; end-
module

4.3 Port Connection Rules


To avoid errors in module instantiations, Verilog defines certain rules:

4.3.1 1. Matching Port Widths


The widths of the connected signal and the port must match.

4.3.2 2. Matching Port Directions


Connecting an output to another output is not valid.

37
Chapter 4 Modules and Ports

4.3.3 3. Proper Data Types


The data type of the connected signal should be compatible with the port declaration.

Diagram: Port Connection

Input Output
Module
Inout

Figure 8: Valid port connections for input, output, and inout

Pro Tip
Pro Tip: Always declare port directions explicitly! Verilog infers wires by default —
which may cause synthesis issues if not declared correctly.

Connecting Port to External Signal


A port in Verilog connects the internal logic of a module to external signals. There are two
ways to connect ports:

• Positional Association: The ports are connected in the order they are defined.

• Named Association: The ports are explicitly named during instantiation.

Example: Positional Connection


1 module full_adder (a, b, cin, sum, cout);
2 input a, b, cin;
3 output sum, cout;
4 assign {cout, sum} = a + b + cin;
5 endmodule
6
7 module top;
8 wire x, y, z, s, c;

38
Chapter 4 Modules and Ports

9 full_adder fa1(x, y, z, s, c); // Positional mapping


10 endmodule

Example: Named Connection


1 module top;
2 wire x, y, z, s, c;
3 full_adder fa1(
4 .a(x),
5 .b(y),
6 .cin(z),
7 .sum(s),
8 .cout(c)
9 );
10 endmodule

Pro Tip
Pro Tip: Prefer named associations for better readability and error prevention, espe-
cially in large designs.

4.4 Hierarchical Name Referencing


Verilog allows access to sub-modules using a path of module and instance names. This is
called hierarchical referencing.
Syntax:
<topmodule>.<submodule>.<signal>

Example:
1

2 module top;
3 wire d, clk, q;
4 dff d1 (.d(d), .clk(clk), .q(q));
5 endmodule

If you want to monitor signal q inside dff, you can refer to it as:
verilog top.d1.q

39
Chapter 4 Modules and Ports

Pro Tip
Pro Tip: Avoid writing to hierarchical signals. Hierarchical referencing is best used for
monitoring, not design.

Practice Questions
Theoretical:

1. What are the different ways to connect ports in Verilog?

2. Explain hierarchical referencing with an example.

3. Why are illegal port connections dangerous in synthesis?

4. How do named associations help in avoiding errors?

Predict the Output:

1. Given a module with positional vs named connection, identify errors.

2. What happens if a port is left unconnected?

3. Trace output of a basic full adder using port mapping.

4. Write the hierarchical path to access a flip-flop’s output in nested modules.

Summary
• Modules are the building blocks of Verilog designs.

• Ports allow interfacing between modules and external signals.

• Use named associations for clarity and safety.

• Hierarchical referencing allows access to deep-level signals.

• Illegal connections can break simulation or synthesis behavior.

40
Chapter 4 Modules and Ports

Learning Outcome:

1. Understand how to define and instantiate modules.

2. Clearly differentiate between legal and illegal port connections.

3. Master the skill of connecting modules with signals using ports.

4. Access internal signals using hierarchical paths safely.

“Modular design is the art of building complexity from simplicity.”

41
Chapter 5: Gate Level Modelling

Introduction
Gate-level modelling represents the most basic level of abstraction in digital design. It
deals directly with logic gates and their interconnections. This style is essential for under-
standing how synthesized logic maps onto physical gates.

Learning Objectives
• Understand the different types of logic gates available in Verilog.

• Learn how to create gate-level circuits using built-in primitives.

• Explore gate delays and their use in timing simulation.

• Analyze Verilog modules through examples and diagrams.

5.1 Gate Types


Verilog provides predefined primitives for various logic gates:

• and, nand – AND, NAND gates

• or, nor – OR, NOR gates

• xor, xnor – XOR, XNOR gates

• not – Inverter

• buf – Buffer

42
Chapter 5 Gate Level Modelling

Truth Table for Common Gates


A B A AND B A OR B
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 1

Pro Tip
Pro Tip: Think of gates as mathematical functions. An AND gate is like multiplication:
1 * 1 = 1, everything else is 0.

Circuit Diagram for AND Gate


A
Y
B

Truth Tables of Basic Logic Gates


A B AND (A & B) OR (A | B) XOR (A B̂) NAND ( (A & B))
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 1
1 1 1 1 0 0

Pro Tip
Trick to Remember:
Think of AND as "both must be true", OR as "either can be true", XOR as "only
one must be true", and NAND as "AND but inverted".

Circuit Diagram for OR Gate


A
Y
B

43
Chapter 5 Gate Level Modelling

Other Common Gate Types


• NAND Gate: Inverted output of AND. High output unless both inputs are high.

• NOR Gate: Inverted output of OR. Output is high only when both inputs are low.

• XNOR Gate: Inverted output of XOR. True when inputs are equal.

Pro Tip
Hardware Hint:
NAND and NOR gates are known as Universal Gates — any digital logic can be im-
plemented using just these two!

5.2 Gate Delays in Verilog


Gate delays allow modeling the propagation delay of logic gates in Verilog. They simulate
the real-world behavior of circuits, where signals do not propagate instantaneously. You
can use the ‘#‘ symbol to introduce a delay in the output.
1 module and_gate_delay(output y, input a, b);
2 assign #5 y = a & b;
3 endmodule

Listing 1: AND Gate with 5 Time Unit Delay

Explanation
The output will update 5 time units after both inputs become valid. Use this in
testbenches to visualize delays.

5.3 Gates with Different Delays


1. OR Gate Delay:
1 module or_gate_delay(output y, input a, b);
2 assign #3 y = a | b;
3 endmodule

2. NOT Gate Delay:

44
Chapter 5 Gate Level Modelling

1 module not_gate_delay(output y, input a);


2 assign #2 y = ~a;
3 endmodule

3. NAND Gate with Rise and Fall Delay:


1 module nand_delay(output y, input a, b);
2 assign #(2, 4) y = ~(a & b); // rise = 2, fall = 4
3 endmodule

Pro Tip
Use multiple delay values to model real-world rise and fall transitions of gates.

5.4 Practice and Interview Questions


Theoretical Questions:

1. Explain the difference between primitive and derived gates in Verilog.

2. What are the possible values that a signal can take in Verilog?

3. Describe gate delays and their usage.

4. Why are gate delays ignored during synthesis?

5. Explain the importance of gate-level modeling in the VLSI design cycle.

Output Prediction Questions:

1. Predict the output of an AND gate with a 5-time unit delay.

2. Given a NOT gate connected to a wire initialized to 1, what will be the delayed
output?

3. Trace the waveform of a 2-input NAND gate over a 10-time unit simulation.

4. Modify an OR gate to introduce two types of delays (rise and fall).

5. Identify the error in a module using gate delays.

45
Chapter 5 Gate Level Modelling

Hands-On Coding Tasks:


1. Implement an XOR gate with a delay of 2 units.
2. Create a testbench for a NAND gate with delays.
3. Model a 2-to-1 MUX using gate-level primitives.
4. Use waveform viewer to visualize the delay in NOT gates.
5. Modify a 3-input AND gate to include a 1 unit propagation delay.
Pro Tip
In waveform viewers (like GTKWave or ModelSim), gate delays help visualize tim-
ing, races, and glitches. Always simulate your design even if delays are not synthe-
sized.

5.5 Summary
• Gate-level modeling represents logic using basic gates such as AND, OR, NOT,
NAND, NOR, XOR, and XNOR.
• Verilog allows incorporating delays using the # operator.
• Truth tables and diagrams are essential for understanding gate operations.
• Proper modeling of gates ensures accurate simulation and functional verification.
• Gate delays help visualize real-world signal behavior during simulation.

Learning Outcome:

1. Identify and model different logic gates in Verilog.

2. Apply gate delays and understand their impact on simulation.

3. Interpret gate-level design through truth tables and circuit diagrams.

“Logic gates are the atoms of digital design — master them to build anything!”

46
Chapter 6: Data Flow Modelling

Introduction

Dataflow modeling is one of the core abstraction styles used in Verilog to describe how
data moves through a design using continuous assignments. Unlike gate-level or behav-
ioral modeling, dataflow emphasizes *how data flows* between signals based on logical
or arithmetic operations, without explicitly describing how it’s implemented.

What is Dataflow Modelling?


Dataflow modeling in Verilog is used to describe the functionality of a circuit in
terms of how data moves from input to output using continuous assignments (using
‘assign‘ keyword).

47
Chapter 6 Data Flow Modelling

Figure 9: Dataflow modeling concept

Why Dataflow Modeling?

• It abstracts away structural and timing details.

• Helps model combinational logic efficiently.

• Useful for arithmetic and logical operations.

• Enables simulation of timing via delays.

Where it fits in HDL Design:

48
Chapter 6 Data Flow Modelling

Gate-Level Modeling

Dataflow Modeling

Behavioral Modeling

Comparison Table:

Feature Gate-Level Dataflow Behavioral


Abstraction Low Medium High
Description Style Primitive gates Logical expressions Procedural constructs
Code Complexity High Medium Low
Delay Modeling Possible Possible Advanced
Simulation Speed Fast Medium Slow
Synthesis Friendly Yes Yes Yes

Table 2: Comparison between Modeling Styles

Real-World Analogy
Think of dataflow modeling like water pipelines: you don’t worry about each pipe’s
structure but just how water (data) flows from tank (input) to faucet (output) through
connections (assignments).

49
Chapter 6 Data Flow Modelling

Learning Objectives
• Understand the purpose and application of dataflow modeling in Verilog.

• Learn about the ‘assign‘ statement and how continuous assignments work.

• Explore various types of delays used in dataflow modeling.

• Analyze how operators and operands form expressions.

• Practice through examples, questions, and output predictions.

“Flow the logic, not the gates — that’s the dataflow mindset.”

6.1 Continuous Assignment


In Verilog, continuous assignment is the most fundamental aspect of dataflow modeling.
It allows a designer to express hardware logic as direct assignments using the keyword
assign, representing logic gates and combinational logic concisely.

Definition
A continuous assignment describes a logic expression that is continuously evaluated and
assigned to a net. Any change in the right-hand-side variables automatically triggers re-
evaluation and updates the output.

Syntax of Continuous Assignment


assign <net_identifier> = <expression>;

50
Chapter 6 Data Flow Modelling

Example 1: Simple AND Gate

1 module and_example(output y, input a, b);


2 assign y = a & b;
3 endmodule

Listing 2: Simple AND Gate using Continuous Assignment

Explanation: The output y will always reflect the logical AND of inputs a and b. If
either of the inputs change, y is updated automatically.

Key Properties of Continuous Assignment


• Only used with nets (e.g., wire).

• Cannot be used inside procedural blocks (always or initial).

• Describes combinational logic (no memory).

• Re-evaluates automatically when input signals change.

Example 2: Multiplexer using Dataflow

1 module mux2x1(output y, input a, b, sel);


2 assign y = sel ? b : a;
3 endmodule

Listing 3: 2:1 Multiplexer using Continuous Assignment

Explanation: This implements a simple 2-to-1 multiplexer. When sel=1, y=b; oth-
erwise, y=a.

51
Chapter 6 Data Flow Modelling

Comparison with Procedural Assignment

Feature Continuous Assignment Procedural Assignment


Used with wire reg
Syntax assign y = a & b; y = a & b; inside
always block
Trigger Automatic (event-driven) Based on sensitivity list
Usage Combinational logic only Sequential or combinational
logic

Block Diagram: Continuous Assignment

52
Chapter 6 Data Flow Modelling

Interview Insight

Pro Tip
Always remember that assign statements work best for modeling combinational
logic. They’re synthesizable and resemble actual gate-level hardware more closely
than procedural logic.

Practice Questions
1. What is the main difference between continuous and procedural assignments?

2. Implement a 4-to-1 multiplexer using continuous assignment.

3. Predict the output of:


1 wire y;
2 assign y = (a ^ b) & c;

4. Can we use assign inside an always block? Justify.

5. How do continuous assignments differ from blocking assignments?

Key Takeaways:

• Continuous assignment is the backbone of dataflow modeling in Verilog.

• It enables real-time updates to logic output based on inputs.

• It provides a direct, synthesizable method for implementing combinational logic.

“With assign, you define how data flows — no clocks, no waits, just logic.”

53
Chapter 6 Data Flow Modelling

6.2 Delays in Dataflow Modeling


Introduction
Delays in Verilog’s dataflow modeling allow us to simulate real-world signal propagation.
In real circuits, signals don’t change instantaneously, and Verilog provides syntactic ways
to include timing delays in simulation.
Delays are especially important when writing testbenches or when timing visualization is
required for digital designs.

Why Use Delays?


• To simulate realistic gate and wire propagation.

• To test timing glitches, race conditions, and pulse filtering.

• To create time-based behavior in testbenches.

Types of Delays in Verilog


1. Inertial Delay (Default)
Definition: Inertial delay mimics the behavior where input pulses shorter than the
delay value are filtered out. Verilog implicitly supports this behavior with standard delay
notation.
1 assign #5 y = a & b;

Listing 4: AND Gate with Inertial Delay

If input changes last less than 5 units, the output remains unchanged.

2. Transport Delay (Conceptual Only)


Definition: Transport delay transmits all changes, even glitches. Though Verilog does
not implement it directly, it can be conceptually modeled.
Useful in modeling physical wire behavior or interconnect delays in advanced test-
benches.

3. Timing Control with #


You can specify:

54
Chapter 6 Data Flow Modelling

• A single delay

• Rise and fall delays

• Rise, fall, and turn-off delays

1 assign #5 y = a & b; // Single delay


2 assign #(3,5) y = a | b; // Rise = 3, Fall = 5
3 assign #(1,2,3) y = ~(a & b); // Rise = 1, Fall = 2, Turn-off = 3

Listing 5: Different Types of Delays

Delay Syntax Table


Delay Type Syntax Explanation
Single Delay #5 Delays output by 5 time units
Rise/Fall Delay #(3,5) Rise = 3, Fall = 5
Rise/Fall/Turn-Off #(3,5,7) Adds Turn-Off delay = 7

Real-World Examples
Example 1: Basic Delay
1 assign #3 y = a ^ b;

Example 2: Different Rise and Fall Delay


1 assign #(2,4) y = a | b;

Example 3: Full Delay Model


1 assign #(1,2,3) y = ~(a & b);

Pro Tip
Delays are ignored during synthesis but are vital in simulation. Use them in testbenches
to accurately test real-time behavior.

55
Chapter 6 Data Flow Modelling

Comparison Table: Synthesis vs Simulation

Context Delay Use Purpose


Synthesis & NO & Timing not inferred
Simulation & YES & Accurate signal timing and glitches
Testbenches & YES & Timing validation, waveform generation

Summary of Section 6.4


• Delays in dataflow modeling allow time-accurate simulation.

• Verilog supports inertial-like delays using the # symbol.

• Multiple delay types are supported: single, rise/fall, and full delays.

• Always simulate with delays to visualize waveform behaviors, but avoid them in
synthesis code.

Learning Outcome
• Understand different types of delays and their syntax in Verilog.

• Apply correct delay modeling in testbenches for verification.

• Differentiate between synthesizable and non-synthesizable constructs.

6.3: Expression Operators and Operands


Expressions in Verilog form the heart of logic design. Dataflow modeling heavily relies
on the ability to describe circuit behavior using mathematical and logical expressions.

Expression: A combination of operands (like wires, variables, constants) and operators


(like +, &, !) to produce a logic value.

Syntax:
1 assign out = expression;

56
Chapter 6 Data Flow Modelling

Operands in Verilog
Operands are the basic data items on which operations are performed. They may include
constants, wires, or even another expression.

Table 3: Types of Operands


Type Description Example
Constant Literal numerical value 4’b1010, 8’hFF
Variable/Wire Named signal in a module a, b, clk
Expression Result of another expression (a & b), (x + y)

Types of Operators
Verilog offers various operators, categorized as:

Operator Type Operators Example


Arithmetic +, -, *, /, % assign sum = a + b;
Relational ==, !=, <, >, <=, >= assign result = (a >
b);
Logical &&, ||, ! assign out = (a &&
b);
Bitwise &, |, ˆ, ˜ assign y = a ˆ b;
Shift «, », «<, »> assign out = a « 2;
Concatenation {a, b}, {{2{a}}} assign out = {a, b};
Reduction &, |, ˜&, ˜|, ˆ, ˜ˆ assign zero = ˜|a;
Conditional ? : assign y = sel ? a :
b;

Examples for Each Operator Type


1. Arithmetic Operator:

57
Chapter 6 Data Flow Modelling

1 assign sum = a + b;
2 assign diff = a - b;
3 assign prod = a * b;
4 assign div = a / b;

Listing 6: Arithmetic Operation

2. Relational Operator:
1 assign is_greater = (a > b);
2 assign is_equal = (a == b);

Listing 7: Relational Operation

3. Logical Operator:
1 assign logic_result = (a && b) || (!c);

Listing 8: Logical Operation

4. Bitwise Operator:
1 assign and_op = a & b;
2 assign xor_op = a ^ b;

Listing 9: Bitwise Operation

5. Shift Operator:
1 assign left_shift = a << 2;
2 assign right_shift = b >> 1;

Listing 10: Shift Operation

6. Concatenation and Repetition:


1 assign out = {a, b}; // Concatenate a and b
2 assign repeat = {{4{a}}}; // Repeat ’a’ 4 times

Listing 11: Concatenation and Repetition

7. Reduction Operator:
1 assign any_bit_high = |a;
2 assign all_bits_low = ~|a;

Listing 12: Reduction Operation

8. Conditional Operator:

58
Chapter 6 Data Flow Modelling

1 assign out = (sel) ? a : b;

Listing 13: Conditional Operator

Operator Precedence (Highest to Lowest)


• Unary Operators: !, , &, |

• Multiplicative: *, /, %

• Additive: +, -

• Relational: <, >, <=, >=

• Equality: ==, !=

• Bitwise: &, |, ˆ

• Logical: &&, ||

• Conditional: ? :

Tip: Use parentheses () for clarity when mixing operators.

Pro Tip
Always use parentheses to clarify precedence in complex expressions. It not only
reduces bugs but makes your code more readable.

“The more expressive your logic, the cleaner your design.”

59
Chapter 6 Data Flow Modelling

6.4 20 Solved Examples (Problems with Solutions)


Understanding dataflow modeling becomes much more effective through hands-on problem-
solving. This section presents 20 problems modeled using the ‘assign‘ statement, show-
casing how Verilog can be used to describe circuits at the dataflow level.

“Think of dataflow modeling as plumbing logic—where signals flow like water through
gates and pipes!”

Example 1: 2-Input AND Gate


1 module and_gate(output y, input a, b);
2 assign y = a & b;
3 endmodule

Listing 14: 2-input AND gate using assign

Explanation: This is the simplest form of logic gate. Think of it like a door that only
opens when both switches (inputs) are ON.

Example 2: 2-Input OR Gate


1 module or_gate(output y, input a, b);
2 assign y = a | b;
3 endmodule

Analogy: Like a streetlight system where light turns ON if any one sensor detects motion.

Example 3: NOT Gate


1 module not_gate(output y, input a);
2 assign y = ~a;
3 endmodule

Explanation: Acts like a toggle switch.

60
Chapter 6 Data Flow Modelling

Example 4: 2-to-1 Multiplexer


1 module mux2to1(output y, input a, b, sel);
2 assign y = sel ? b : a;
3 endmodule

Analogy: Like a train junction that decides which track to follow based on a lever (selec-
tor).

Example 5: Half Adder


1 module half_adder(output sum, carry, input a, b);
2 assign sum = a ^ b;
3 assign carry = a & b;
4 endmodule

Explanation: Adds two 1-bit values, just like primary school math.

Example 6: Full Adder


1 module full_adder(output sum, carry, input a, b, cin);
2 assign sum = a ^ b ^ cin;
3 assign carry = (a & b) | (b & cin) | (a & cin);
4 endmodule

Example 7: 4-bit Adder


1 module four_bit_adder(output [3:0] sum, input [3:0] a, b);
2 assign sum = a + b;
3 endmodule

Example 8: Comparator
1 module comparator(output gt, eq, lt, input [3:0] a, b);
2 assign gt = (a > b);
3 assign eq = (a == b);
4 assign lt = (a < b);
5 endmodule

61
Chapter 6 Data Flow Modelling

Example 9: 4-bit XOR Gate

1 module xor_4bit(output [3:0] y, input [3:0] a, b);


2 assign y = a ^ b;
3 endmodule

Example 10: Parity Generator

1 module parity_gen(output parity, input [3:0] data);


2 assign parity = ^data; // XOR all bits
3 endmodule

Example 11: Even Parity Checker

1 module parity_check(output even, input [3:0] data);


2 assign even = ~(^data); // Complement of XOR result
3 endmodule

Example 12: 4-bit Subtractor

1 module subtractor(output [3:0] diff, input [3:0] a, b);


2 assign diff = a - b;
3 endmodule

Example 13: Bitwise AND

1 module bitwise_and(output [3:0] y, input [3:0] a, b);


2 assign y = a & b;
3 endmodule

62
Chapter 6 Data Flow Modelling

Example 14: Bitwise OR

1 module bitwise_or(output [3:0] y, input [3:0] a, b);


2 assign y = a | b;
3 endmodule

Example 15: Bitwise NOT

1 module bitwise_not(output [3:0] y, input [3:0] a);


2 assign y = ~a;
3 endmodule

Example 16: Left Shift

1 module shift_left(output [3:0] y, input [3:0] a);


2 assign y = a << 1;
3 endmodule

Example 17: Right Shift

1 module shift_right(output [3:0] y, input [3:0] a);


2 assign y = a >> 1;
3 endmodule

Example 18: Concatenation Example

1 module concat_example(output [7:0] y, input [3:0] a, b);


2 assign y = {a, b}; // Join two 4-bit numbers
3 endmodule

63
Chapter 6 Data Flow Modelling

Example 19: Sign Extension

1 module sign_extend(output [7:0] y, input [3:0] a);


2 assign y = {{4{a[3]}}, a}; // Extend sign
3 endmodule

Example 20: Priority Selector (3-input)

1 module priority_selector(output y, input a, b, c);


2 assign y = a ? 1’b1 : (b ? 1’b1 : c);
3 endmodule

Pro Tip
You can simulate all the above examples using tools like ModelSim or EDA Playground.
Try changing input values to visualize how logic flows!

6.5 Practice Questions (30 Problems)


Practice strengthens understanding. Try solving the following Verilog questions to re-
inforce your understanding of dataflow modeling. Each question is designed to address
specific concepts and increase your proficiency step-by-step.

Level 1: Basic Gates (1–5)


Q1. Write Verilog code using dataflow to implement a 2-input NAND gate.

Q2. Implement a 2-input NOR gate using an ‘assign‘ statement.

Q3. Model a NOT gate and verify its truth table.

Q4. Create a 3-input AND gate using a single ‘assign‘ statement.

Q5. Design a 4-input OR gate and simulate it with all combinations of inputs.

64
Chapter 6 Data Flow Modelling

Level 2: Arithmetic & Bitwise Operations (6–10)


Q6. Implement a 4-bit adder using the ‘assign‘ statement.

Q7. Write a 4-bit subtractor using dataflow modeling.

Q8. Design a module that performs bitwise XOR of two 8-bit numbers.

Q9. Build a module to compute the modulus (%) of two 4-bit numbers.

Q10. Write a Verilog code for multiplying two 4-bit numbers using ‘*‘.

Level 3: Conditional Logic & Operators (11–15)


Q11. Implement a 2-to-1 multiplexer using a conditional (‘? :‘) operator.

Q12. Design a 4-to-1 multiplexer using nested conditional operators.

Q13. Create a module for a 1-bit comparator (==).

Q14. Implement a parity generator using the reduction XOR (ˆ) operator.

Q15. Design an even parity checker.

Level 4: Shifting & Concatenation (16–20)


Q16. Write a Verilog code for logical left shift by 2 bits.

Q17. Implement arithmetic right shift on a signed number.

Q18. Concatenate two 4-bit inputs and store the result in an 8-bit output.

Q19. Create a barrel shifter using assign statements (hint: use shifts).

Q20. Perform sign-extension of a 4-bit number to 8 bits.

Level 5: Mixed Logic and Design (21–25)


Q21. Create a dataflow model of a 1-bit full adder.

Q22. Implement a 4-bit full adder using four 1-bit full adders.

Q23. Design a 4-bit comparator (greater than, less than, equal).

65
Chapter 6 Data Flow Modelling

Q24. Model a 3-bit priority encoder.

Q25. Write a Verilog module that outputs 1 when a number is divisible by 2.

Level 6: Output Prediction & Debug (26–30)


Q26. Predict the output:
1 assign y = 3’b101 & 3’b110;

Q27. Predict the output:


1 assign y = (a < b) ? a : b;

Q28. Identify the issue in the following dataflow code:


1 assign y = (a == b) & (c | d;

Q29. Debug the following code:


1 assign out = {a,b};
2 endmodule

Q30. Predict and explain the output:


1 assign y = ~((a & b) | c);

Pro Tip
Tip: Start writing these on simulation platforms like ModelSim or EDA Playground to
test your syntax and logic. Simulating is the best way to validate and learn!

6.6 Pro Tips for Dataflow Modeling


To become efficient in Verilog, it’s important to follow practices that not only help avoid
bugs but also write readable, scalable, and synthesizable code. Below are some pro tips
specifically for dataflow modeling:

66
Chapter 6 Data Flow Modelling

Tip 1: Always Use ‘assign‘ in Dataflow


Dataflow modeling uses the keyword assign to bind continuous assignments. Forget-
ting to use assign will result in a syntax error.

Tip 2: Use ‘wire‘ for Outputs


In dataflow modeling, ensure that output ports are declared as wire. Do not use reg
types unless required in procedural blocks.

Tip 3: Use Grouping with Parentheses


Always group operations using parentheses. This helps avoid precedence-related bugs
and improves readability.

Tip 4: Avoid Mixing Blocking (‘


Never use blocking assignments (=) within modules that use continuous assignment via
assign. This can confuse simulators and result in mismatches.

Tip 5: Match Bit Widths


Bit width mismatches may not always raise errors but can silently cause logic errors.
Always ensure the output has sufficient width to store the result of operations like addi-
tion or shifting.

Tip 6: Use Named Ports for Clarity


When instantiating modules, use named port mapping:
1 and_gate u1(.a(a), .b(b), .y(y));

This improves readability and avoids wiring mistakes.

Tip 7: Simulate Early and Often


Don’t wait till the end to simulate. Use tools like ModelSim or Icarus Verilog frequently
to test modules. Simulation catches most mistakes before synthesis.

67
Chapter 6 Data Flow Modelling

Tip 8: Use Meaningful Names


Avoid generic names like a1, b1, c2. Use clk, data_in, sel, etc., for better un-
derstanding and maintainability.

Tip 9: Beware of Overusing Concatenation


While concatenation is powerful, excessive or complex nested concatenation can harm
readability and may introduce bugs. Use only when required.

Tip 10: Use Delay Only in Testbenches


Delays like #5 are simulation constructs and should not be used in RTL designs for
synthesis. Use them only in testbenches or behavioral-level code.

Figure: Dataflow Modeling – A Clear and Concise Way to Define Logic

6.7 Summary
In this chapter, we explored the foundations of Dataflow Modeling in Verilog, one of the
most intuitive and efficient ways to describe hardware behavior using continuous assign-
ments. Below is a recap of all important concepts covered:

68
Chapter 6 Data Flow Modelling

• Continuous Assignments: Defined using the assign keyword, suitable for com-
binational logic.

• Delay Types:

– Inertial and Transport delay


– Rise, Fall, Turn-off delay for gate-level modeling

• Expression Components:

– Operators (Arithmetic, Relational, Logical, etc.)


– Operands (Wires, Constants, Expressions)

• Operator Types: Covered in depth with syntax, examples, and application tips.

• Examples: We studied 20+ real-world examples of common logic expressions us-


ing dataflow style.

• Practice Questions: A bank of 30 curated problems to test your understanding.

• Pro Tips: Coding best practices, synthesis tips, and simulation advice were pro-
vided to guide both beginners and advanced learners.

Key Takeaway
Dataflow modeling is ideal for describing simple combinational circuits. It provides
a clean, readable, and hardware-accurate way of connecting expressions to outputs
using the assign keyword.

69
Chapter 6 Data Flow Modelling

Dataflow Modeling

Continuous Assignment Delay Types

Operators and Operands 20+ Solved Examples

Pro Tips 30 Practice Problems

Figure: Mind Map of Concepts Covered in Dataflow Modeling

70
Chapter 7: Behavioral Modeling

Introduction
Behavioral modeling in Verilog allows designers to describe the functionality of a digital
system rather than its structural implementation. It focuses on what the system does, not
how it is physically realized with gates or data paths.

Analogy: Programming a Robot


Think of behavioral modeling like programming a robot. Instead of telling the robot
how to move each joint (gate-level) or how to move based on a signal (dataflow), you
write: “If obstacle detected, then turn right.” This describes behavior—precisely
what behavioral modeling captures.

Where Behavioral Modeling is Used:

• For describing sequential and complex digital systems

• In writing testbenches for verification

• When control logic is needed (state machines, counters, etc.)

• To simulate timing-based events using delay/event control

Key Behavioral Constructs:

• initial and always procedural blocks

• if, case, for, and other control statements

71
Chapter 7 Behavioral Modeling

• Blocking and non-blocking assignments

• Sequential and parallel block creation

Pro Tip
Use behavioral modeling to define sequential behavior and test logic. Keep it RTL-
compliant for synthesis, and fully expressive for testbenches!

Key Takeaway: Behavioral modeling is the highest abstraction level in Verilog. It em-
powers you to describe complex logic in compact, readable, and expressive ways.

“Behavioral modeling brings your ideas to life—by telling the system what to do, not how
to do it.”

72
Chapter 7 Behavioral Modeling

Learning Objectives

Objective Map
Behavioral modeling is the heart of algorithmic digital design. These objectives
will help you grasp the essence of control structures, sequential logic, and design
abstraction.

By the end of this chapter, you will be able to:

1. Understand and implement structured procedural blocks such as initial and


always.

2. Differentiate between blocking and non-blocking assignments and know when to


use each.

3. Apply timing controls like delay control (#), event control (@), and level-sensitive
constructs.

4. Construct various types of control flow mechanisms:

• Conditional statements (if, if-else)


• Multiway branches (if-else-if, case, casex, casez)
• Looping statements (for, while, repeat, forever)

5. Use sequential and parallel blocks to describe concurrent and ordered logic flows.

6. Design and analyze small to mid-sized behavioral Verilog models.

7. Debug behavioral logic using simulation waveform analysis.

8. Write synthesizable behavioral code by following RTL design best practices.

73
Chapter 7 Behavioral Modeling

Pro Tip
Behavioral modeling is used in 90% of simulation and verification tasks. Master it to
enhance your coding and debugging skills in both industry and academia!

74
Chapter 7 Behavioral Modeling

7.1 Structured Procedures (initial and always State-


ments)
In behavioral modeling, Verilog provides two structured procedures to describe the be-
havior of digital systems: initial and always blocks. These are fundamental for
modeling control flow, algorithmic descriptions, and sequential behavior.

Analogy: Initial vs Always


Think of the initial block as a one-time instruction you give before a mission
begins (like a robot’s startup routine). On the other hand, the always block keeps
monitoring conditions forever, like a robot patrolling continuously based on sensor
input.

7.1.1 initial Block


Purpose: Executes the statements inside it only once at the beginning of the simulation
time (time = 0).
1 module test;
2 reg clk;
3 initial begin
4 clk = 0;
5 #5 clk = 1;
6 #5 clk = 0;
7 end
8 endmodule

Listing 15: Example of initial block

Key Points:

• Executes only once.

• Mostly used in testbenches.

• Not synthesizable.

75
Chapter 7 Behavioral Modeling

7.1.2 always Block


Purpose: Executes the block of code repeatedly for the entire simulation based on an
event or condition.
1 module counter;
2 reg clk;
3 reg [3:0] count;
4
5 always @(posedge clk)
6 count = count + 1;
7 endmodule

Listing 16: Example of always block

Key Points:

• Executes continuously as long as the simulation runs.

• Used in both combinational and sequential circuits.

• Synthesizable and RTL friendly.

7.1.3 Comparison Table

Feature initial always


Execution Executes once at simulation start Executes continuously
Use case Testbenches, initialization RTL modeling, clocked logic
Synthesis Not synthesizable Synthesizable
Triggered by Time = 0 Sensitivity list or implicit always
Simulation Use Initialization, debugging Functional description

Table 5: Comparison Between initial and always Blocks

76
Chapter 7 Behavioral Modeling

7.1.4 Block Diagram – Structured Procedure Usage

Pro Tip
Use initial blocks in testbenches to apply stimulus or set default values. Use
always blocks when describing logic based on clocks or input changes.

7.1.5 Summary
• initial blocks run only once and are perfect for stimulus generation in test-
benches.

• always blocks run continuously and form the backbone of synthesizable RTL.

• Understanding when and where to use each block is key to effective Verilog model-
ing.

77
Chapter 7 Behavioral Modeling

7.2 Procedural Assignment (Blocking and Non-Blocking As-


signments)
In Verilog, procedural assignments inside initial or always blocks are classified into
two types:

• Blocking assignments (using =)

• Non-blocking assignments (using <=)

Analogy: Blocking vs Non-Blocking


Imagine cooking breakfast:
- In blocking style, you make tea, wait for it to finish, then toast bread. - In non-
blocking style, you start tea, then simultaneously toast bread.
Similarly, blocking assignments wait for one task to finish before starting the next,
while non-blocking assignments let tasks proceed in parallel.

7.2.1 Blocking Assignment (=)


Behavior: Executes statements sequentially. One statement must complete before the
next begins.
1 always @(posedge clk) begin
2 a = b;
3 c = a; // ’c’ gets the new value of ’a’
4 end

Listing 17: Blocking Assignment Example

Key Characteristics:

• Operates sequentially like traditional programming.

• Easier to debug.

• Can lead to incorrect behavior in sequential circuits.

78
Chapter 7 Behavioral Modeling

7.2.2 Non-Blocking Assignment (<=)


Behavior: All RHS expressions are evaluated first, and then assignments happen in paral-
lel at the end of the simulation time step.
1 always @(posedge clk) begin
2 a <= b;
3 c <= a; // ’c’ gets old value of ’a’
4 end

Listing 18: Non-Blocking Assignment Example


Key Characteristics:

• Executes in parallel.

• Best suited for sequential logic (flip-flop modeling).

• Avoids race conditions.

7.2.3 Use Cases

Type When to Use Typical Application


Blocking (=) For combinational logic or test- Combinational circuits, initial-
benches ization
Non-Blocking (<=) For sequential logic or pipelines Flip-flops, clocked logic, FSMs

Table 6: Usage Comparison of Blocking and Non-Blocking Assignments

7.2.4 Common Pitfall Example


1 always @(posedge clk) begin
2 q = d;
3 q_bar = ~q; // q_bar gets wrong value
4 end

Listing 19: Incorrect: Blocking in Sequential Logic

79
Chapter 7 Behavioral Modeling

1 always @(posedge clk) begin


2 q <= d;
3 q_bar <= ~q; // q_bar gets correct old value of q
4 end

Listing 20: Correct: Non-Blocking in Sequential Logic

7.2.5 Block Diagram: Assignment Execution Flow

Start Clock Edge Evaluate RHS (b) Start Clock Edge Evaluate RHS (b, a)

a=b a<= b, c <= a

c=a End of Non-Blocking

End of Blocking

Pro Tip
Golden Rule: Never mix blocking and non-blocking assignments in the same always
block. It may cause unpredictable simulation results!

7.2.6 Summary
• Blocking (=) executes sequentially — best for combinational logic.

• Non-Blocking (<=) executes concurrently — ideal for sequential logic.

80
Chapter 7 Behavioral Modeling

• Use non-blocking in always @(posedge clk) for safe and reliable RTL code.

• Mixing both types in the same block is a common source of bugs — avoid it!

7.3 Conditional Statements

Conditional statements in Verilog are used to make decisions based on certain conditions.
These statements guide the simulation or synthesis tool to execute specific blocks of code
when certain criteria are met.

Introduction

Conditional logic is fundamental to any digital system, allowing the circuit to behave
differently depending on inputs or internal states. In Verilog, the most commonly used
conditional statement is the ‘if‘ statement.

Analogy
Think of conditional statements like a traffic signal system. If the light is green, ve-
hicles move. If it’s red, they stop. This simple decision-making mechanism governs
how the circuit reacts to different situations.

Syntax: “‘verilog if (condition) statement; else statement;

81
Chapter 7 Behavioral Modeling

Block Diagram: Conditional Statement Flow

Start

Is condition true?

Yes No

Execute Execute
True Block False Block

Continue

Example 1: Simple If-Else


verilog Copy Edit module ifexample; reg [3:0] a, b; reg [3:0] max;
initial begin a = 5; b = 10;
if (a > b) max = a; else max = b;
$display("Max = end endmodule
Pro Tip
Conditional statements can be synthesized if they represent combinational logic. How-
ever, unintentional latches may form if not all conditions are covered!

Where It’s Used:

• Control units

• Priority encoders

82
Chapter 7 Behavioral Modeling

• Data path selection

• Conditional data assignments

Quick Recap:

1. if, else, and else if allow decision-making in Verilog.

2. Always wrap multi-line blocks with begin...end.

3. Avoid incomplete conditions to prevent latch inference.

7.4 Multiway Branching in Verilog


Multiway branching is used when a variable or expression needs to be compared against
multiple possible constant values. This is efficiently implemented using the case state-
ment in Verilog, which is functionally similar to the switch statement in other program-
ming languages like C or C++.

Analogy: Vending Machine Logic


Imagine you’re selecting an item from a vending machine. Pressing A1 gives you
chips, B2 gives chocolate, and C3 gives soda. The internal logic behind this selec-
tion is a perfect analogy for a case statement.

Syntax of the case Statement


1 case (expression)
2 constant1: begin
3 // statements
4 end
5 constant2: begin
6 // statements
7 end
8 default: begin
9 // statements
10 end
11 endcase

83
Chapter 7 Behavioral Modeling

Types of Case Statements in Verilog


• case – Matches exactly (including ‘x‘ and ‘z‘)

• casex – Ignores ‘x‘ and ‘z‘ bits in the comparison

• casez – Ignores only ‘z‘ bits in the comparison

1. Standard case Statement Example

1 module mux_4to1 (input [1:0] sel, output reg [3:0] out);


2 always @(*) begin
3 case (sel)
4 2’b00: out = 4’b0001;
5 2’b01: out = 4’b0010;
6 2’b10: out = 4’b0100;
7 2’b11: out = 4’b1000;
8 endcase
9 end
10 endmodule

2. casex Statement Example


Useful when we want to treat don’t care (‘x‘) bits in the case expression as wildcards:
1 casex (opcode)
2 4’b1x0x: instruction = "LOAD";
3 4’b0x1x: instruction = "STORE";
4 endcase

3. casez Statement Example


Ignore only high-impedance (‘z‘) bits:
1 casez (data)
2 4’b1zz0: result = 1;
3 4’b0zz1: result = 0;
4 endcase

84
Chapter 7 Behavioral Modeling

Comparison Table
Statement Ignores ‘x‘ Ignores ‘z‘
case No No
casex Yes Yes
casez No Yes

Pro Tip
Use casex and casez with caution in synthesis as they may result in unexpected
logic due to wildcard matching.

Summary of Key Points


• The case statement is useful for selecting between multiple options based on a
variable.

• casex treats ‘x‘ and ‘z‘ as wildcards — good for simulation, not synthesis.

• casez ignores only ‘z‘ — better than casex for synthesis use.

• Always include a default case to handle unexpected values.

7.5 Loops in Verilog


Introduction to Loops
Loops in Verilog are used to execute a block of code repeatedly based on a condition or
predefined count. They are primarily used in testbenches, simulation environments, and
occasionally in synthesizable code if designed carefully.

Analogy
Think of loops like an assembly line machine: you instruct it to stamp a part multiple
times until the job is complete. In Verilog, loops allow similar repetition of tasks in
code.

Verilog Provides the Following Loop Constructs:

85
Chapter 7 Behavioral Modeling

• for loop

• while loop

• repeat loop

• forever loop

Comparison of Verilog Loop Constructs

Loop Type Structure Usage Synthesizable


for Counter-controlled Array traversal, testbench Yes (with fixed count)
while Condition-based Iteration until condition false No (generally avoided)
repeat Fixed iterations Clock cycle specific repetition Yes (limited usage)
forever Infinite loop Clocks, testbenches No (only for simulation)

1. for Loop
The for loop is the most common loop in Verilog. It is counter-based and resembles the
loop syntax in C/C++.
Syntax: “‘verilog for (initialization; condition; increment) begin // Statements end
Example: Generating 8-bit test pattern module forexample; integer i; reg [7:0] pat-
tern; initial begin for (i = 0; i < 8; i = i + 1) begin pattern[i] = 1’b1; end end endmodule

2. while Loop
The while loop executes as long as a condition is true. However, it is generally not
synthesizable due to potential infinite looping.
Syntax: while (condition) begin // Statements end Example: Toggle signal until
condition met module whileexample; reg clk; integer count = 0; initial begin clk = 0;
while (count < 5) begin #5 clk = clk; count = count + 1; end end endmodule

86
Chapter 7 Behavioral Modeling

3. repeat Loop
The repeat loop executes a block of statements a fixed number of times. Often used in
clocked designs.
Syntax: repeat (n) begin // Statements end
Example: Repeat clock toggle 10 times module repeatexample; reg clk; initial begin
clk = 0; repeat (10) begin #5 clk = clk; end end endmodule

4. forever Loop
The forever loop runs indefinitely and is used mostly in testbenches and clock genera-
tion.
Syntax: forever begin // Statements end Example: Clock generator using forever
module foreverexample; reg clk; initial begin clk = 0; forever #5 clk = clk; end endmodule
Pro Tip
Always add appropriate conditions or delay in loops like while and forever to
avoid infinite loops and simulation hangs.

Common Errors in Loops


• Infinite loops without proper delay
• Missing increment/decrement statements
• Using while or forever loops in synthesizable code

Quick Checklist:

1. Use for loops for array or memory initialization

2. Use repeat for specific delay cycles

3. Avoid forever and while loops in synthesizable blocks

7.6 Case Statements in Verilog (case, casex, casez)


Case statements in Verilog are multiway decision constructs, just like the switch-case
statement in C. They are often used to create control logic like decoders, multiplexers, and

87
Chapter 7 Behavioral Modeling

FSMs. There are three variants:

• case – performs exact match

• casex – ignores unknowns (X) and high-impedance (Z)

• casez – ignores only high-impedance (Z)

Analogy: Sorting Letters in a Mailroom


Imagine a clerk sorting letters based on ZIP codes. A normal case is like sorting with full,
exact ZIP code. casex is like saying “ignore missing digits” and sort whatever matches,
while casez is like “treat ZIPs with unknown digit as match unless the digit is critical.”

Pro Tip
Use case for synthesis-safe design. Avoid casex unless you fully understand
how X/Z values propagate in simulation.

Syntax of Case Statements


1 case (expression)
2 constant_1: statement_1;
3 constant_2: statement_2;
4 default: default_statement;
5 endcase

Listing 21: General Syntax of a Case Statement


Example 1: Simple Case Statement (Decoder)


1 module decoder (input [1:0] in, output reg [3:0] out);
2 always @ (in)
3 begin
4 case (in)

88
Chapter 7 Behavioral Modeling

5 2’b00: out = 4’b0001;


6 2’b01: out = 4’b0010;
7 2’b10: out = 4’b0100;
8 2’b11: out = 4’b1000;
9 endcase
10 end
11 endmodule

Listing 22: 2-to-4 Decoder using Case


Example 2: casex – Ignoring Don’t-Care Bits


1 always @(a or b)
2 casex ({a, b})
3 2’b1x: out = 1’b1; // x is ignored
4 2’b0x: out = 1’b0;
5 endcase

Listing 23: Using casex for Don’t Care Conditions


Example 3: casez – Ignoring High Impedance (Z)


1 always @(select)
2 casez (select)
3 4’b1ZZZ: out = a;
4 4’b01ZZ: out = b;
5 default: out = 0;
6 endcase

Listing 24: Using casez to Match Patterns with Z


Comparison Table: case vs. casex vs. casez


89
Chapter 7 Behavioral Modeling

Feature case casex casez


Ignores X No Yes No
Ignores Z No Yes Yes
Best for Synthesis Yes No Use with care
Use Case Exact match Priority encoders Pattern match with Z
Risky in Simulation No Yes Sometimes

Table 7: Comparison of case, casex, and casez

Best Practices
• Always include a default case to avoid latches.

• Avoid casex in synthesis if signal may carry real X values.

• Use casez with masks for implementing decoders.

• For FSMs, case is safest and synthesizable.

Pro Tip
Always initialize your output in a case structure or use a default path to prevent
latch inference during synthesis.

Learning Outcome
After completing this section, students should be able to:

• Use all three types of case statements effectively

• Understand the difference between case, casex, and casez

• Know when to use each construct in behavioral modeling

90
Chapter 7 Behavioral Modeling

7.7 Loops in Verilog


Loops are powerful control structures in Verilog that allow repeated execution of state-
ments under specific conditions. They are essential for testbenches, repeated hardware be-
haviors, and automating multiple similar operations such as register initializations, wave-
form printing, etc.

Analogy: Washing Dishes


Think of loops as a set of instructions that say: “Keep washing the dishes while
there are dirty ones.” The loop keeps executing until the sink is empty.

Types of Loops in Verilog


• for loop

• while loop

• repeat loop

• forever loop

Comparison of Loop Types

Loop Type Use Case Example


for loop Known number of itera- for (i = 0; i < 10; i = i
tions + 1)
while loop Iterates as long as a condi- while (a < b)
tion holds
repeat loop Repeat fixed number of repeat (5) {...}
times

91
Chapter 7 Behavioral Modeling

forever loop Continuous, infinite exe- forever #10 clk = clk;


cution (usually used with
delays)

Detailed Examples
1. for Loop
“‘verilog integer i; initial begin for (i = 0; i < 8; i = i + 1) begin $display("i = end end

2. while Loop
integer a = 0; initial begin while (a < 5) begin $display("a = a = a + 1; end end

3. repeat Loop
integer j = 0; initial begin repeat (4) begin $display("j = j = j + 2; end end

4. forever Loop
reg clk = 0; initial begin forever begin #5 clk = clk; // toggle clock every 5 time units end
end

Loop Use Case in Testbench


initial begin for (i = 0; i < 16; i = i + 1) begin datain = i; #10; end end

Pro Tip
Use forever loops only with proper delay elements like # or (posedge clk) to
prevent simulation from hanging.

92
Chapter 7 Behavioral Modeling

Common Mistakes and Tips


• Avoid infinite loops without delays—they’ll hang the simulation.

• Do not use loops with variables not initialized beforehand.

• for loops are synthesizable if bounds are fixed.

• forever loops are mostly used in testbenches, not synthesizable logic.

Interview Trick
You may be asked: “Is this code synthesizable?” Always analyze if the loop bounds and
contents are deterministic and finite. If not, it’s for simulation only.

7.8 Sequential and Parallel Blocks


In Verilog, grouping of multiple statements inside a procedural block (‘always‘ or ‘initial‘)
is essential when more than one operation needs to be performed in sequence or in parallel.
This is done using the following constructs:

• Sequential Block: begin ... end

• Parallel Block: fork ... join

7.8.1 Sequential Blocks (begin ... end)


Sequential blocks execute the statements in order, one after the other.

Syntax
initial begin
statement1;
statement2;
statement3;
end

93
Chapter 7 Behavioral Modeling

Example

Verilog Code Example


initial begin
$display("Start");
#10;
$display("Middle");
#10;
$display("End");
end

Output:

Time 0: Start
Time 10: Middle
Time 20: End

7.8.2 Parallel Blocks fork...join

Parallel blocks execute all the enclosed statements simultaneously and wait for all of them
to complete.

Syntax
initial fork
statement1;
statement2;
statement3;
join

94
Chapter 7 Behavioral Modeling

Example

Verilog Code Example


initial fork
#5 $display("A");
#10 $display("B");
#2 $display("C");
join

Output:

Time 2: C
Time 5: A
Time 10: B

Comparison Table: Sequential vs Parallel Blocks

Feature Sequential Block Parallel Block


Keyword Used begin ... end fork ... join
Execution Type One statement after another All statements executed concur-
rently
Common Use Synchronous tasks, FSMs Clock generation, concurrent
triggers
Simulation Behavior Waits for one to finish before All statements start together,
next waits for all to finish
Delay Handling Cumulative delays Independent delays
Synthesizable? Yes (commonly used in RTL) No (simulation-only construct)

95
Chapter 7 Behavioral Modeling

When to Use What?


• Use begin ... end when sequence/order matters.

• Use fork ... join when multiple events need to occur simultaneously (e.g.,
generating multiple signals).

• Avoid fork ... join in RTL design (not synthesizable).

Pro Tip
Pro Tip
Always ensure to use fork...join with care inside testbenches, especially when
one of the processes never terminates — it can cause the simulation to hang!

Example: Mixing Delay and Parallelism


Verilog Code Example
initial fork
begin
#5 $display("Task 1 done");
end
begin
#10 $display("Task 2 done");
end
join

Output:

Time 5: Task 1 done


Time 10: Task 2 done

Interview Insight
• fork ... join is often asked in testbench-related interviews.

• Trick: If you use fork inside a procedural block, all forks must finish or the simu-
lation may get stuck.

96
Chapter 7 Behavioral Modeling

7.9 Timing and Event Control in Behavioral Modeling


Introduction
In behavioral modeling, controlling the timing of events is crucial for creating realistic
testbenches and simulating actual circuit behavior. Verilog provides several constructs to
specify when and how operations are triggered.

Learning Objectives
• Understand the difference between delay control and event control.

\item Use ‘#‘, ‘@‘, and ‘wait‘ for controlling simulation time and eve

• Implement realistic timing in testbenches.

7.9.1 Delay Control (#)


Delay control is the simplest way to pause execution for a specified amount of time.

Syntax
#time; // Waits for ’time’ units

Example: Simple Delay


verilog

initial begin
$display("Time = %0d: Start", $time);
#10;
$display("Time = %0d: After 10 units delay", $time);
end

Output: Time = 0: Start Time = 10: After 10 units delay Pro Tip: Use delay control
carefully — excessive use may cause simulation inefficiency.

97
Chapter 7 Behavioral Modeling

7.9.2 Event Control (@)


Event control pauses execution until a specific event occurs, such as a signal changing
state.

Syntax
@(event_expression); // Waits until event_expression becomes true

Example: Event Control on Clock Edge


always @(posedge clk) begin q <= d; end

Example: Multiple Event Control


always @(posedge clk or negedge reset) begin if (!reset) q <= 0; else q <= d; end Expla-
nation: The block is triggered when either clk rises or reset falls.

7.9.3 Wait Statement


The wait statement pauses the execution until the specified condition becomes true.

Syntax
wait(condition); // Suspends execution until condition is true

Example: Wait Until Signal is High


initial begin
wait(clk == 1);
$display("clk is HIGH at time %0t", $time);
end

Output:

clk is HIGH at time 15

Explanation: This waits until ‘clk‘ becomes ‘1‘, regardless of how long it takes.

98
Chapter 7 Behavioral Modeling

Pro Tip

Pro Tip
Avoid putting wait inside infinite loops without an escape condition. It may lead
to simulation deadlock if the condition never becomes true.

7.9.4 Comparison Table

Feature Delay Control (#) Event Control (@) Wait Statement


Triggering Mechanism Time-based Signal change or edge Boolean condition
Use Case Introduce delay in simu- Edge-triggered behav- Wait for specific condi-
lation iors (e.g., clocks) tion to become true
Simulation Efficiency Slower if overused Efficient Conditional and reactive
RTL Synthesis Support No Yes (in ‘always‘ blocks) No
Example #10; @(posedge clk); wait(clk==1);

7.9.5 More Examples


Example 1: Combined Delay and Event
initial begin
#5;
@(posedge clk);
$display("5 time units delay + posedge clk");
end

Example 2: Wait for Condition


initial begin
wait(data_ready == 1);
$display("Data is ready at time = %0t", $time);
end

99
Chapter 7 Behavioral Modeling

7.9.6 Interview Questions


• What is the difference between ‘@‘ and ‘wait‘?

• Why is # not synthesizable in Verilog?

• Can you use multiple event controls in a single block?

• What is the preferred way to trigger actions on clock edges?

• How would you model asynchronous reset using ‘@‘?

7.10 Summary of Behavioral Modeling in Verilog


• Behavioral modeling describes the functionality of the design using high-level con-
structs like ‘initial‘, ‘always‘, ‘if‘, ‘case‘, ‘loops‘, etc.

• Two main procedural blocks are:

– initial – Executes once at time zero.


– always – Repeats whenever triggered by sensitivity list.

• Procedural assignments are:

– Blocking (‘=‘) – Executes statements sequentially.


– Non-blocking (‘<=‘) – Executes concurrently.

• Conditional execution is handled using:

– ‘if‘, ‘if-else‘, ‘nested if‘, ‘if-else-if‘

• Multi-way branching supports:

– ‘case‘, ‘casex‘, ‘casez‘

• Loops available:

– ‘for‘, ‘while‘, ‘repeat‘, ‘forever‘

• Grouping statements:

– Sequential block: ‘begin ... end‘

100
Chapter 7 Behavioral Modeling

– Parallel block: ‘fork ... join‘ (simulation only)

• Timing & Event Control:

– Delay Control: #10


– Event Control: (posedge clk)‘
– Wait statements
– Forever loop with event

Pro Tips and Tricks


Pro Tips
• Always use non-blocking in sequential logic for correct simulation.

• Avoid using ‘fork ... join‘ in synthesizable code. Use only for testbenches.

• Prefer ‘casez‘ for don’t-care conditions in case statements.

• Be careful with forever loops—ensure they are used inside testbenches.

• Combine ‘@(posedge clk)‘ with ‘forever‘ to simulate clocked behavior.

• Use ‘display‘and‘monitor‘ for effective debugging.

• Remember: ‘initial‘ blocks are ignored in hardware synthesis.

101
Chapter 8: Task and Function

Introduction
In Verilog, reusable blocks of code are essential for improving readability, modularity, and
scalability of complex designs. Tasks and functions serve this purpose by encapsulating
frequently used operations. While both can be invoked from procedural blocks, they differ
significantly in their usage and capabilities.
This chapter covers both in detail, helping you distinguish when and how to use them
effectively in real-world Verilog projects.

Learning Objectives
• Understand the purpose and syntax of tasks and functions.

• Differentiate between tasks and functions with examples and use-cases.

• Learn how to reuse blocks of Verilog code for better modularity.

• Write synthesizable tasks and functions in RTL.

• Gain confidence through 20 examples and 30 interview questions.

Why It Matters
Tasks and functions help you avoid repetition, reduce errors, and improve code
maintainability in Verilog. Whether writing RTL or testbenches, mastering these
will boost your efficiency and skillset.

102
Chapter 8 Task and Function

8.1 Tasks in Verilog


What is a Task?
A task in Verilog is a reusable block of procedural statements used to group commonly
executed operations. Tasks can contain:

• Multiple inputs, outputs, and inouts

• Delays (‘#‘), event controls, and timing

• System tasks like $display

• Nested blocks and control structures

Syntax of a Task
Task Syntax
task task_name;
input [bit_width] input_name;
output [bit_width] output_name;
inout [bit_width] inout_name;

// Task body
begin
// Statements
end
endtask

Key Features
• Can include delays (#) and event control (@).

• Can return multiple values using output and inout.

• Used for simulation and behavioral modeling.

• Cannot be used directly in continuous assignments.

103
Chapter 8 Task and Function

Example 1: Task with Input Only


task print_number;
input [3:0] num;
begin
$display("Number is: %d", num);
end
endtask

initial begin
print_number(4);
end

Output: Number is: 4

Example 2: Task with Input and Output


task multiply;
input [3:0] a, b;
output [7:0] result;
begin
result = a * b;
end
endtask

reg [7:0] res;

initial begin
multiply(3, 4, res);
$display("Result: %d", res);
end

Output: Result: 12

Example 3: Task with Delay


task delay_print;
input [3:0] delay_time;
begin

104
Chapter 8 Task and Function

#delay_time;
$display("Waited %d time units", delay_time);
end
endtask

initial begin
delay_print(5);
end

Output (after 5 units): Waited 5 time units

Pro Tips
• Tasks are powerful in testbenches and can simplify repeated sequences.

• Always use output and inout for returning values—functions cannot do


that.

• Avoid using tasks with delays in RTL blocks intended for synthesis.

• Use meaningful task names like add_two_nums, reset_dut, etc.

105
Chapter 8 Task and Function

Flowchart: Task Execution Logic


Start

Task Call

Execute Statements

Return Control

End

8.2 Functions in Verilog

What is a Function?
A function in Verilog is a reusable block of code that returns a single value. Functions are
primarily used for combinational logic without any timing delays.

• Functions must return exactly one value.

• They cannot include time-consuming operations like delays (#), event controls
(@), or wait statements.

• All inputs must be passed by value — there are no output or inout ports.

106
Chapter 8 Task and Function

Syntax of a Function
Function Syntax
function [bit_width] function_name;
input [bit_width] arg1;
input [bit_width] arg2;

begin
function_name = expression;
end
endfunction


Examples of Functions in Verilog

Example 1: Simple Addition Function


function [3:0] add;
input [3:0] a, b;
begin
add = a + b;
end
endfunction

initial begin
$display("Sum = %d", add(2, 3));
end

Output: Sum = 5

Example 2: Maximum of Two Numbers


function [3:0] max_val;
input [3:0] a, b;
begin
max_val = (a > b) ? a : b;
end
endfunction

107
Chapter 8 Task and Function

initial begin
$display("Max = %d", max_val(8, 12));
end

Output: Max = 12

Example 3: Bitwise AND Function


function [3:0] and_func;
input [3:0] a, b;
begin
and_func = a & b;
end
endfunction

initial begin
$display("AND = %b", and_func(4’b1101, 4’b1011));
end

Output: AND = 1001

Comparison Table: Tasks vs Functions

Feature Task Function


Return Value Can return multiple via out- Returns only one value
put/inout
Allowed in Assignments No Yes
Delays and Events Allowed (#, @) Not allowed
Time-Consuming Opera- Supported Not Supported
tions
Usage Context Testbenches, control se- Pure combinational logic
quences
Inputs/Outputs Input, output, inout supported Only inputs supported

108
Chapter 8 Task and Function

Call Syntax task_name(args); result =


func(args);
Synthesizability Some are, if no delays Mostly synthesizable

Pro Tips
• Use functions to simplify combinational logic like arithmetic, comparisons,
and encoding.

• Never include delays or non-synthesizable operations inside functions.

• Functions can be used within continuous assignments (‘assign‘) — tasks can-


not.

• Best suited for hardware logic that’s fast, predictable, and simple.

8.3 20 Examples of Tasks and Functions in Verilog


Example 1: Function for 4-bit Addition
function [3:0] adder;
input [3:0] a, b;
begin
adder = a + b;
end
endfunction

initial begin
$display("Sum = %d", adder(5, 10)); // Output: 15
end

Example 2: Task to Display a Message


task show_msg;

109
Chapter 8 Task and Function

input [7:0] msg;


begin
$display("Message: %s", msg);
end
endtask

initial begin
show_msg("Hello");
end

Example 3: Function to Calculate 2’s Complement


function [7:0] twos_comp;
input [7:0] a;
begin
twos_comp = ~a + 1;
end
endfunction

Example 4: Task to Wait for Delay and Print


task delay_print;
input integer d;
begin
#d;
$display("Waited for %0d time units", d);
end
endtask

Example 5: Function for Bit Reversal


function [3:0] reverse_bits;
input [3:0] data;
integer i;

110
Chapter 8 Task and Function

begin
for (i = 0; i < 4; i = i + 1)
reverse_bits[i] = data[3 - i];
end
endfunction

Example 6: Task to Compare Two Numbers


task compare;
input [3:0] x, y;
begin
if (x > y)
$display("X is greater");
else
$display("Y is greater or equal");
end
endtask

Example 7: Function to Count 1s in a Binary Number


function [2:0] count_ones;
input [3:0] val;
integer i;
begin
count_ones = 0;
for (i = 0; i < 4; i = i + 1)
count_ones = count_ones + val[i];
end
endfunction

Example 8: Task with Nested Blocks


task nested_example;
input [3:0] a;

111
Chapter 8 Task and Function

begin
begin
$display("Inner Block Value: %d", a);
end
end
endtask

Example 9: Function for XOR Operation


function xor_out;
input a, b;
begin
xor_out = a ^ b;
end
endfunction

Example 10: Task to Simulate Clock Generation


task generate_clk;
output clk;
begin
forever begin
#5 clk = ~clk;
end
end
endtask

112
Chapter 8 Task and Function

Example 11: Function to Convert Binary to Gray Code


function [3:0] bin2gray;
input [3:0] bin;
begin
bin2gray = bin ^ (bin >> 1);
end
endfunction

Example 12: Task for Counting Clock Cycles


task count_cycles;
input integer num;
integer i;
begin
for (i = 0; i < num; i = i + 1)
#10 $display("Cycle %0d", i);
end
endtask

Example 13: Function to Check Even or Odd


function is_even;
input [3:0] val;
begin
is_even = (val % 2 == 0);
end
endfunction

Example 14: Task to Swap Two Variables


task swap;
inout [3:0] a, b;
reg [3:0] temp;
begin

113
Chapter 8 Task and Function

temp = a;
a = b;
b = temp;
end
endtask

Example 15: Function to Compute Square


function [7:0] square;
input [3:0] a;
begin
square = a * a;
end
endfunction

Example 16: Task to Display ASCII Value


task ascii_val;
input [7:0] ch;
begin
$display("ASCII: %0d", ch);
end
endtask

Example 17: Function to Perform OR Reduction


function or_reduce;
input [3:0] data;
begin
or_reduce = |data;
end
endfunction

114
Chapter 8 Task and Function

Example 18: Task to Print an Array


task print_array;
input [7:0] arr [3:0];
integer i;
begin
for (i = 0; i < 4; i = i + 1)
$display("Element[%0d] = %0d", i, arr[i]);
end
endtask

Example 19: Function for Bitwise NOR


function bitwise_nor;
input [3:0] a, b;
begin
bitwise_nor = ~(a | b);
end
endfunction

Example 20: Task to Print Binary Representation


task print_binary;
input [3:0] data;
begin
$display("Binary = %b", data);
end
endtask

8.4 30 Practice and Interview Questions on Tasks and Func-


tions
Conceptual Questions
1. What is the difference between a task and a function in Verilog?

115
Chapter 8 Task and Function

2. Why can’t a function contain ‘delay‘, ‘event‘, or ‘wait‘ statements?

3. Can a function call a task? Why or why not?

4. How are input, output, and inout ports used differently in tasks and functions?

5. Can tasks be used in synthesizable RTL code?

6. What are the default data types of function return values?

7. Explain the difference between automatic and static tasks/functions.

8. What happens if a task never terminates inside a testbench?

9. Can a function have more than one return statement?

10. In what scenario would you choose a task over a function?

Fill-in-the-Blank and True/False


a. Tasks are generally (synthesizable/non-synthesizable).

b. A function must return exactly value.

c. True/False: A task can include time control statements.

d. True/False: A function can return multiple values.

Code Output Prediction


5. Predict the output:

116
Chapter 8 Task and Function

function [3:0] sum;


input [3:0] a, b;
begin
sum = a + b;
end
endfunction

initial begin
$display("%d", sum(4’d3, 4’d5));
end

6. What will be printed?

task show_delay;
input [3:0] x;
begin
#x;
$display("Delayed by %d", x);
end
endtask

initial begin
show_delay(4);
end

Debugging Based Questions


7. Identify and correct the error in the following code:

function add_numbers;
input [3:0] a, b;
add_numbers = a + b;
endfunction

117
Chapter 8 Task and Function

8. Fix the issue:

task invalid_delay;
input [3:0] a;
begin
$display("Waiting...");
wait(a == 1);
end
endfunction

Design Questions
9. Design a function that counts the number of 1’s in an 8-bit input.

10. Design a task that swaps two 8-bit values using ‘inout‘.

11. Implement a function that performs a logical AND operation on two inputs and
returns the result.

12. Write a task that accepts an input and displays whether it is odd or even.

13. Design a function that performs a priority encoding for 4-bit input.

14. Create a task to simulate a 5-cycle clock pulse.

15. Implement a function to find the maximum of three 4-bit numbers.

16. Create a task to generate a PWM signal (simulate with delay and display).

17. Write a function to return the absolute value of a signed input.

18. Design a task to loop through an array and print each value.

118
Chapter 8 Task and Function

8.5 Pro Tips


Pro Tips for Mastering Tasks and Functions
• Use function for simple combinational calculations — keep it short and
delay-free!

• Use task when you need delays, multiple outputs, or procedural operations.

• Never insert a delay (#), event, or wait statement in a function — this violates
synthesizable code rules.

• Automatic tasks/functions are preferred in testbenches to avoid variable


overwriting.

• Always verify that your task ends (no infinite waits) — to avoid simulation
hang.

• For large testbenches, organize reusable components into tasks/functions to


improve modularity.

• Remember: A task can call another task or function, but a function can
**only** call another function.

• Use ‘begin...end‘ in tasks and functions to enclose multiple statements.

8.6 Summary
• Verilog provides two primary subprograms: task and function, to modularize
repeated logic.

• Tasks:

– Can contain delays, events, and wait statements.


– Can have input, output, and inout ports.
– Used for procedural, time-based simulation and verification tasks.

• Functions:

– Must execute in zero simulation time.

119
Chapter 8 Task and Function

– Only one output value (return).


– Cannot contain delays or time controls.

• Tasks and functions can be defined as automatic (reentrant) or static (default).

• While functions are preferred in RTL design (synthesizable logic), tasks are mainly
used in testbenches.

• Both are reusable, modular constructs that improve code clarity, testability, and
maintenance.

120
Chapter 9 : Useful Modelling Technique

Introduction
In Verilog, modeling techniques are not just limited to ‘module‘, ‘initial‘, or ‘always‘
blocks. For simulation clarity, debugging, and performance tuning, certain special model-
ing methods are frequently used. These include procedural assignments, conditional com-
pilation, timescale precision, dump files, and more. This chapter explores all these useful
modeling strategies in depth, which are especially critical in verification environments and
testbench construction.

Learning Objectives
• Understand the purpose and syntax of procedural continuous assignments (‘assign-
deassign‘, ‘force-release‘).
• Learn conditional compilation and execution techniques for flexible code testing.
• Set and manipulate simulation time precision using ‘timescale‘.
• Use system tasks like ‘display‘, ‘monitor‘, and $time‘ effectively.
• Generate and interpret waveform files using Value Change Dump (VCD).

9.1 Procedural Continuous Assignment


Procedural continuous assignments allow a procedural block (like ‘initial‘ or ‘always‘)
to drive a net continuously using ‘assign‘ and ‘deassign‘, or override it using ‘force‘ and
‘release‘.

121
Chapter 9 Useful Modelling Technique

9.0.1 assign-deassign
The ‘assign‘ statement in a procedural context behaves similarly to a continuous assign-
ment, except it is done within an ‘initial‘ or ‘always‘ block.

Syntax
assign <net> = <value>;
deassign <net>;

Example: “‘verilog reg clk; initial begin assign clk = 1; #5; deassign clk; // Removes
the continuous assignment end

9.0.2 force-release
The force statement overrides any existing value or driver on a signal (net or variable), and
release restores the previous value.

Syntax
force <net/var> = <value>; release <net/var>;

Example:
reg reset; initial begin force reset = 1; // Overrides all other drivers #10; release reset;
// Restores value from other sources end

Comparison Table: assign-deassign vs force-release

Feature assign-deassign force-release


Applies to Only nets (e.g., wire) Both nets and variables
Usage Context Used in procedural blocks Used in testbenches or special
cases
Restoration Method deassign release
Synthesizable No No
Preferred Use Net override simulation Temporary forcing in simula-
tion

122
Chapter 9 Useful Modelling Technique

Pro Tip
Pro Tip
Avoid using assign-deassign and force-release in RTL. These constructs are meant
only for simulation and can create undefined behaviors if mixed with synthesizable
logic.

9.2 Conditional Compilation and Execution


In Verilog, conditional compilation allows you to selectively include or exclude parts of
the code during **compile-time** using special compiler directives. These are particu-
larly useful when working with testbenches, simulation-only features, or platform-specific
modules.

Why Use Conditional Compilation?


• To enable/disable debug code without removing it.
• To include simulation-only logic without affecting synthesis.
• To manage different versions of modules or test environments.

Common Directives
• \‘ifdef MACRO – Compile if macro is defined.
• \‘ifndef MACRO – Compile if macro is **not** defined.
• \‘else – Alternate code when ‘ifdef fails.
• \‘endif – Ends a conditional directive block.
• \‘define MACRO – Defines a macro.
• \‘undef MACRO – Undefines a macro.

123
Chapter 9 Useful Modelling Technique

Syntax

Syntax
‘define DEBUG

module example;
...
‘ifdef DEBUG
initial $display("Debug Mode Enabled");
‘endif
endmodule

Example 1: Basic Conditional Block


‘define SIMULATION

module tb;
initial begin
‘ifdef SIMULATION
$display("This is a simulation-only block.");
‘endif
$display("Testbench running...");
end
endmodule

Output (when SIMULATION defined):


Output (when SIMULATION undefined):

Example 2: Using ‘else‘ and ‘ifndef‘


‘define ASIC

module check;
initial begin
‘ifdef ASIC
$display("ASIC flow selected.");

124
Chapter 9 Useful Modelling Technique

‘else
$display("FPGA flow selected.");
‘endif
end
endmodule
Output:

Comparison Table: ‘ifdef vs ifndef‘

Feature ‘ifdef ‘ifndef


Condition Executes block if macro is de- Executes block if macro is not
fined defined
Common Usage Enable code for debug/test Exclude simulation-only
mode code in synthesis
Typical Use-case Debug, logging, platform RTL exclusion from sim-
flags specific features

Pro Tips
Pro Tips
• Always end conditional compilation blocks with ‘endif to avoid errors.

• Use meaningful macro names like SIMULATION, DEBUG, SYNTHESIS.

• Never include hardware logic inside ‘ifdef blocks that are excluded during
synthesis.

• Group macro definitions at the top of the file for better readability.

9.3 Timescale Directive


In Verilog, the ‘‘timescale‘ directive is used to specify the time unit and time preci-
sion for simulation. This directive is essential for simulation accuracy, particularly when

125
Chapter 9 Useful Modelling Technique

working with delays (e.g., #5).

Syntax

Syntax Format
‘timescale <time_unit> / <time_precision>

Example:
‘timescale 1ns / 1ps
This means:
• 1ns is the time unit: delay values such as #1 mean 1 nanosecond.
• 1ps is the time precision: how accurate the simulator tracks time events.

Why Timescale Matters?


• Affects interpretation of ‘#‘ delays in simulation.
• Helps ensure consistent simulation timing across modules.
• Needed to avoid mismatches when integrating third-party IPs or modules.

Example: Simple Timescale Use


‘timescale 1ns / 1ps

module test;
initial begin
#1 $display("1ns passed");
#2 $display("2ns more passed");
end
endmodule
Output:

126
Chapter 9 Useful Modelling Technique

Valid Time Units and Precisions

• s, ms, us, ns, ps, fs

• Precision should be equal to or smaller than the time unit

Example: Incorrect Precision

‘timescale 1ns / 10ns // Incorrect!

Error: Precision must not be greater than the time unit.

Comparison Table: Time Unit vs Time Precision

Aspect Time Unit Time Precision


Meaning Base unit for delay expres- Accuracy in simulation time
sions tracking
Use-case Determines how long a delay Controls rounding in time
like #5 lasts calculations
Example Value 1ns, 10ps 100ps, 1ps
Dependency Delay interpretation depends Must be ≤ Time Unit
on this
Impact Simulation realism and be- Delay rounding and event
havior scheduling

127
Chapter 9 Useful Modelling Technique

Pro Tips

Pro Tips
• Always define ‘timescale at the top of every Verilog file for consistency.

• Mismatched timescales between modules can lead to subtle simulation errors.

• Use higher precision (e.g., 1ps) in testbenches for more accurate timing con-
trol.

• For FPGA/ASIC flow, timescale has no synthesis impact — it’s for simulation
only.

Useful System Tasks in Verilog


System tasks in Verilog are special constructs that begin with a dollar sign ($) and are used
to perform operations like displaying output, monitoring signals, file I/O, and controlling
simulation. These are only used during simulation and are not synthesizable.

1. $display

Prints messages to the console. Executes only once when called.

Syntax and Example


$display("Value of A = %b", A);

Formats:

• %b - binary

• %d - decimal

• %h - hexadecimal

128
Chapter 9 Useful Modelling Technique

2. $monitor
Continuously prints whenever any variable in the list changes.

$monitor("Time = %0t, A = %b, B = %b", $time, A, B);

3. $time, $stime, $realtime


Used to access simulation time.

• $time – returns 64-bit integer

• $stime – returns 32-bit integer

• $realtime – returns real value

$display("Current time = %0t", $time);

4. $finish and $stop


• $stop – Halts simulation temporarily, user can resume.

• $finish – Completely ends the simulation.

#100 $finish; // End simulation at 100 time units

5. $dumpfile and $dumpvars


Used for waveform generation in simulation (especially with GTKWave).

$dumpfile("waveform.vcd"); // Create VCD file


$dumpvars(0, test); // Log all signals in module "test"

Note: Must be placed in the testbench.

129
Chapter 9 Useful Modelling Technique

Comparison Table: Common System Tasks

Task Purpose Usage Scenario


$display Prints a message once For showing variable values
$monitor Prints on change of any variable in For monitoring multiple vari-
list ables
$time Returns simulation time For debugging delays and timing
$stop Halts simulation temporarily For intermediate pause in simu-
lation
$finish Ends simulation To terminate testbench automat-
ically
Create waveform dump
$dumpfile/$dumpvars To analyze behavior using tools
like GTKWave

Pro Tips
Pro Tips
• Prefer $display for static messages and $monitor for tracking changes
over time.

• Always use $finish in testbenches to avoid indefinite simulations.

• Combine $dumpfile and $dumpvars for waveform analysis.

• Use $time with $display to log when certain events occur.

• System tasks are non-synthesizable; they are used only for simulation and
debugging.

9.4 Value Change Dump (VCD) File in Verilog


A Value Change Dump (VCD) file records all the changes in signal values during simu-
lation and can be viewed using waveform viewers like GTKWave. This helps in visually
debugging and analyzing how signals behave over time.

130
Chapter 9 Useful Modelling Technique

Purpose
The VCD file stores simulation signal changes in a time-stamped format, allowing the user
to examine transitions, glitches, or timing issues.

Why Use a VCD File?


• To visualize waveform for better understanding

• To detect bugs or signal contention

• To analyze timing behavior

• Essential in debugging large testbenches

Steps to Generate a VCD File

How to Generate a VCD File


1. Use $dumpfile("filename.vcd") to specify output file.

2. Use $dumpvars(0, top_module) to log signals starting from top.

3. Place these in the initial block of your testbench.

Example
module tb;
reg clk, rst;
initial begin
$dumpfile("waveform.vcd");
$dumpvars(0, tb);
end

initial begin
clk = 0;
forever #5 clk = ~clk;

131
Chapter 9 Useful Modelling Technique

end

initial begin
rst = 1;
#10 rst = 0;
end
endmodule

Waveform Viewer
Tools like GTKWave allow you to load VCD files and inspect each signal’s behavior
during simulation.
Usage:
• After simulation, run:

gtkwave waveform.vcd

• You’ll see the signal transitions and can zoom/pan through time.

Comparison Table: VCD vs System Task Outputs

Feature VCD File (GTKWave) System Tasks ($display, $mon-


itor)
Visibility Graphical waveform of all Console message only
signals
Detail Level Very high – includes every Limited to user-defined mes-
transition sages
Storage Output in a file (view later) Printed during simulation only
Best For Post-simulation waveform Quick value checks during run
debugging
Synthesis Impact None (simulation-only) None (simulation-only)

132
Chapter 9 Useful Modelling Technique

Pro Tips
Pro Tips
• Keep your VCD file size small by using specific levels: $dumpvars(1,
module) logs only top level.

• Use GTKWave bookmarks and hierarchy view to quickly navigate large de-
signs.

• VCD logging slows down simulation — only use when needed.

• VCD does not capture memories or variables by default — use tools like
$dumpvars deeply or switch to FST or other formats if needed.

9.5 10 Practical Examples of Useful Modeling Techniques


Example 1: Using assign-deassign
module assign_example;
reg clk;
wire data;

initial begin
assign data = clk;
#5 clk = 1;
#10 clk = 0;
deassign data;
end
endmodule

Explanation: The ‘data‘ net is connected to ‘clk‘ temporarily using ‘assign‘. Once
‘deassign‘ is executed, ‘data‘ becomes undriven.

Example 2: Using force-release


module force_example;
reg a, b;

133
Chapter 9 Useful Modelling Technique

initial begin
a = 0;
force b = a;
#5 a = 1;
#10 release b;
end
endmodule

Explanation: The value of ‘b‘ is forcibly tied to ‘a‘. Even if ‘a‘ changes, ‘b‘ follows
until ‘release‘ is issued.

Example 3: Conditional Compilation


‘define DEBUG
module cond_compile;
initial begin
‘ifdef DEBUG
$display("Debugging enabled");
‘else
$display("Debugging off");
‘endif
end
endmodule

Example 4: Timescale Usage


‘timescale 1ns/1ps
module delay_example;
reg clk = 0;
always #10 clk = ~clk;
endmodule

Explanation: Every delay (e.g., #10) is interpreted in nanoseconds with 1ps precision.

134
Chapter 9 Useful Modelling Technique

Example 5: Dumping VCD File


module vcd_test;
reg a, b;

initial begin
$dumpfile("waveform.vcd");
$dumpvars(0, vcd_test);
a = 0; b = 1;
#5 a = 1;
#5 b = 0;
end
endmodule

Example 6: Using $monitor


module monitor_demo;
reg x, y;
initial $monitor("Time=%0t, x=%b, y=%b", $time, x, y);

initial begin
x = 0; y = 0;
#10 x = 1;
#10 y = 1;
end
endmodule

Example 7: Using $time


module time_demo;
initial begin
#5 $display("Time is %0t", $time);
end
endmodule

135
Chapter 9 Useful Modelling Technique

Example 8: Releasing Force in Testbench


module tb;
reg a;
wire b;

assign b = a;

initial begin
a = 0;
force b = 1; // overrides the assign
#10 release b; // returns to original assignment
end
endmodule

Example 9: Using $display to Debug FSM


module debug_fsm;
reg clk = 0;
reg [1:0] state = 0;

always #5 clk = ~clk;

always @(posedge clk) begin


$display("Time=%0t, State=%b", $time, state);
state = state + 1;
end
endmodule

Example 10: Combining assign-deassign and $display


module combo_demo;
reg clk;
wire out;

initial begin

136
Chapter 9 Useful Modelling Technique

clk = 0;
assign out = clk;
$display("Assigned out to clk");
#5 clk = 1;
#5 deassign out;
$display("Deassigned out");
end
endmodule

9.6 30 Practice and Interview Questions


Conceptual Questions
1. What is the purpose of ‘assign‘ and ‘deassign‘ in Verilog?

2. Differentiate between ‘force‘ and ‘assign‘.

3. What happens when ‘deassign‘ is not used after ‘assign‘?

4. What is the main difference between ‘assign-deassign‘ and ‘force-release‘?

5. Can ‘force‘ be used on a ‘reg‘ type variable?

6. Why are ‘assign-deassign‘ and ‘force-release‘ not synthesizable?

7. In what type of design would you use ‘force-release‘?

8. What is the role of ‘release‘ in the simulation?

9. When should you use conditional compilation in Verilog?

10. What happens if ‘release‘ is called without a prior ‘force‘?

Code-Based Questions
11. Write a code to demonstrate conditional compilation using ‘ìfdef‘ and ‘èlse‘.

12. Simulate a waveform using ‘dumpf ile‘and‘dumpvars‘.

13. Implement a counter and use ‘$monitor‘ to track its changes.

14. Write a testbench to demonstrate ‘assign-deassign‘ behavior.

137
Chapter 9 Useful Modelling Technique

15. Use $display to print internal signals during simulation.


16. Demonstrate a scenario where ‘force‘ is used to override a wire.
17. Simulate a D Flip-Flop and use ‘$time‘ to observe clock edge delays.
18. Apply ‘assign‘ to a wire and change it with ‘deassign‘.
19. Write a Verilog block using ‘force-release‘ to control a variable in a testbench.
20. Create a waveform viewer using ‘gtkwave‘ and VCD file.

Interview-Oriented Questions
21. Explain a real scenario where ‘assign-deassign‘ can be helpful.
22. What would you recommend for temporarily overriding a signal: ‘assign‘ or ‘force‘?
Why?
23. Are ‘assign‘ and ‘force‘ synthesizable? Why or why not?
24. How can timescale affect simulation resolution and delay interpretation?
25. How can you disable a portion of code during simulation without commenting it?
26. Describe the contents of a VCD file.
27. Why is dumpvars essential during waveform analysis?
28. If a forced value is never released, what simulation issues may occur?

9.7 Pro Tips


Pro Tip 1
Use ‘force-release‘ carefully in testbenches, especially if multiple signals are inter-
acting — releasing one too early may lead to race conditions.

Pro Tip 2
Always pair ‘assign‘ with ‘deassign‘ and ‘force‘ with ‘release‘. Forgetting to undo
forced assignments can cause inconsistent simulations.

138
Chapter 9 Useful Modelling Technique

Pro Tip 3
Use conditional compilation (‘ìfdef‘ / ‘èlse‘) for debugging sections of your
code — much easier than commenting/uncommenting multiple lines.

Pro Tip 4
Generate VCD files (‘.vcd‘) and open in GTKWave to visually debug simulation
behavior and waveform transitions in time.

Summary
• Procedural continuous assignments include ‘assign-deassign‘ and ‘force-release‘,
used primarily in simulation for overriding signal values.

• ‘assign-deassign‘ is limited to nets and is useful in temporary overriding of drivers.

• ‘force-release‘ can be used on both nets and variables, giving more flexibility during
testing.

• Conditional compilation (‘ìfdef‘, ‘èndif‘) helps manage design variations and


debug-specific logic during simulation.

• Timescale affects how delays are interpreted in simulation — using it correctly en-
sures proper timing behavior.

• System tasks like ‘display‘, ‘monitor‘, ‘time‘, and‘dumpvars‘ help monitor and de-
bug simulation behavior.

• Value Change Dump (VCD) files store simulation transitions and are visualized us-
ing tools like GTKWave.

139
Chapter 10 : Finite State Machines
(FSM) in Verilog

Introduction
Finite State Machines (FSMs) are foundational in digital design. They model systems
that move between various states based on input and timing, making them crucial for
everything from vending machines and traffic lights to protocol controllers and embedded
systems.
In Verilog, FSMs are implemented using sequential logic inside always blocks,
driven by a clock signal and typically reset at startup. This chapter explains the theory
and practical implementation of FSMs in Verilog.

Learning Objectives
• Understand the concept and components of FSMs.

• Learn the differences between Mealy and Moore FSMs.

• Design and code FSMs in Verilog using different coding styles.

• Use appropriate state encoding methods: binary, one-hot, or gray.

• Analyze, simulate, and debug FSM-based Verilog models.

140
Chapter 10 Finite State Machines (FSM) in Verilog

10.1 What is an FSM?


A Finite State Machine (FSM) is a sequential logic circuit with a defined set of states. The
system transitions between these states based on input conditions, and produces outputs
either based on the current state (Moore) or both the current state and input (Mealy).
Key Components:

• States: Operational modes like IDLE, RUN, etc.

• Inputs: Control or triggering signals.

• Outputs: Based on the FSM type.

• Transitions: Defined rules to switch between states.

• Clock/Reset: Synchronization and reset control.

10.2 Types of FSMs


Comparison Table: Moore vs Mealy FSMs

Feature Moore Machine Mealy Machine


Output Depends On Current state only Current state + Input
Latency Higher (output updated after Lower (output changes immedi-
transition) ately with input)
Design Complexity Simpler logic, more states Fewer states, complex logic
Timing Behavior More stable outputs Outputs may glitch if inputs
change
Common Usage Control-based FSMs Fast-responsive FSMs

141
Chapter 10 Finite State Machines (FSM) in Verilog

10.3 Moore FSM in Verilog

Structure

• State Register: Stores current state.

• Next-State Logic: Determines next state based on current state and input.

• Output Logic: Based only on the current state.

142
Chapter 10 Finite State Machines (FSM) in Verilog

Verilog Code Example


Moore FSM Code Template
module moore_fsm (
input clk, reset,
input in,
output reg out
);
typedef enum logic [1:0] {IDLE, S1, S2} state_t;
state_t state, next_state;

// State transition
always_ff @(posedge clk or posedge reset) begin
if (reset)
state <= IDLE;
else
state <= next_state;
end

// Next-state logic
always_comb begin
case(state)
IDLE: next_state = in ? S1 : IDLE;
S1: next_state = in ? S2 : IDLE;
S2: next_state = in ? S2 : IDLE;
default: next_state = IDLE;
endcase
end

// Output logic (Moore: based on state)


always_comb begin
case(state)
IDLE: out = 0;
S1: out = 0;
S2: out = 1;
endcase
end
endmodule

143
Chapter 10 Finite State Machines (FSM) in Verilog

Pro Tip
Pro Tip
Use meaningful state names and consistent indentation to make FSM code easy to
read and debug. Use enumerated types (SystemVerilog) for improved readability
and simulation debugging.

Flowchart

in=0

in=1 in=1
IDLE S1 S2
in=1
in=0
in=0

10.4 Mealy FSM in Verilog


Structure
• State Register: Stores the current state.
• Next-State Logic: Decides next state based on current state and input.
• Output Logic: Based on both current state and current input.

Key Differences from Moore FSM


• Outputs can change immediately on input change, without waiting for clock edge.
• Typically requires fewer states compared to Moore FSM.
• Output may glitch if input is not stable.

144
Chapter 10 Finite State Machines (FSM) in Verilog

Verilog Code Example: Mealy FSM

Mealy FSM Code Template


module mealy_fsm (
input clk, reset,
input in,
output reg out
);
typedef enum logic [1:0] {IDLE, S1} state_t;
state_t state, next_state;

// State transition
always_ff @(posedge clk or posedge reset) begin
if (reset)
state <= IDLE;
else
state <= next_state;
end

// Next state logic


always_comb begin
case(state)
IDLE: next_state = in ? S1 : IDLE;
S1: next_state = in ? S1 : IDLE;
default: next_state = IDLE;
endcase
end

// Output logic (Mealy: based on state and input)


always_comb begin
case(state)
IDLE: out = 0;
S1: out = in ? 1 : 0;
endcase
end
endmodule

145
Chapter 10 Finite State Machines (FSM) in Verilog

Flowchart

in=0

in=1
IDLE S1
in=0 in=1

Pro Tip
Pro Tip
Use non-blocking assignments for state transitions and blocking assignments for
combinational next-state/output logic. Keep output logic separate to avoid synthesis
mismatches or latch inference.

Use Case:
Mealy FSMs are ideal in designs where quick output response is needed without waiting
for a full state update. Examples: real-time protocol monitors, handshaking circuits, or
interface detection.

10.5 FSM Coding Styles


Finite State Machines (FSMs) can be written in Verilog using different coding method-
ologies. Each style affects readability, synthesis, and debugging. The three most common
styles are:
• One-Hot Style (Flat)
• Sequential (Three-Block Style)
• Moore/Mealy Encoding within Case Statements

146
Chapter 10 Finite State Machines (FSM) in Verilog

1. One-Hot (Flat) FSM Style

Description: All states are declared as individual bits, and only one bit is active at a time.

Verilog Snippet: One-Hot FSM


reg [3:0] state;
parameter S0 = 4’b0001, S1 = 4’b0010, S2 = 4’b0100, S3 = 4’b1000;

always @(posedge clk or posedge reset) begin


if (reset)
state <= S0;
else begin
case (state)
S0: state <= in ? S1 : S0;
S1: state <= S2;
S2: state <= S3;
S3: state <= S0;
endcase
end
end

2. Three-Block FSM Style

Description: Splits FSM into three separate blocks for:

• State Register

• Next-State Logic

• Output Logic

147
Chapter 10 Finite State Machines (FSM) in Verilog

Structure of 3-block FSM


// 1. State Register
always_ff @(posedge clk or posedge reset)
if (reset)
state <= IDLE;
else
state <= next_state;

// 2. Next-State Logic
always_comb begin
case (state)
IDLE: next_state = (in) ? S1 : IDLE;
...
endcase
end

// 3. Output Logic
always_comb begin
case (state)
...
endcase
end

3. FSM Using Case Statements (Embedded Style)

Description: Common in simpler FSMs. Combines all logic in one always block.

148
Chapter 10 Finite State Machines (FSM) in Verilog

Embedded FSM Style


always @(posedge clk or posedge reset) begin
if (reset)
state <= IDLE;
else begin
case (state)
IDLE: if (in) state <= S1;
...
endcase
end
end

Comparison Table: FSM Coding Styles

Feature Three-Block FSM One-Hot / Flat FSM


Readability High Medium
Debugging Ease Easy due to modular Complex for large FSMs
blocks
Synthesis Friendly Yes Yes (tool dependent)
Resource Usage Minimal May use more FFs
Output Latency One clock delay (Moore) Immediate (Mealy)
Best For RTL FSMs with clarity Small control logic, fast
outputs

149
Chapter 10 Finite State Machines (FSM) in Verilog

Pro Tip

Pro Tip
Use 3-block FSMs for clean synthesis and easier maintenance. Flat FSMs are pre-
ferred in high-speed design where latency is critical, especially for Mealy-style ma-
chines.

10.6 State Encoding Techniques


State encoding is the method used to assign binary values to symbolic states of a Finite
State Machine. The encoding impacts performance, area, and power. The most common
types are:

• Binary Encoding

• One-Hot Encoding

• Gray Encoding

• Johnson Encoding

1. Binary Encoding
Each state is assigned a unique binary number. It uses the minimum number of flip-flops
(log2 (N ), where N is the number of states).
Example: 4 States (S0, S1, S2, S3)

Binary Encoding
parameter S0 = 2’b00, S1 = 2’b01, S2 = 2’b10, S3 = 2’b11;

Pros: Efficient in flip-flop usage. Cons: Slower decoding due to complex logic.

150
Chapter 10 Finite State Machines (FSM) in Verilog

2. One-Hot Encoding
Each state uses a separate bit; only one bit is high at any time.
Example: 4 States

One-Hot Encoding
parameter S0 = 4’b0001, S1 = 4’b0010, S2 = 4’b0100, S3 = 4’b1000;

Pros: Fast decoding, simpler combinational logic. Cons: Uses more flip-flops.

3. Gray Encoding
Only one bit changes between adjacent states. Good for low power or noise-sensitive
applications.
Example: 3-bit Gray Code

000, 001, 011, 010, 110, 111, 101, 100

Pros: Reduces glitches in transitions. Cons: More complex to decode and implement.

4. Johnson Encoding
A twist on Gray encoding. It uses shift register logic with feedback.
Example: For 4 bits:

0000 → 0001 → 0011 → 0111 → 1111 → 1110 → 1100 → 1000

Pros: Suitable for counters and FSM sequencing. Cons: Less popular in general FSM
designs.

Comparison Table: State Encoding Techniques

Feature Binary One-Hot Gray/Johnson


Flip-Flop Usage Minimum (log2 N ) One per state Medium
Decoding Logic Complex Simple Moderate

151
Chapter 10 Finite State Machines (FSM) in Verilog

Glitch Resistance Low High High


Speed Medium Fast High
Power Consumption Low Medium/High Low
Best Use Case Large FSMs Small, Fast FSMs Noise-sensitive
FSMs

Pro Tip
Pro Tip
Use Binary encoding for large FSMs to save area. Use One-Hot for speed-critical
paths or when FSMs are small. Gray coding is ideal for crossing clock domains or
reducing switching noise.

10.7 FSM Design Examples


To understand FSM design better, let us implement two practical examples:

• Example 1: Moore FSM – Sequence Detector for “101”

• Example 2: Mealy FSM – Parity Detector

Example 1: Moore FSM – Sequence Detector “101”


Problem: Design a Moore FSM that detects the sequence “101” from serial input and
outputs 1 when the sequence is found.
States:

• S0: Initial state

• S1: ‘1’ received

152
Chapter 10 Finite State Machines (FSM) in Verilog

• S2: ‘10’ received

• S3: ‘101’ detected (Output = 1)

Verilog Code:

Moore FSM: 101 Detector


module moore_101_detector(input clk, rst, x, output reg y);
typedef enum reg [1:0] {S0, S1, S2, S3} state_t;
state_t state, next_state;

always @(posedge clk or posedge rst) begin


if (rst)
state <= S0;
else
state <= next_state;
end

always @(*) begin


case(state)
S0: next_state = (x == 1) ? S1 : S0;
S1: next_state = (x == 0) ? S2 : S1;
S2: next_state = (x == 1) ? S3 : S0;
S3: next_state = (x == 1) ? S1 : S0;
endcase
end

always @(*) begin


case(state)
S3: y = 1;
default: y = 0;
endcase
end
endmodule

Output: Output goes HIGH after receiving the sequence 101.

153
Chapter 10 Finite State Machines (FSM) in Verilog

Example 2: Mealy FSM – Even Parity Detector

Problem: Detect whether the incoming serial bit stream has even parity using a Mealy
FSM.

States:

• S0: Even number of 1s so far

• S1: Odd number of 1s so far

Output:

• y = 1 if even parity

• y = 0 if odd parity

Verilog Code:

154
Chapter 10 Finite State Machines (FSM) in Verilog

Mealy FSM: Even Parity Detector


module mealy_parity(input clk, rst, x, output reg y);
typedef enum reg {S0, S1} state_t;
state_t state, next_state;

always @(posedge clk or posedge rst) begin


if (rst)
state <= S0;
else
state <= next_state;
end

always @(*) begin


case(state)
S0: begin
y = (x == 0) ? 1 : 0;
next_state = (x == 0) ? S0 : S1;
end
S1: begin
y = (x == 1) ? 1 : 0;
next_state = (x == 1) ? S0 : S1;
end
endcase
end
endmodule

Output: High output when parity is even, updated on each input.

Pro Tip

Pro Tip
Use Moore FSM when output depends only on the current state — it’s easier to test.
Use Mealy FSM for faster output responses, especially in reactive systems.

155
Chapter 10 Finite State Machines (FSM) in Verilog

10.8 Practice and Interview Questions


This section includes carefully curated questions that assess your understanding of FSM
design, Mealy vs Moore implementation, and practical application in Verilog.

A. Conceptual Questions
1. What is the key difference between Mealy and Moore state machines?

2. Why is the output of a Moore FSM more stable than that of a Mealy FSM?

3. How does state encoding affect the performance of an FSM?

4. What are the types of state encoding in FSMs?

5. What are the benefits of one-hot encoding in large FSMs?

6. Can combinational logic be used inside FSMs? Why or why not?

7. How can you minimize the number of states in an FSM?

8. What is a state transition table? How is it used?

9. Describe an FSM for a traffic light controller.

10. What are the common causes of glitches in FSM output?

B. Coding/Verilog-Oriented Questions
11. Write a Verilog code for a Moore FSM to detect the sequence “101”.

12. Write a Verilog code for a Mealy FSM that detects “110” and resets after detection.

13. Modify an FSM to add a reset condition asynchronously.

14. Design a FSM in Verilog that generates a pulse every third clock cycle.

15. Code an FSM with three states: IDLE, LOAD, and DONE. Transition upon specific
inputs.

16. Use one-hot encoding to implement a 4-state FSM.

17. Convert a state diagram to Verilog HDL code.

156
Chapter 10 Finite State Machines (FSM) in Verilog

18. Debug a faulty FSM that remains stuck in a single state.

19. What are the best practices to define parameters for states?

20. Implement a traffic light controller FSM in Verilog using case statements.

C. Interview-Focused Scenario-Based Questions


21. During simulation, your FSM skips a state. What could be the cause?

22. Your FSM works in simulation but not in synthesis. What would you check?

23. How would you optimize an FSM for power reduction?

24. Explain the difference between blocking and non-blocking assignments in FSMs.

25. How do you test an FSM thoroughly using testbenches?

26. What debugging strategy would you apply if the FSM is unstable after reset?

27. In which cases would you prefer a Mealy FSM over a Moore FSM?

28. What are the synthesis considerations for large FSMs?

29. Describe a scenario where a FSM interacts with another FSM.

30. How would you implement a lock/unlock FSM using a combination of state and
input verification?

157
Chapter 10 Finite State Machines (FSM) in Verilog

10.9 Pro Tips

Pro Tips for FSMs


• Use Parameters for State Naming: Always define state names using ‘pa-
rameter‘ or ‘typedef enum‘ (in SystemVerilog) for readability and ease of
maintenance.

• Avoid Latches: Ensure that all state transitions and outputs are defined for
every possible condition to prevent unintended latch inference.

• One-Hot for Speed, Binary for Area: Choose one-hot encoding for faster
FSMs when area isn’t a concern. Prefer binary/gray encoding for area-
sensitive designs.

• Use Reset Wisely: Include asynchronous or synchronous resets explicitly for


FSM stability, especially at power-up.

• Case Statements for Clarity: Implement state transitions using ‘case‘ or


‘casez‘ for clear and synthesizable designs.

• Keep FSM Combinational and Synchronous Logic Separate: Separate


state transition logic and output logic to simplify debugging and synthesis.

• Use Simulation Assertions: While debugging FSMs, use ‘assert‘, ‘display‘,


and ‘monitor‘ system tasks to check state behavior.

• Document State Diagrams: Maintain updated state diagrams to map your


HDL implementation clearly — this helps in design reviews and debugging.

• Avoid Unused States: Ensure all defined states are reachable. Unreachable
states increase area and can cause simulation warnings.

• Modularize FSMs: For complex designs, modularize FSMs and connect


them through clearly defined interfaces to avoid spaghetti logic.

158
Chapter 10 Finite State Machines (FSM) in Verilog

10.10 Mindmap: FSM Design Concepts

Verilog
Testbenches
Case Model

Debug/Simulation Reset/Clocking

FSM

State
Moore
Encoding

State
Mealy
Diagrams

159
Chapter 11: Memory Modeling in
Verilog

Introduction
Memory modeling is an essential aspect of digital design, enabling the representation of
storage elements such as RAM, ROM, and register files in Verilog. These models are used
to simulate how memory components behave and interact with the rest of a digital system.
In Verilog, memory is modeled using arrays and procedural constructs. Memory types
can be classified into:

• ROM (Read-Only Memory) – initialized and read-only.

• RAM (Random Access Memory) – readable and writable.

• Register Files – sets of registers used for temporary data storage.

Memory elements are non-synthesizable unless properly mapped with synthesis direc-
tives or inferred using coding styles recognized by tools.
Understanding memory modeling allows designers to:

• Write behavioral models of memory for simulation.

• Create synthesizable memory blocks.

• Integrate memories with FSMs, datapaths, and controllers.

160
Chapter 11 Memory Modeling in Verilog

Learning Objectives
After completing this chapter, you will be able to:

• Understand memory declaration in Verilog.

• Model and simulate ROM and RAM behavior.

• Differentiate between behavioral and synthesizable memory.

• Implement read/write operations on memory.

• Create testbenches for memory verification.

11.1 Memory Declaration and Types


In Verilog, memory is declared as arrays of data, typically using the ‘reg‘ keyword for
simulation purposes. This section covers the declaration syntax and types of memory you
can model.

11.1.1 Declaring 1-Dimensional Memory Arrays


To declare a simple array of registers (used to model memory):

reg [7:0] mem_array [0:255]; // 256 memory locations, each 8 bits wide

Explanation:

• reg [7:0] specifies each word is 8 bits.

• [0:255] specifies the number of memory locations.

11.1.2 2-Dimensional Memory Declaration


reg [15:0] matrix [0:63]; // 64 locations of 16-bit words

These types are used for LUTs, register files, or basic RAM/ROM simulation.

161
Chapter 11 Memory Modeling in Verilog

11.1.3 Constant Memory (ROM)


For modeling ROM:

reg [7:0] rom [0:15];

initial begin
rom[0] = 8’hAA;
rom[1] = 8’hBB;
rom[2] = 8’hCC;
// ... initialize all
end

Use case: Instruction memory in CPU design.

11.1.4 Random Access Memory (RAM)


RAMs require both read and write operations:

reg [7:0] ram [0:255];

always @(posedge clk) begin


if (wr_en)
ram[addr] <= data_in;
else
data_out <= ram[addr];
end

11.1.5 Memory Initialization with Files


Verilog supports memory pre-loading using external files:

initial $readmemh("data.hex", ram); // Hex initialization


initial $readmemb("data.bin", ram); // Binary initialization

Useful when working with larger programs or instructions.


162
Chapter 11 Memory Modeling in Verilog

11.1.6 Synthesizable vs. Non-Synthesizable Memory

Feature Synthesizable Memory Non-Synthesizable Memory


Declaration Style Procedural with proper sensitiv- Often with initial blocks or
ity system tasks
Behavior Implements hardware on FP- Used for simulation only
GA/ASIC
Initialization Usually inferred from block Via $readmemh, loops, or
RAM IP or inferred by tools initial
Usage Inside always blocks with clock For testbenches and simulations
control
Examples RAM, ROM using ‘always @‘ File preload, dynamic address-
and ‘case‘ ing in simulation

11.1.7 Flowchart: Declaring and Using Memory in Verilog


(Illustrative flowchart to be added for visual understanding: Declaration → Initialization
→ Read/Write → Optional File Loading)

11.2 Read and Write Operations


Efficient memory access is critical in digital designs. Verilog allows both synchronous
and asynchronous memory read and write operations. This section explains different ap-
proaches with examples.

11.2.1 Synchronous Write with Asynchronous Read


This is a common approach for RAM design.

module sync_write_async_read (
input wire clk,
input wire [7:0] data_in,

163
Chapter 11 Memory Modeling in Verilog

input wire [7:0] addr,


input wire wr_en,
output wire [7:0] data_out
);
reg [7:0] memory [0:255];

always @(posedge clk) begin


if (wr_en)
memory[addr] <= data_in;
end

assign data_out = memory[addr]; // Asynchronous read


endmodule

Key points:
• Write happens on the positive clock edge.

• Read is instantaneous, without waiting for a clock.


11.2.2 Synchronous Read and Write


Used when both read and write must be aligned to the clock (e.g., dual-port memory or
register files).

module sync_read_write (
input wire clk,
input wire wr_en,
input wire [7:0] addr,
input wire [7:0] data_in,
output reg [7:0] data_out
);
reg [7:0] memory [0:255];

always @(posedge clk) begin


if (wr_en)
memory[addr] <= data_in;
else

164
Chapter 11 Memory Modeling in Verilog

data_out <= memory[addr];


end
endmodule

Note: Read and write are controlled through a clock cycle and are mutually exclusive.

11.2.3 Dual-Port Memory Access


Dual-port memories allow concurrent access — one port for read and another for write.

module dual_port_mem (
input wire clk,
input wire wr_en,
input wire [7:0] wr_addr,
input wire [7:0] data_in,
input wire [7:0] rd_addr,
output reg [7:0] data_out
);
reg [7:0] memory [0:255];

always @(posedge clk) begin


if (wr_en)
memory[wr_addr] <= data_in;
data_out <= memory[rd_addr];
end
endmodule

Advantage: Improves performance when simultaneous read and write are required.

11.2.4 Memory Read/Write Using Case Statements


For larger memory models or ROMs, use ‘case‘ for controlled access.

always @(posedge clk) begin


case (addr)
8’h00: data_out <= memory[0];
8’h01: data_out <= memory[1];

165
Chapter 11 Memory Modeling in Verilog

8’h02: data_out <= memory[2];


default: data_out <= 8’h00;
endcase
end

Pros:

• Extremely scalable

• Clean separation of data and logic

11.2.5 Dynamic Comparison Table: ROM Modeling Techniques


Method Advantages Limitations
Case Statement Easy to read, suitable Not scalable, manual
for <16 entries
Array Initialization Neat syntax, scalable to Still hardcoded in code
moderate ROM size
$readmemh/$readmemb Scalable to very large File dependency, needs
ROM, external data file file management

11.3 Register File Design


A Register File is a small and fast memory unit comprising multiple registers. It allows
simultaneous reading from multiple locations and optional writing to a specific location.
Register files are often used in CPUs, microcontrollers, and DSPs to store operands, re-
sults, and intermediate values.

11.3.1 Key Features of a Register File


• Supports multiple read and write ports

• Typically synchronous write and asynchronous/synchronous read

• Provides random access to registers

166
Chapter 11 Memory Modeling in Verilog

Explanation:

• 4 registers, each 8-bit wide

• 2-bit address lines used to select one of the 4 registers

• One write enable signal (we) to control writing

11.3.2 Verilog Code for 2R1W Register File (4 Registers, 8-bit Wide)
module register_file (
input clk,
input we,
input [1:0] w_addr, r_addr1, r_addr2,
input [7:0] w_data,
output [7:0] r_data1,
output [7:0] r_data2
);

reg [7:0] reg_array [3:0]; // 4 registers of 8 bits

// Write Operation
always @(posedge clk) begin
if (we) begin
reg_array[w_addr] <= w_data;
end
end

// Read Operation (asynchronous)


assign r_data1 = reg_array[r_addr1];
assign r_data2 = reg_array[r_addr2];

endmodule

167
Chapter 11 Memory Modeling in Verilog

11.3.3 Verilog Code for 1R1W Register File with Synchronous Read
module reg_file_sync_read (
input clk,
input we,
input [1:0] w_addr, r_addr,
input [7:0] w_data,
output reg [7:0] r_data
);

reg [7:0] reg_file [3:0];

always @(posedge clk) begin


if (we)
reg_file[w_addr] <= w_data;

r_data <= reg_file[r_addr];


end
endmodule

11.3.4 Comparison Table: Asynchronous vs Synchronous Read

Feature Asynchronous Read Synchronous Read


Timing Immediate data access Data read after clock edge
Speed Faster access Slightly slower
Use-case Control-heavy logic, test- Pipeline stages, synthesis-
benches friendly
Simulation Debugging Easier to debug Timing alignment required

11.3.5 Key Design Tips


• Always reset register file contents when needed using initial or explicit reset
logic.

168
Chapter 11 Memory Modeling in Verilog

• Avoid reading and writing the same location in the same clock cycle.

• For multi-port register files, prioritize arbitration logic to prevent data hazards.

11.4 Testbench for 2R1W Register File


This testbench writes values to specific registers and reads them using two read ports. It
helps verify the correctness of the register file’s behavior.

‘timescale 1ns/1ps

module tb_register_file;

// Inputs
reg clk;
reg we;
reg [1:0] w_addr;
reg [1:0] r_addr1, r_addr2;
reg [7:0] w_data;

// Outputs
wire [7:0] r_data1;
wire [7:0] r_data2;

// Instantiate the register file


register_file uut (
.clk(clk),
.we(we),
.w_addr(w_addr),
.r_addr1(r_addr1),
.r_addr2(r_addr2),
.w_data(w_data),
.r_data1(r_data1),
.r_data2(r_data2)
);

// Clock generation
initial clk = 0;

169
Chapter 11 Memory Modeling in Verilog

always #5 clk = ~clk;

initial begin
// Initialize inputs
we = 0; w_addr = 0; w_data = 8’h00;
r_addr1 = 0; r_addr2 = 1;

// Wait for global reset


#10;

// Write 8’hAA to register 0


we = 1;
w_addr = 2’b00;
w_data = 8’hAA;
#10;

// Write 8’h55 to register 1


w_addr = 2’b01;
w_data = 8’h55;
#10;

// Write 8’hF0 to register 2


w_addr = 2’b10;
w_data = 8’hF0;
#10;

// Disable write
we = 0;

// Read from register 0 and 1


r_addr1 = 2’b00;
r_addr2 = 2’b01;
#10;

// Read from register 2 and 3 (unwritten)


r_addr1 = 2’b10;
r_addr2 = 2’b11;
#10;

170
Chapter 11 Memory Modeling in Verilog

$display("Test Completed.");
$stop;
end

endmodule

11.5 Summary and Pro Tips


Summary
• A Register File is a collection of registers accessible for read and write operations.
It is commonly used in CPU architectures.

• The 2R1W Register File supports two simultaneous read operations and one write
operation per clock cycle.

• It is implemented using an array of registers and accessed using read and write
addresses.

• The write operation is synchronous with the clock and controlled by a write enable
signal.

• Read operations are asynchronous in basic models, but can also be made synchronous
depending on the design requirement.

• Proper testbenches are crucial to validate correct functionality — multiple values


and all register addresses should be tested.

Pro Tips
• Always initialize register file contents if required for simulation consistency.

• When using synchronous read, ensure proper handling of setup and hold timing for
inputs.

• Use meaningful parameter names and labels for register widths and counts — it
enhances code reusability.

• Avoid using blocking assignments in sequential blocks when designing register files.

171
Chapter 11 Memory Modeling in Verilog

• Remember that simultaneous write and read to the same address in the same cycle
may require special handling (read-after-write hazard).

• Include ‘display‘or‘monitor‘ in testbenches to trace register values at each simula-


tion step.

• For synthesizable RTL, avoid initializing memory inside the definition — use an
initial block for simulation only.

• Use one-hot encoding or binary encoding for state machines interfacing with register
files depending on power and area constraints.

172
Chapter 12: User Defined Primitive
(UDP)

Introduction
Introduction
Verilog allows the creation of custom logic through a powerful feature called User Defined
Primitives (UDP). These are low-level representations of logic behavior, typically used to
model gates or flip-flops.

Analogy
Think of a UDP as a handmade switchboard – just like you wire logic manually,
you define how outputs respond to specific inputs via a custom truth table.

Learning Objectives
• Understand the concept of UDPs in Verilog.

• Differentiate between combinational and sequential UDPs.

• Learn to write UDPs using truth tables.

• Apply UDPs in practical examples.

12.1 Theory and Syntax


User Defined Primitives can be of two types:

173
Chapter 12 User Defined Primitive (UDP)

• Combinational UDP: No memory, output is purely based on current inputs.

• Sequential UDP: Has memory element, output depends on both current input and
previous state.

Syntax

Combinational UDP Syntax


primitive primitive_name(output, input1, input2);
output output;
input input1, input2;

table
// input1 input2 : output;
0 0 : 0;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive

Comparison: UDP vs Module

Feature UDP Module


Purpose Low-level behavior modeling General HDL description
Structure Truth-table based RTL/Behavioral/Structural
Memory Support Only sequential UDPs Full support
Synthesizable Yes (limited) Yes
Parameterization Not supported Fully supported

Example: Combinational UDP


primitive AND_UDP(out, a, b);
output out;
input a, b;

174
Chapter 12 User Defined Primitive (UDP)

table
// a b : out
0 0 : 0;
0 1 : 0;
1 0 : 0;
1 1 : 1;
endtable
endprimitive

Example: Sequential UDP (D Flip-Flop)


primitive DFF_UDP(q, clk, d);
output q;
reg q;
input clk, d;

table
// clk d : q : q_next
r 0 : ? : 0;
r 1 : ? : 1;
f ? : ? : -;
endtable
endprimitive

Practice Examples
1. XNOR Gate Using UDP

primitive XNOR_UDP(out, a, b);


output out;
input a, b;

table
0 0 : 1;
0 1 : 0;
1 0 : 0;
1 1 : 1;

175
Chapter 12 User Defined Primitive (UDP)

endtable
endprimitive

2. OR Gate Using UDP


primitive OR_UDP(out, a, b);
output out;
input a, b;

table
0 0 : 0;
0 1 : 1;
1 0 : 1;
1 1 : 1;
endtable
endprimitive

3. Latch Using Sequential UDP


primitive LATCH(q, d, en);
output q;
reg q;
input d, en;

table
// en d : q : q_next
1 0 : ? : 0;
1 1 : ? : 1;
0 ? : q : -;
endtable
endprimitive

12.2 Practice and Interview Questions


Conceptual
• What is the difference between a combinational and sequential UDP?

176
Chapter 12 User Defined Primitive (UDP)

• Why is UDP not suitable for complex logic design?

• When would you prefer a UDP over a Verilog module?

• What are the limitations of UDPs in synthesis?

Practical/Verilog-Based
1. Create a UDP for a 3-input majority function.

2. Write a UDP for a D latch with an enable signal.

3. Implement a NOR gate using UDP.

4. Modify an existing UDP to include an unknown state.

5. Simulate a UDP in a testbench and check its waveform.

Pro Tips
Pro Tips
• Use UDPs for modeling gate-level primitives only.

• Always simulate UDPs before synthesis – they may not be synthesizable on


all tools.

• Avoid using UDPs for large or combinatorially deep logic.

• Prefer using behavioral constructs (‘always‘, ‘assign‘) for readability unless


the compactness of a UDP is required.

• You can use ‘¿ (don’t care) in UDP tables to simplify conditions.

Summary
• UDPs allow custom logic behavior via truth tables.

• They come in two types: combinational (no memory) and sequential (with memory).

• Syntax involves ‘primitive‘, ‘table‘, and optionally ‘reg‘ for sequential behavior.

177
Chapter 12 User Defined Primitive (UDP)

• Ideal for modeling simple gates, flip-flops, or latches at a low level.

• Limited in synthesizability, parameterization, and should be used carefully.

178
Chapter 13: Event Scheduler

Introduction
In Verilog, the **event scheduler** is the internal mechanism that determines the exe-
cution order of events within a simulation time step. Since multiple statements can be
scheduled for the same time, understanding how Verilog handles their execution is crucial
for accurate modeling and debugging.
It divides simulation time into four main regions for handling scheduled events:

• Active Region

• Inactive Region

• NBA (Non-blocking Assign) Region

• Monitor/Reactive Region

Each region has its own specific role in maintaining simulation integrity and race-free
behavior.

Learning Objectives
• Understand the internal working of the Verilog simulator’s event scheduler.

• Differentiate between active, inactive, NBA, and monitor regions.

• Analyze how race conditions are avoided using proper scheduling.

• Visualize the flow using a clear flowchart representation.

179
Chapter 13 Event Scheduler

13.1 Detailed Theory with Flowchart


The Verilog event scheduler processes all events scheduled for the same simulation time in
an ordered sequence of regions. Here’s how the scheduler works during every simulation
time step:

1. Active Region: Executes blocking assignments, continuous assignments, ‘display‘, ‘monitor‘,


‘f inish‘, ‘stop‘, and evaluation of RHS expressions.

2. Inactive Region: Events postponed from the active region (usually from zero-delay
assignments).

3. NBA Region: Executes non-blocking assignments (i.e., all ‘<= assignments).

4. Monitor Region: Executes monitoring tasks (‘monitor‘, ‘strobe‘) after all values are
updated.

Flowchart: Event Scheduler in Verilog

Start Time Step

Active Region
(Blocking, Eval RHS)

Inactive Region
(Zero-delay Scheduled)

NBA Region
(Non-blocking Assignments)

Monitor Region
($monitor, $strobe)

End of Time Step

This flow ensures a clean and deterministic simulation order, minimizing unintended
interactions and race conditions.

180
Chapter 13 Event Scheduler

13.2 Example: Event Scheduling


module eventdemo; reg a, b;
initial begin a = 0; b = 0; end
always @(a) begin b = a + 1; // Blocking: active region end
always @(b) begin #0 a <= b; // Non-blocking: NBA region (due to <=) end endmod-
ule

Simulation Walkthrough
• Time 0: a and b set to 0 in the initial block.

• Changing a triggers first always block.

• b = a + 1 happens immediately (active region).

• b changes, second always is triggered.

• a <= b is queued in NBA region.

• After active/inactive regions complete, NBA executes a <= b.

13.3 Additional Examples, Summary, and Pro Tips


13.3 Additional Examples, Summary, and Pro Tips
Example 1: Zero Delay Race Condition
module race_condition;
reg a, b;

initial begin
a = 0;
b = 0;
end

always @(a)
b = a;

181
Chapter 13 Event Scheduler

always @(a)
a = 1;

endmodule

Explanation: Both always blocks are sensitive to changes in a. Since there is no


delay, the execution order is not deterministic, leading to a race condition.

Example 2: Using #0 to Prioritize Execution

module zero_delay_fix;
reg clk, a, b;

always @(posedge clk) begin


a = 1;
#0 b = a; // Ensures ’a’ is updated before ’b’ reads it
end
endmodule

Explanation: The #0 introduces an inactive delay, pushing the second assignment to


a later phase to avoid race conditions.

Example 3: Delays and Event Ordering

module delay_order;
reg x, y;

initial begin
x = 0;
y = 0;
#5 x = 1;
y = 1;
end
endmodule

Explanation: The assignment x = 1 is scheduled at simulation time 5 while y = 1


executes immediately at time 0.

182
Chapter 13 Event Scheduler

Summary

Concept Description
Event Scheduler Controls execution timing and order of Verilog code
Regions of Execution Active, Inactive, Non-blocking active (NBA), NBA inactive
Blocking Assignment (=) Immediate execution; may cause race conditions
Non-Blocking Assign- Executes later in NBA region; safer for sequential logic
ment (<=)
#0 Delay Schedules assignment for Inactive region; resolves race is-
sues
Event Control Triggers execution on signal events using @, posedge,
negedge
Delta Cycle Zero time step used for simulation ordering at same time
instant

Pro Tips
• Use <= for sequential logic inside clocked always blocks to avoid race conditions.

• Avoid simultaneous read/write of the same signal in multiple always blocks.

• Delta delays help ensure all operations at the same time are handled sequentially
without time progression.

• Use #0 to separate assignments when debugging timing or ordering issues.

• Explain the event scheduler using real-life analogies like a traffic signal (Red = Wait,
Green = Execute, Yellow = Prepare).

• Use simulation waveforms and flowcharts to analyze and debug timing behavior.

183
Chapter 14: Efficient Testbench Writing

Introduction
A testbench in Verilog is a simulation environment created to verify the functionality of
a design module. Writing efficient and reusable testbenches is critical in verifying digital
designs before synthesis or tape-out. A poorly written testbench can lead to misleading
simulation results, bugs in design, or even failure at the silicon level.
This chapter aims to provide a structured approach to writing efficient and professional
testbenches using good practices, reusable components, and real-world scenarios.

Learning Objectives
• Understand the purpose and structure of a Verilog testbench.

• Learn how to use initial blocks, procedural constructs, and tasks/functions for veri-
fication.

• Grasp techniques for modular, reusable, and maintainable testbench design.

• Develop debugging skills through simulation waveform observation.

• Create testbenches for various digital systems with increasing complexity.

184
Chapter 14 Efficient Testbench Writing

14.1 Testbench Examples with Theory


Example 1: Testbench for 2:1 Multiplexer
Design Under Test (DUT):
1 module mux2to1(input a, input b, input sel, output y);
2 assign y = sel ? b : a;
3 endmodule

Testbench:
1 module tb_mux2to1;
2 reg a, b, sel;
3 wire y;
4
5 mux2to1 uut (.a(a), .b(b), .sel(sel), .y(y));
6
7 initial begin
8 a = 0; b = 0; sel = 0;
9 #10 a = 1;
10 #10 sel = 1;
11 #10 b = 1;
12 #10 sel = 0;
13 end
14 endmodule

Explanation: This testbench initializes inputs and applies different test cases using
time delays to test how the multiplexer behaves with different combinations of inputs.

Example 2: Testbench for D Flip-Flop


DUT:
1 module dff(input clk, input d, output reg q);
2 always @(posedge clk)
3 q <= d;
4 endmodule

Testbench:
1 module tb_dff;
2 reg clk, d;
3 wire q;
4

5 dff uut (.clk(clk), .d(d), .q(q));

185
Chapter 14 Efficient Testbench Writing

6
7 always #5 clk = ~clk; // Clock generator
8

9 initial begin
10 clk = 0; d = 0;
11 #10 d = 1;
12 #10 d = 0;
13 #10 d = 1;
14 #20;
15 end
16 endmodule

Explanation: The ‘always‘ block toggles the clock every 5 time units. The ‘initial‘
block changes the ‘d‘ value at specific times to simulate input behavior.

Example 3: Testbench for 4-bit Adder


DUT:
1 module adder4bit(input [3:0] a, b, output [4:0] sum);
2 assign sum = a + b;
3 endmodule

Testbench:
1 module tb_adder4bit;
2 reg [3:0] a, b;
3 wire [4:0] sum;
4
5 adder4bit uut (.a(a), .b(b), .sum(sum));
6
7 initial begin
8 a = 4’b0000; b = 4’b0000;
9 #10 a = 4’b0101; b = 4’b0011;
10 #10 a = 4’b1111; b = 4’b1111;
11 #10 a = 4’b1010; b = 4’b0101;
12 end
13 endmodule

Explanation: This testbench applies different sets of 4-bit values to check overflow
and proper addition functionality.

Example 4: Testbench for 8-bit Up Counter with Reset


DUT:

186
Chapter 14 Efficient Testbench Writing

1 module counter(input clk, reset, output reg [7:0] out);


2 always @(posedge clk or posedge reset)
3 if (reset)
4 out <= 0;
5 else
6 out <= out + 1;
7 endmodule

Testbench:
1 module tb_counter;
2 reg clk, reset;
3 wire [7:0] out;
4
5 counter uut (.clk(clk), .reset(reset), .out(out));
6
7 always #5 clk = ~clk;
8
9 initial begin
10 clk = 0; reset = 1;
11 #10 reset = 0;
12 #50 reset = 1;
13 #10 reset = 0;
14 #30;
15 end
16 endmodule

Explanation: Clock toggling and reset control demonstrate synchronous behavior and
reset mechanism of the counter.

Example 5: Testbench for AND Gate with Task-based Testcase


DUT:
1 module and_gate(input a, b, output y);
2 assign y = a & b;
3 endmodule

Testbench:
1 module tb_and_gate;
2 reg a, b;
3 wire y;
4
5 and_gate uut (.a(a), .b(b), .y(y));
6

187
Chapter 14 Efficient Testbench Writing

7 task apply_inputs;
8 input aa, bb;
9 begin
10 a = aa; b = bb;
11 #5;
12 end
13 endtask
14
15 initial begin
16 apply_inputs(0, 0);
17 apply_inputs(0, 1);
18 apply_inputs(1, 0);
19 apply_inputs(1, 1);
20 end
21 endmodule

Explanation: This example uses a custom task to apply inputs. This method enhances
code readability and modularity.

Testbench Example 6: Detecting a Sequence using FSM (Moore Ma-


chine)
Objective: Detect the sequence “1011” using a Moore state machine and write an efficient
testbench.

// FSM Module (Moore)


module seq_detector (
input clk,
input reset,
input in_bit,
output reg detected
);
typedef enum reg [2:0] {S0, S1, S2, S3, S4} state_t;
state_t state;

always @(posedge clk or posedge reset) begin


if (reset)
state <= S0;
else begin
case(state)

188
Chapter 14 Efficient Testbench Writing

S0: state <= (in_bit == 1) ? S1 : S0;


S1: state <= (in_bit == 0) ? S2 : S1;
S2: state <= (in_bit == 1) ? S3 : S0;
S3: state <= (in_bit == 1) ? S4 : S1;
S4: state <= S0;
endcase
end
end

always @(state) begin


detected = (state == S4);
end
endmodule

// Testbench
module tb_seq_detector;
reg clk, reset, in_bit;
wire detected;

seq_detector dut (.clk(clk), .reset(reset), .in_bit(in_bit), .detected(d

initial begin
clk = 0; forever #5 clk = ~clk;
end

initial begin
reset = 1; in_bit = 0;
#10 reset = 0;
#10 in_bit = 1; #10 in_bit = 0; #10 in_bit = 1; #10 in_bit = 1;
#20 $finish;
end

initial begin
$monitor("Time=%0t in_bit=%b detected=%b", $time, in_bit, detected);
end
endmodule
Explanation: This testbench drives the FSM with input sequence to check if it cor-
rectly detects “1011”. The use of ‘$monitor‘ is efficient for observing signal values over

189
Chapter 14 Efficient Testbench Writing

time.

Testbench Example 7: Edge Detection


Objective: Create a module to detect rising edge and verify with a testbench.

// Edge Detector Module


module edge_detector(
input clk,
input sig,
output reg edge
);
reg sig_d;

always @(posedge clk) begin


sig_d <= sig;
edge <= sig & ~sig_d;
end
endmodule

// Testbench
module tb_edge_detector;
reg clk, sig;
wire edge;

edge_detector dut (.clk(clk), .sig(sig), .edge(edge));

initial begin
clk = 0; forever #5 clk = ~clk;
end

initial begin
sig = 0;
#12 sig = 1; #10 sig = 0; #10 sig = 1; #20;
$stop;
end

initial begin

190
Chapter 14 Efficient Testbench Writing

$monitor("Time=%0t sig=%b edge=%b", $time, sig, edge);


end
endmodule

Example 13: Testbench for 2-to-1 Multiplexer


Theory: A 2-to-1 MUX selects one of two inputs based on a select line.

module mux2x1(input a, b, sel, output y);


assign y = sel ? b : a;
endmodule

module tb_mux2x1();
reg a, b, sel;
wire y;

mux2x1 uut(.a(a), .b(b), .sel(sel), .y(y));

initial begin
a = 0; b = 1;
sel = 0; #10;
sel = 1; #10;
$finish;
end
endmodule

Example 14: Testbench for 4-bit Adder


Theory: This testbench verifies a 4-bit adder module.

module adder_4bit(input [3:0] a, b, output [4:0] sum);


assign sum = a + b;
endmodule

module tb_adder_4bit();
reg [3:0] a, b;
wire [4:0] sum;

adder_4bit uut (.a(a), .b(b), .sum(sum));

191
Chapter 14 Efficient Testbench Writing

initial begin
a = 4’d9; b = 4’d5; #10;
a = 4’d10; b = 4’d15; #10;
a = 4’d7; b = 4’d2; #10;
$finish;
end
endmodule

14.2 Practice and Interview Questions


These questions are designed to test your understanding of efficient testbench devel-
opment and debugging in Verilog.

Conceptual and Design Questions


1. What is the purpose of a testbench in Verilog?

2. How does a testbench differ from the design under test (DUT)?

3. What are the different phases of a testbench execution?

4. What is the role of initial and always blocks in a testbench?

5. How do you generate a clock signal in a testbench?

6. What are self-checking testbenches?

7. What is the use of $monitor‘, $display‘, and $strobe‘?

8. What is the advantage of using tasks and functions inside a testbench?

9. What is the importance of ‘timescale‘ in simulation?

10. How can you simulate asynchronous resets in a testbench?

192
Chapter 14 Efficient Testbench Writing

Verilog-Based Coding Practice

11. Write a testbench to simulate a 2-to-1 multiplexer.

12. Design a testbench to verify a 4-bit binary up-counter.

13. Write a testbench that checks both synchronous and asynchronous reset behavior.

14. Create a testbench for a D flip-flop and monitor metastability.

15. Simulate a full adder using various test vectors in a loop.

16. Generate a clock and reset signal in a structured testbench.

17. Use ‘for‘ loop and arrays to automate test cases in a testbench.

18. Simulate edge-triggered behavior using ‘@(posedge clk)‘ constructs.

19. Write a testbench for a finite state machine (FSM) that detects ‘1011‘.

20. Use ‘repeat‘ and ‘while‘ loops to simulate a counter.

Debugging and Optimization Scenarios

21. Your testbench runs but shows ‘X‘ outputs. What could be wrong?

22. Explain how ‘dumpf ile‘and‘dumpvars‘ help in debugging.

23. How would you log all testbench events with timestamps?

24. Your simulation output is stuck. What would be your approach to debug it?

25. Describe the difference between blocking and non-blocking in testbenches.

26. How can a race condition arise in a poorly written testbench?

27. What is the use of delay modeling in testbenches?

28. Explain how you would simulate a handshaking protocol.

29. Write a checklist to validate a testbench for a UART module.

30. Create a testbench for a memory block that tests read and write functionality.

193
Chapter 14 Efficient Testbench Writing

14.3 Pro Tips for Efficient Testbench Writing

Pro Tips for Better Testbenches


• Start Small: Always test small pieces of your design before building large
testbenches.

• Use ‘timescale‘: Define timing precision and unit clearly to avoid simulation
mismatch.

• Clock Generation: Use ‘always #5 clk = c̃lk;‘ to produce reliable square-


wave clocks.

• Automation: Automate test vectors using ‘for‘, ‘repeat‘, and ‘case‘ state-
ments to reduce manual errors.

• Self-Checking: Always include assertions or comparisons in your testbench


to validate results automatically.

• Waveform Dumping: Use ‘dumpf ile(”wave.vcd”)‘and‘dumpvars‘ to visu-


alize signals in GTKWave or ModelSim.

• Task and Function Reuse: Create reusable test routines with ‘task‘ and
‘function‘ blocks to avoid redundancy.

• Stimulus Timing: Ensure proper delay between stimulus events to allow the
DUT to process inputs.

• Coverage Plan: Think about all edge cases while preparing stimulus (reset,
boundary inputs, illegal states).

• Initial and Always Balance: Use ‘initial‘ for one-time stimulus and ‘always‘
for continuous signal generation.

194
Chapter 14 Efficient Testbench Writing

14.4 Summary
Chapter Summary
• Testbenches are essential for validating digital designs before hardware im-
plementation.

• A testbench should ideally include input generators, clock logic, reset logic,
and output monitors.

• Key constructs include ‘initial‘, ‘always‘, ‘$display‘, ‘$monitor‘, ‘$dump-


vars‘, ‘tasks‘, and ‘functions‘.

• Efficient testbenches are modular, self-checking, reusable, and well-


documented.

• Simulation tools and waveform viewers like GTKWave are crucial for debug-
ging.

• Practice with real-world testbenches enhances design robustness and verifica-


tion speed.

195
Chapter 15: 200 Verilog Interview
Questions (Without Answers)

Introduction
This chapter includes a carefully curated list of 200 Verilog interview questions divided
into multiple categories such as basics, modeling techniques, synthesis, simulation, test-
bench development, FSMs, and real-world debugging scenarios. These are designed to
test both theoretical understanding and practical coding ability.

15.1 Questions 1–40: Verilog Basics and Syntax


1. What is the difference between Verilog and VHDL?

2. Explain the purpose of the ‘module‘ keyword in Verilog.

3. What are ‘wire‘ and ‘reg‘ in Verilog?

4. Describe the difference between ‘initial‘ and ‘always‘ blocks.

5. What are blocking and non-blocking assignments in Verilog?

6. Why is non-blocking assignment preferred in sequential circuits?

7. How do you define a 4-bit register in Verilog?

8. What is the default value of a register in Verilog?

9. What is the use of ‘parameter‘ in Verilog?

10. Explain the use of ‘generate‘ blocks in Verilog.

196
Chapter 15 200 Verilog Interview Questions

11. What is the difference between ‘case‘, ‘casex‘, and ‘casez‘?

12. What is the role of ‘display‘, ‘monitor‘, and $finish‘?

13. How do you implement a 4:1 multiplexer using Verilog?

14. What are system tasks in Verilog?

15. Define and differentiate between combinational and sequential logic in Verilog.

16. What are continuous assignments?

17. When would you use ‘assign‘ statements?

18. How can you model tristate logic in Verilog?

19. What are ‘initial‘ and ‘always‘ blocks used for in simulations?

20. Can you declare variables inside ‘always‘ blocks?

21. Explain the difference between ‘posedge‘ and ‘negedge‘.

22. How do you declare and use arrays in Verilog?

23. What are compiler directives in Verilog?

24. What does ‘timescale‘ do?

25. What is ‘blocking delay‘ and ‘non-blocking delay‘?

26. Describe how to write a D Flip-Flop using Verilog.

27. Explain the concept of implicit and explicit nets.

28. How does a ‘for‘ loop differ from a ‘repeat‘ loop in Verilog?

29. What is ‘inferred latch‘ in Verilog and when does it occur?

30. How do you initialize memories in Verilog?

31. What are race conditions in Verilog?

32. How do you define multiple modules in a single file?

33. How do you handle asynchronous reset in Verilog?

197
Chapter 15 200 Verilog Interview Questions

34. What are simulation commands available in Verilog?

35. Can a ‘wire‘ be used as output in a module?

36. What is a port list and how is it defined?

37. Explain what is meant by ‘implicit continuous assignment‘.

38. How do you instantiate a module in another module?

39. Describe what a ‘sensitivity list‘ is and when it should be used.

40. What is the difference between simulation and synthesis?

15.2 Questions 41–202: Modeling, Operators, and Control


Structures
41. What are the types of modeling styles in Verilog?

42. Compare dataflow and behavioral modeling.

43. Explain the concept of hierarchical modeling in Verilog.

44. What are the different types of delays in Verilog?

45. How is a ‘gate delay‘ modeled in Verilog?

46. What are the types of operators supported by Verilog?

47. Describe bitwise vs logical operators in Verilog.

48. What are reduction operators in Verilog? Provide examples.

49. What is the purpose of shift operators?

50. What are conditional operators in Verilog?

51. How does Verilog handle operator precedence?

52. What is the difference between ‘if-else‘ and ‘case‘ statements?

53. How do you avoid latch inference in conditional structures?

198
Chapter 15 200 Verilog Interview Questions

54. What are the pitfalls of incomplete ‘case‘ or ‘if‘ statements?

55. What is meant by parallel case vs full case in synthesis?

56. What is ‘disable‘ statement in Verilog?

57. Explain the use of ‘fork-join‘ in Verilog.

58. What is event control? List different types.

59. How is ‘wait‘ statement used in Verilog?

60. Explain how a ‘forever‘ loop differs from a ‘while‘ loop.

61. What is a ‘named block‘ in Verilog?

62. Explain the difference between a blocking assignment in a ‘begin-end‘ block vs


‘fork-join‘.

63. Describe how you implement priority encoding in Verilog.

64. What are generate-if and generate-for constructs?

65. How do ‘defparam‘ and ‘parameter‘ differ?

66. What happens if the ‘sensitivity list‘ is incomplete?

67. What is a ‘disable fork‘ statement used for?

68. How do you model a counter in Verilog?

69. How do you create a priority encoder in Verilog?

70. What are the design issues with deeply nested ‘if‘ statements?

71. Describe how to use functions inside Verilog modules.

72. What is the role of ‘random‘, ‘urandom‘, and $dist_uniform‘?

73. Describe the purpose and syntax of ‘always_comb‘, ‘always_ff‘, and ‘always_latch‘
in SystemVerilog.

74. What happens if multiple assignments are made to the same wire?

75. What is ‘strength‘ and ‘drive‘ in gate-level modeling?

199
Chapter 15 200 Verilog Interview Questions

76. What is a ‘primitive‘ in Verilog?

77. How does Verilog resolve multiple drivers on a wire?

78. Explain the concept of 4-state logic in Verilog.

79. What is the use of ‘buf‘ and ‘not‘ primitives?

80. What are the differences between ‘assign‘ and ‘force‘?

81. What are concurrent statements in Verilog?

82. Differentiate between a blocking assignment and a continuous assignment.

83. What is a simulation delta cycle?

84. What is an ‘initial‘ block, and how is it different from ‘always‘?

85. Explain how delays can be modeled in Verilog.

86. What is a delay control and event control?

87. Can we write an ‘always‘ block inside a module more than once?

88. Why do we use ‘posedge‘ and ‘negedge‘?

89. What is the functionality of ‘display‘, $monitor‘, and‘finish‘?

90. How do you use ‘timescale‘ in Verilog?

91. What are race conditions in Verilog simulations?

92. How do you simulate a memory module in Verilog?

93. What is the difference between ‘force‘ and ‘assign‘?

94. How do you model tristate logic in Verilog?

95. What is the function of ‘casex‘ and ‘casez‘ in Verilog?

96. What are implicit nets in Verilog?

97. How do you prevent implicit nets in a Verilog design?

98. What is synthesis, and how does it relate to Verilog coding?

200
Chapter 15 200 Verilog Interview Questions

99. Explain why not all Verilog constructs are synthesizable.

100. What is RTL (Register Transfer Level)?

101. Explain the ‘generate‘ block in Verilog.

102. What are Verilog attributes and where are they used?

103. What is a ‘parameter‘ in Verilog, and how is it used?

104. What is a ‘localparam‘ and how is it different from ‘parameter‘?

105. Can a parameter value be changed during simulation?

106. What are hierarchical names in Verilog?

107. What is a sensitivity list and how does it work?

108. Explain how a flip-flop is modeled in Verilog.

109. How do you implement a finite state machine (FSM) in Verilog?

110. How can we avoid latches in Verilog?

111. What is the role of ‘default‘ in case statements?

112. How do you handle asynchronous reset in sequential circuits?

113. How do you write a 4-to-1 multiplexer in Verilog?

114. How can a testbench be written for a multiplexer?

115. What is the function of the $random‘ system task?

116. How do you use $readmemh‘ and $readmemb‘?

117. Can two ‘always‘ blocks write to the same signal?

118. What are overlapping and non-overlapping clocks?

119. How can setup and hold time violations be modeled?

120. Describe how you would debug a non-functional Verilog design.

121. What is meant by zero delay in Verilog?

201
Chapter 15 200 Verilog Interview Questions

122. How do you model combinational logic using ‘always‘ blocks?

123. How would you implement a priority encoder in Verilog?

124. What is the difference between a blocking and non-blocking assignment in terms of
simulation results?

125. Why is it a bad practice to mix blocking and non-blocking assignments?

126. Describe the types of loops available in Verilog.

127. What is the function of the $time‘ system task?

128. Explain the scope of variables and signals in Verilog.

129. What is a race condition and how can it be avoided?

130. How do you create parameterized modules in Verilog?

131. What is the purpose of testbenches?

132. Can you synthesize a testbench?

133. How can assertions be implemented in Verilog?

134. How do you ensure that your design is resettable?

135. What is a blocking assignment used for in testbenches?

136. What is synthesis tool behavior for ‘casex‘ and ‘casez‘?

137. What are some best practices in Verilog coding for synthesis?

138. How do you check whether your design meets timing constraints?

139. How do you model memory elements like RAM or ROM?

140. What is the difference between $display‘ and $strobe‘?

141. What is the Verilog ‘disable‘ statement used for?

142. Can you write recursive functions in Verilog?

143. What is the difference between ‘wire‘ and ‘reg‘ in Verilog?

202
Chapter 15 200 Verilog Interview Questions

144. Explain the purpose of $dumpvars‘ and $dumpfile‘.

145. How do you model a FIFO using Verilog?

146. What is a gray code counter and how would you implement it?

147. How would you detect a metastability issue in your simulation?

148. What is the role of ‘posedge clk‘ in a D flip-flop model?

149. Explain the use of named blocks in Verilog.

150. What are the different ways to describe hardware in Verilog?

151. What is a testbench delay and how does it affect simulation?

152. Describe how a ring counter works and its Verilog implementation.

153. Can a procedural block drive multiple signals at once?

154. How do you write a priority encoder using a case statement?

155. What’s the difference between RTL and Gate-Level modeling?

156. How would you write a self-checking testbench?

157. How do you log simulation results to a file in Verilog?

158. What is a ‘repeat‘ loop and where is it used?

159. What are asynchronous FIFO and how are they implemented?

160. How can you reduce simulation time in a large design?

161. What is the difference between ‘posedge‘ and ‘negedge‘ triggers?

162. What are the benefits of using ‘generate‘ blocks in Verilog?

163. Explain the role of ‘monitor‘andhowitdif f ersf rom‘display‘.

164. How can you ensure a testbench covers all corner cases?

165. What are synthesis directives and how are they used?

166. Describe the differences between Verilog-1995, Verilog-2001, and SystemVerilog.

203
Chapter 15 200 Verilog Interview Questions

167. What are the steps involved in verifying a Verilog design?

168. How does a ‘for‘ loop behave differently in simulation vs. synthesis?

169. What is the difference between ‘initial‘ and ‘always‘ blocks?

170. What precautions must be taken when using asynchronous resets?

171. What is a glitch, and how can it be avoided in Verilog?

172. What is a combinational feedback loop and why should it be avoided?

173. What are synthesis warnings, and how should you handle them?

174. What is a latch? How can you avoid unintentional latch inference?

175. How can you pass parameters into a module?

176. What is meant by “design under test” (DUT) in a testbench?

177. How do you verify a state machine’s transitions?

178. Can you simulate multiple clock domains in Verilog?

179. What is the effect of using blocking assignments in sequential logic?

180. What is the recommended method to initialize memory in Verilog?

181. What are commonly used verification methodologies for Verilog?

182. How would you implement a watchdog timer in Verilog?

183. What is the difference between hierarchical and flat design in Verilog?

184. How can you control simulation time granularity?

185. What are ‘tri‘ and ‘tri0/tri1‘ nets in Verilog?

186. How would you write a parameterized counter?

187. What is the purpose of ‘localparam‘ over ‘parameter‘?

188. What’s the difference between ‘defparam‘ and ‘parameter override‘?

189. How can you force or release a signal during simulation?

204
Chapter 15 200 Verilog Interview Questions

190. What are the different simulation phases in Verilog?

191. What does ‘f inish‘doandhowisitdif f erentf rom‘stop‘?

192. What is an FSM encoding style and how does it impact synthesis?

193. How would you create reusable modules for IP design in Verilog?

194. What’s the difference between inter-assignment and intra-assignment delay?

195. Can a single module have multiple ‘initial‘ blocks?

196. What are user-defined primitives (UDP) in Verilog?

197. How is a ‘posedge clk‘ different from ‘posedge‘ any signal?

198. How do you implement handshaking protocols in Verilog?

199. What is the role of event control statements in Verilog?

200. Describe how to design and verify a UART protocol in Verilog.

201. What is the difference between a synthesizable and non-synthesizable construct?

202. Describe a real-world project where you wrote Verilog code and verified it.

205
Chapter 16 : Problems with Solutions

Let’s Code to Conquer!


This chapter contains structured hands-on Verilog projects to reinforce
concepts and improve real-world design thinking.

Project Levels
Project Categories
• Beginner

• Intermediate

• Advanced

206
Chapter 16 Problems with Solutions

Beginner Projects (1–100)


Project 1: 2-Input AND Gate
Objective: Implement a 2-input AND gate using Verilog.

Verilog Code
module and_gate (input A, input B, output Y);
assign Y = A & B;
endmodule

Pro Tip
Pro Tip: Use ModelSim to simulate this with 4 test cases to verify all input combina-
tions.

Project 2: 2-to-1 Multiplexer


Objective: Write a simple 2:1 MUX using assign statement.

Verilog Code
module mux_2to1 (input A, input B, input Sel, output Y);
assign Y = Sel ? B : A;
endmodule

Pro Tip
Pro Tip: Replace the ternary operator with an if-else block in behavioral modeling for
learning.

Project 3: Half Adder


Objective: Create a Half Adder using gate-level modeling.

207
Chapter 16 Problems with Solutions

Verilog Code
module half_adder (input A, input B, output Sum, output Carry);
assign Sum = A ^ B;
assign Carry = A & B;
endmodule

Pro Tip
Pro Tip: Half Adders are used in ripple-carry adders – build one next!

208
Chapter 16 Problems with Solutions

Project 4: Full Adder

Objective: Implement a Full Adder using two Half Adders and an OR gate.

Verilog Code
module full_adder (
input A, B, Cin,
output Sum, Cout
);
wire Sum1, Carry1, Carry2;

half_adder HA1 (A, B, Sum1, Carry1);


half_adder HA2 (Sum1, Cin, Sum, Carry2);

assign Cout = Carry1 | Carry2;


endmodule

Pro Tip
Pro Tip: Use structural modeling to wire up submodules like in this example!

Project 5: 4-Bit Ripple Carry Adder

Objective: Design a 4-bit Ripple Carry Adder using four Full Adders.

209
Chapter 16 Problems with Solutions

Verilog Code
module ripple_adder_4bit (
input [3:0] A, B,
input Cin,
output [3:0] Sum,
output Cout
);
wire C1, C2, C3;

full_adder FA0 (A[0], B[0], Cin, Sum[0], C1);


full_adder FA1 (A[1], B[1], C1, Sum[1], C2);
full_adder FA2 (A[2], B[2], C2, Sum[2], C3);
full_adder FA3 (A[3], B[3], C3, Sum[3], Cout);
endmodule

Pro Tip
Pro Tip: Great first project to test on waveform viewers and learn carry propagation
delays.

Project 6: 4-Bit Comparator


Objective: Compare two 4-bit numbers and output greater, less, or equal.

Verilog Code
module comparator_4bit (
input [3:0] A, B,
output A_gt_B, A_eq_B, A_lt_B
);
assign A_gt_B = (A > B);
assign A_eq_B = (A == B);
assign A_lt_B = (A < B);
endmodule

210
Chapter 16 Problems with Solutions

Pro Tip
Pro Tip: Expand this into a 16-bit comparator with pipelining later.

Project 7: 3-to-8 Decoder

Objective: Build a decoder with enable input.

Verilog Code
module decoder_3to8 (
input [2:0] A,
input En,
output [7:0] Y
);
assign Y = En ? (1 << A) : 8’b0;
endmodule

Pro Tip
Pro Tip: Decoders are widely used in address decoding in SoC.

Project 8: 8-to-3 Encoder

Objective: Create a basic priority encoder.

211
Chapter 16 Problems with Solutions

Verilog Code
module encoder_8to3 (
input [7:0] D,
output reg [2:0] Y
);
always @(*) begin
casez(D)
8’b1???????: Y = 3’d7;
8’b01??????: Y = 3’d6;
8’b001?????: Y = 3’d5;
8’b0001????: Y = 3’d4;
8’b00001???: Y = 3’d3;
8’b000001??: Y = 3’d2;
8’b0000001?: Y = 3’d1;
8’b00000001: Y = 3’d0;
default: Y = 3’dx;
endcase
end
endmodule

Pro Tip
Pro Tip: Try replacing ‘casez‘ with ‘casex‘ and explore behavior.

Project 9: D Flip-Flop

Objective: Design a positive-edge triggered D flip-flop.

212
Chapter 16 Problems with Solutions

Verilog Code
module d_flip_flop (
input D, clk,
output reg Q
);
always @(posedge clk)
Q <= D;
endmodule

Pro Tip
Pro Tip: Always use non-blocking assignments inside sequential logic!

Project 10: T Flip-Flop using D Flip-Flop


Objective: Convert D flip-flop into T flip-flop using logic.

Verilog Code
module t_flip_flop (
input T, clk,
output reg Q
);
always @(posedge clk)
if (T)
Q <= ~Q;
else
Q <= Q;
endmodule

Pro Tip
Pro Tip: Used in counters – combine 3 of these to make a 3-bit counter.

Project 11: 4-to-1 Multiplexer


Objective: Implement a 4-to-1 multiplexer using ‘case‘ statement.

213
Chapter 16 Problems with Solutions

Verilog Code
module mux_4to1 (
input [3:0] D,
input [1:0] Sel,
output reg Y
);
always @(*) begin
case (Sel)
2’b00: Y = D[0];
2’b01: Y = D[1];
2’b10: Y = D[2];
2’b11: Y = D[3];
endcase
end
endmodule

Pro Tip
Pro Tip: Experiment with ‘assign‘ statement for structural style too.

Project 12: 1-to-4 Demultiplexer


Objective: Design a 1-to-4 demux controlled by select lines.

Verilog Code
module demux_1to4 (
input D,
input [1:0] Sel,
output reg [3:0] Y
);
always @(*) begin
Y = 4’b0000;
Y[Sel] = D;
end
endmodule

214
Chapter 16 Problems with Solutions

Pro Tip
Pro Tip: Test on waveform viewer — only one output line should be HIGH at a time.

Project 13: 4-bit Register with Enable

Objective: Store and hold 4-bit data on clock with enable.

Verilog Code
module register_4bit (
input clk, rst, en,
input [3:0] D,
output reg [3:0] Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 4’b0000;
else if (en)
Q <= D;
end
endmodule

Pro Tip
Pro Tip: Useful for pipeline registers in processor design.

Project 14: 4-bit Up Counter

Objective: Design a 4-bit synchronous up counter with reset.

215
Chapter 16 Problems with Solutions

Verilog Code
module counter_up_4bit (
input clk, rst,
output reg [3:0] count
);
always @(posedge clk or posedge rst) begin
if (rst)
count <= 4’d0;
else
count <= count + 1;
end
endmodule

Pro Tip
Pro Tip: Try adding enable and direction signals to upgrade it!

Project 15: 4-bit Down Counter


Objective: Reverse the direction of counting.

Verilog Code
module counter_down_4bit (
input clk, rst,
output reg [3:0] count
);
always @(posedge clk or posedge rst) begin
if (rst)
count <= 4’d15;
else
count <= count - 1;
end
endmodule

216
Chapter 16 Problems with Solutions

Pro Tip
Pro Tip: Set initial value from input instead of hardcoding.

Project 16: Bidirectional Counter

Objective: Create a 4-bit counter that can count up or down based on a control signal.

Verilog Code
module counter_bidirectional (
input clk, rst, dir,
output reg [3:0] count
);
always @(posedge clk or posedge rst) begin
if (rst)
count <= 0;
else
count <= dir ? count + 1 : count - 1;
end
endmodule

Pro Tip
Pro Tip: Add enable signal and explore debounce logic for switches.

Project 17: Gray Code Converter

Objective: Convert binary input to gray code.

217
Chapter 16 Problems with Solutions

Verilog Code
module binary_to_gray (
input [3:0] bin,
output [3:0] gray
);
assign gray[3] = bin[3];
assign gray[2] = bin[3] ^ bin[2];
assign gray[1] = bin[2] ^ bin[1];
assign gray[0] = bin[1] ^ bin[0];
endmodule

Pro Tip
Pro Tip: Gray code is useful in encoder applications to avoid glitches.

Project 18: Parity Generator


Objective: Generate even and odd parity bits for 4-bit data.

Verilog Code
module parity_generator (
input [3:0] D,
output even_parity, odd_parity
);
assign even_parity = ~^D;
assign odd_parity = ^D;
endmodule

Pro Tip
Pro Tip: Use ˆ for XOR reduction and ˜ˆ for XNOR reduction.

Project 19: Sequence Detector (1011)


Objective: Detect the pattern ‘1011‘ in a bit stream.

218
Chapter 16 Problems with Solutions

Verilog Code
module seq_detect_1011 (
input clk, rst, X,
output reg Z
);
reg [2:0] state;

parameter S0=0, S1=1, S2=2, S3=3;

always @(posedge clk or posedge rst) begin


if (rst) begin
state <= S0; Z <= 0;
end else begin
case(state)
S0: state <= (X==1) ? S1 : S0;
S1: state <= (X==0) ? S2 : S1;
S2: state <= (X==1) ? S3 : S0;
S3: begin
Z <= (X==1) ? 1 : 0;
state <= (X==1) ? S1 : S2;
end
endcase
end
end
endmodule

Pro Tip
Pro Tip: Try Moore version for a better understanding of FSMs.

Project 20: Majority Voter (3 Inputs)

Objective: Output 1 when two or more inputs are HIGH.

219
Chapter 16 Problems with Solutions

Verilog Code
module majority_voter (
input A, B, C,
output Y
);
assign Y = (A & B) | (B & C) | (A & C);
endmodule

Pro Tip
Pro Tip: Expand to 5-input and 7-input majority logic – useful in fault-tolerant systems.

Project 21: D Flip-Flop with Asynchronous Reset


Objective: Design a positive-edge triggered D Flip-Flop with asynchronous reset.

Verilog Code
module dff_async_reset (
input D, clk, rst,
output reg Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 0;
else
Q <= D;
end
endmodule

Pro Tip
Pro Tip: Asynchronous resets can be dangerous in CDC designs. Use sync resets for
FPGA.

Project 22: D Flip-Flop with Enable


Objective: Create a DFF that only updates output when enable is HIGH.

220
Chapter 16 Problems with Solutions

Verilog Code
module dff_enable (
input clk, rst, en, D,
output reg Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 0;
else if (en)
Q <= D;
end
endmodule

Pro Tip
Pro Tip: Use such flip-flops in data latches or gated registers in FSMs.

Project 23: JK Flip-Flop

Objective: Implement a classic JK flip-flop behavior.

221
Chapter 16 Problems with Solutions

Verilog Code
module jk_flip_flop (
input J, K, clk, rst,
output reg Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 0;
else if (J & ~K)
Q <= 1;
else if (~J & K)
Q <= 0;
else if (J & K)
Q <= ~Q;
end
endmodule

Pro Tip
Pro Tip: JK flip-flops are used in counters and toggling registers.

Project 24: T Flip-Flop

Objective: Create a toggle flip-flop using JK logic.

222
Chapter 16 Problems with Solutions

Verilog Code
module t_flip_flop (
input T, clk, rst,
output reg Q
);
always @(posedge clk or posedge rst) begin
if (rst)
Q <= 0;
else if (T)
Q <= ~Q;
end
endmodule

Pro Tip
Pro Tip: T flip-flops are often used in frequency dividers.

Project 25: 4-bit Synchronous Counter with Enable


Objective: Counter that counts only when enable is HIGH.

Verilog Code
module counter_sync_en (
input clk, rst, en,
output reg [3:0] count
);
always @(posedge clk or posedge rst) begin
if (rst)
count <= 0;
else if (en)
count <= count + 1;
end
endmodule

223
Chapter 16 Problems with Solutions

Pro Tip
Pro Tip: Use ‘en‘ to control state transition in FSMs as well.

Project 26: Clock Divider by 2

Objective: Create a clock divider using a T flip-flop logic.

Verilog Code
module clk_div2 (
input clk, rst,
output reg clk_out
);
always @(posedge clk or posedge rst) begin
if (rst)
clk_out <= 0;
else
clk_out <= ~clk_out;
end
endmodule

Pro Tip
Pro Tip: Extend this to divide clock by 4, 8, or N using counters.

Project 27: Clock Divider by 4

Objective: Use a 2-bit counter to divide clock frequency.

224
Chapter 16 Problems with Solutions

Verilog Code
module clk_div4 (
input clk, rst,
output reg clk_out
);
reg [1:0] count;

always @(posedge clk or posedge rst) begin


if (rst) begin
count <= 0;
clk_out <= 0;
end else begin
count <= count + 1;
if (count == 2’b11)
clk_out <= ~clk_out;
end
end
endmodule

Project 28: Clock Divider by N (Parameterizable)

Objective: Build a clock divider with customizable divide factor.

225
Chapter 16 Problems with Solutions

Verilog Code
module clk_div_n #(parameter N = 10)(
input clk, rst,
output reg clk_out
);
reg [$clog2(N)-1:0] count;

always @(posedge clk or posedge rst) begin


if (rst) begin
count <= 0;
clk_out <= 0;
end else begin
if (count == N-1) begin
count <= 0;
clk_out <= ~clk_out;
end else
count <= count + 1;
end
end
endmodule

Pro Tip
Pro Tip: Use ‘clog2‘ to make the design more scalable.

Project 29: Priority Encoder (4-to-2)

Objective: Encode the highest priority input out of 4.

226
Chapter 16 Problems with Solutions

Verilog Code
module priority_encoder_4to2 (
input [3:0] D,
output reg [1:0] Y
);
always @(*) begin
casez (D)
4’b1???: Y = 2’b11;
4’b01??: Y = 2’b10;
4’b001?: Y = 2’b01;
4’b0001: Y = 2’b00;
default: Y = 2’bxx;
endcase
end
endmodule

Project 30: Edge Detector (Rising Edge)


Problem: Design a module that detects the rising edge of a signal.

Solution:
1 module edge_detector (
2 input clk,
3 input signal,
4 output reg edge_detected
5 );
6 reg signal_d;
7
8 always @(posedge clk) begin
9 signal_d <= signal;
10 edge_detected <= signal & ~signal_d;
11 end
12 endmodule

227
Chapter 16 Problems with Solutions

Project 31: Pulse Generator


Problem: Generate a single clock cycle pulse for every rising edge of an input.

Solution:
1 module pulse_gen (
2 input clk,
3 input trigger,
4 output reg pulse
5 );
6 reg trigger_d;
7
8 always @(posedge clk) begin
9 trigger_d <= trigger;
10 pulse <= trigger & ~trigger_d;
11 end
12 endmodule

Project 32: 2-to-4 Decoder


Problem: Implement a 2-to-4 decoder using behavioral Verilog.

Solution:
1 module decoder_2to4 (
2 input [1:0] in,
3 input en,
4 output reg [3:0] out
5 );
6 always @(*) begin
7 if (en)
8 out = 4’b0001 << in;
9 else
10 out = 4’b0000;
11 end
12 endmodule

228
Chapter 16 Problems with Solutions

Project 33: D Flip-Flop with Enable and Async Reset


Problem: Design a D flip-flop with enable and asynchronous reset.

Solution:
1 module d_ff (
2 input clk,
3 input rst,
4 input en,
5 input d,
6 output reg q
7 );
8 always @(posedge clk or posedge rst) begin
9 if (rst)
10 q <= 0;
11 else if (en)
12 q <= d;
13 end
14 endmodule

Project 34: 4-bit Synchronous Counter with Enable


Problem: Create a 4-bit synchronous counter that increments only when enable is
high.

Solution:
1 module sync_counter (
2 input clk,
3 input rst,
4 input en,
5 output reg [3:0] count
6 );
7 always @(posedge clk or posedge rst) begin
8 if (rst)
9 count <= 0;
10 else if (en)
11 count <= count + 1;
12 end
13 endmodule

229
Chapter 16 Problems with Solutions

Project 35: 3-bit Binary Up Counter (Asynchronous Reset)


Problem: Design a 3-bit up counter with asynchronous reset.

Solution:
1 module up_counter (
2 input clk,
3 input rst,
4 output reg [2:0] count
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 count <= 3’b000;
9 else
10 count <= count + 1;
11 end
12 endmodule

Project 36: T Flip-Flop using D Flip-Flop


Problem: Implement a T flip-flop using a D flip-flop logic.

Solution:
1 module t_ff (
2 input clk,
3 input rst,
4 input t,
5 output reg q
6 );
7 always @(posedge clk or posedge rst) begin
8 if (rst)
9 q <= 0;
10 else if (t)
11 q <= ~q;
12 end
13 endmodule

230
Chapter 16 Problems with Solutions

Project 37: Synchronous Resettable D Flip-Flop


Problem: Design a D flip-flop with a synchronous reset.

Solution:
1 module sync_dff (
2 input clk,
3 input rst,
4 input d,
5 output reg q
6 );
7 always @(posedge clk) begin
8 if (rst)
9 q <= 0;
10 else
11 q <= d;
12 end
13 endmodule

Project 38: 1-bit Magnitude Comparator


Problem: Design a 1-bit comparator that gives output for A > B, A < B, A == B.

Solution:
1 module comparator_1bit (
2 input a, b,
3 output gt, lt, eq
4 );
5 assign gt = a & ~b;
6 assign lt = ~a & b;
7 assign eq = ~(a ^ b);
8 endmodule

231
Chapter 16 Problems with Solutions

Project 39: 8-to-3 Priority Encoder


Problem: Design an 8-to-3 priority encoder with valid output.

Solution:
1 module priority_encoder (
2 input [7:0] in,
3 output reg [2:0] out,
4 output reg valid
5 );
6 always @(*) begin
7 valid = 1’b1;
8 casex (in)
9 8’b1xxxxxxx: out = 3’b111;
10 8’b01xxxxxx: out = 3’b110;
11 8’b001xxxxx: out = 3’b101;
12 8’b0001xxxx: out = 3’b100;
13 8’b00001xxx: out = 3’b011;
14 8’b000001xx: out = 3’b010;
15 8’b0000001x: out = 3’b001;
16 8’b00000001: out = 3’b000;
17 default: begin
18 out = 3’b000;
19 valid = 1’b0;
20 end
21 endcase
22 end
23 endmodule

232
Chapter 16 Problems with Solutions

Project 40: 4-bit Up/Down Counter


Problem: Design a 4-bit up/down counter. The counter should increment or
decrement based on the updown signal.

Solution:
1 module up_down_counter (
2 input clk,
3 input rst,
4 input up_down, // 1 for up, 0 for down
5 output reg [3:0] count
6 );
7 always @(posedge clk or posedge rst) begin
8 if (rst)
9 count <= 4’b0000;
10 else if (up_down)
11 count <= count + 1;
12 else
13 count <= count - 1;
14 end
15 endmodule

Project 41: 4-bit Binary to Gray Code Converter


Problem: Implement a 4-bit binary to Gray code converter.

Solution:
1 module binary_to_gray (
2 input [3:0] bin,
3 output reg [3:0] gray
4 );
5 always @(*) begin
6 gray[3] = bin[3];
7 gray[2] = bin[3] ^ bin[2];
8 gray[1] = bin[2] ^ bin[1];
9 gray[0] = bin[1] ^ bin[0];
10 end
11 endmodule

233
Chapter 16 Problems with Solutions

Project 42: 3-to-8 Line Decoder


Problem: Design a 3-to-8 line decoder.

Solution:
1 module decoder_3to8 (
2 input [2:0] in,
3 output reg [7:0] out
4 );
5 always @(*) begin
6 case (in)
7 3’b000: out = 8’b00000001;
8 3’b001: out = 8’b00000010;
9 3’b010: out = 8’b00000100;
10 3’b011: out = 8’b00001000;
11 3’b100: out = 8’b00010000;
12 3’b101: out = 8’b00100000;
13 3’b110: out = 8’b01000000;
14 3’b111: out = 8’b10000000;
15 default: out = 8’b00000000;
16 endcase
17 end
18 endmodule

Project 43: 4-bit Binary Subtractor


Problem: Design a 4-bit binary subtractor. The subtractor should handle borrow
detection.

Solution:
1 module binary_subtractor (
2 input [3:0] a, b,
3 output reg [3:0] diff,
4 output reg borrow
5 );
6 always @(*) begin
7 {borrow, diff} = a - b;
8 end
9 endmodule

234
Chapter 16 Problems with Solutions

Project 44: 4-bit Binary Adder


Problem: Implement a 4-bit binary adder. The adder should include a carry-out
bit.

Solution:
1 module binary_adder (
2 input [3:0] a, b,
3 output reg [3:0] sum,
4 output reg carry_out
5 );
6 always @(*) begin
7 {carry_out, sum} = a + b;
8 end
9 endmodule

Project 45: 8-bit Multiplier


Problem: Design an 8-bit multiplier. The module should take two 8-bit inputs and
output the 16-bit product.

Solution:
1 module multiplier_8bit (
2 input [7:0] a, b,
3 output reg [15:0] product
4 );
5 always @(*) begin
6 product = a * b;
7 end
8 endmodule

235
Chapter 16 Problems with Solutions

Project 46: 4-bit Magnitude Comparator


Problem: Create a 4-bit magnitude comparator. The output should indicate
whether one number is greater than, less than, or equal to the other.

Solution:
1 module magnitude_comparator (
2 input [3:0] a, b,
3 output reg greater, less, equal
4 );
5 always @(*) begin
6 if (a > b) begin
7 greater = 1;
8 less = 0;
9 equal = 0;
10 end else if (a < b) begin
11 greater = 0;
12 less = 1;
13 equal = 0;
14 end else begin
15 greater = 0;
16 less = 0;
17 equal = 1;
18 end
19 end
20 endmodule

236
Chapter 16 Problems with Solutions

Project 47: 4-bit Parity Generator


Problem: Design a 4-bit parity generator. The module should generate an even or
odd parity bit based on the inputs.

Solution:
1 module parity_generator (
2 input [3:0] data,
3 output reg parity
4 );
5 always @(*) begin
6 parity = data[0] ^ data[1] ^ data[2] ^ data[3]; // Even
parity
7 end
8 endmodule

Project 48: 4-bit D Flip-Flop


Problem: Design a 4-bit D flip-flop. The flip-flop should latch the input value on
the rising edge of the clock signal.

Solution:
1 module d_flip_flop (
2 input clk, rst,
3 input [3:0] d,
4 output reg [3:0] q
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 q <= 4’b0000;
9 else
10 q <= d;
11 end
12 endmodule

237
Chapter 16 Problems with Solutions

Project 49: Shift Register (4-bit)


Problem: Design a 4-bit shift register. The shift register should support both left
and right shifting based on the control signal.

Solution:
1 module shift_register (
2 input clk, rst, shift_left, shift_right,
3 input [3:0] data_in,
4 output reg [3:0] data_out
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 data_out <= 4’b0000;
9 else if (shift_left)
10 data_out <= data_out << 1;
11 else if (shift_right)
12 data_out <= data_out >> 1;
13 else
14 data_out <= data_in;
15 end
16 endmodule

238
Chapter 16 Problems with Solutions

Project 50: 4-bit Counter with Enable


Problem: Design a 4-bit counter with enable. The counter should count up or down
based on the ‘updown‘ signal and should only count when the enable signal is active.

Solution:
1 module counter_with_enable (
2 input clk, rst, enable, up_down,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else if (enable) begin
9 if (up_down)
10 count <= count + 1;
11 else
12 count <= count - 1;
13 end
14 end
15 endmodule

239
Chapter 16 Problems with Solutions

Project 51: 4-bit Up/Down Counter


Problem: Design a 4-bit up/down counter with control logic to select the counting
direction. The counter should increment or decrement based on the ‘updown‘
signal.

Solution:
1 module up_down_counter (
2 input clk, rst, up_down, // up_down is 1 for up, 0 for down
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else if (up_down)
9 count <= count + 1;
10 else
11 count <= count - 1;
12 end
13 endmodule

240
Chapter 16 Problems with Solutions

Project 52: 8-bit Comparator


Problem: Design an 8-bit comparator that compares two 8-bit inputs and returns a
result indicating if the first number is greater, equal, or less than the second number.

Solution:
1 module comparator_8bit (
2 input [7:0] a, b,
3 output reg greater, equal, less
4 );
5 always @(*) begin
6 if (a > b) begin
7 greater = 1;
8 less = 0;
9 equal = 0;
10 end else if (a < b) begin
11 greater = 0;
12 less = 1;
13 equal = 0;
14 end else begin
15 greater = 0;
16 less = 0;
17 equal = 1;
18 end
19 end
20 endmodule

241
Chapter 16 Problems with Solutions

Project 53: 4-bit Binary to BCD Converter


Problem: Create a 4-bit binary to BCD converter. The output should represent the
binary input in Binary Coded Decimal (BCD).

Solution:
1 module bin_to_bcd (
2 input [3:0] bin,
3 output reg [7:0] bcd
4 );
5 always @(*) begin
6 case(bin)
7 4’b0000: bcd = 8’b00000000; // BCD for 0
8 4’b0001: bcd = 8’b00000001; // BCD for 1
9 4’b0010: bcd = 8’b00000010; // BCD for 2
10 4’b0011: bcd = 8’b00000011; // BCD for 3
11 4’b0100: bcd = 8’b00000100; // BCD for 4
12 4’b0101: bcd = 8’b00000101; // BCD for 5
13 4’b0110: bcd = 8’b00000110; // BCD for 6
14 4’b0111: bcd = 8’b00000111; // BCD for 7
15 4’b1000: bcd = 8’b00001000; // BCD for 8
16 4’b1001: bcd = 8’b00001001; // BCD for 9
17 default: bcd = 8’b00000000; // Default BCD for
invalid input
18 endcase
19 end
20 endmodule

242
Chapter 16 Problems with Solutions

Project 54: Priority Encoder


Problem: Design a 4-bit priority encoder that takes 4 input lines and returns a 2-bit
output. The output should represent the highest priority active input.

Solution:
1 module priority_encoder (
2 input [3:0] in,
3 output reg [1:0] out
4 );
5 always @(*) begin
6 case (in)
7 4’b1000: out = 2’b11;
8 4’b0100: out = 2’b10;
9 4’b0010: out = 2’b01;
10 4’b0001: out = 2’b00;
11 default: out = 2’b00; // In case of no active input
12 endcase
13 end
14 endmodule

Project 55: 4-bit Up Counter with Enable


Problem: Design a 4-bit up counter with an enable input. The counter should
increment only when the enable signal is active.

Solution:
1 module up_counter_enable (
2 input clk, rst, enable,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else if (enable)
9 count <= count + 1;
10 end
11 endmodule

243
Chapter 16 Problems with Solutions

Project 56: 4-bit Down Counter with Enable


Problem: Design a 4-bit down counter with an enable input. The counter should
decrement only when the enable signal is active.

Solution:
1 module down_counter_enable (
2 input clk, rst, enable,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b1111;
8 else if (enable)
9 count <= count - 1;
10 end
11 endmodule

Project 57: Johnson Counter


Problem: Design a 4-bit Johnson counter. The output should create a sequence of
4-bit patterns, cycling through a set of states.

Solution:
1 module johnson_counter (
2 input clk, rst,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else
9 count <= {count[2:0], ~count[3]};
10 end
11 endmodule

244
Chapter 16 Problems with Solutions

Project 58: 4-bit Binary to Gray Code Converter


Problem: Create a 4-bit binary to Gray code converter. The output should convert
a binary number into its corresponding Gray code.

Solution:
1 module bin_to_gray (
2 input [3:0] bin,
3 output [3:0] gray
4 );
5 assign gray[3] = bin[3]; // MSB of Gray code is the same as
binary
6 assign gray[2] = bin[3] ^ bin[2];
7 assign gray[1] = bin[2] ^ bin[1];
8 assign gray[0] = bin[1] ^ bin[0];
9 endmodule

Project 59: 4-bit Gray to Binary Converter


Problem: Create a 4-bit Gray code to binary converter. The output should convert
a Gray code number into its corresponding binary value.

Solution:
1 module gray_to_bin (
2 input [3:0] gray,
3 output [3:0] bin
4 );
5 assign bin[3] = gray[3];
6 assign bin[2] = gray[3] ^ gray[2];
7 assign bin[1] = gray[2] ^ gray[1];
8 assign bin[0] = gray[1] ^ gray[0];
9 endmodule

245
Chapter 16 Problems with Solutions

Project 60: 4-bit Synchronous Up Counter


Problem: Design a 4-bit synchronous up counter. The counter should increment
on every clock pulse, and it should reset to 0 when the reset signal is asserted.

Solution:
1 module sync_up_counter (
2 input clk, rst,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else
9 count <= count + 1;
10 end
11 endmodule

246
Chapter 16 Problems with Solutions

Project 61: 4-bit Up/Down Counter with Enable


Problem: Design a 4-bit up/down counter with an enable input. The counter
should count up or down based on the ‘updown‘ signal, and should only count
when the enable signal is active.

Solution:
1 module up_down_counter_enable (
2 input clk, rst, enable, up_down, // up_down is 1 for up, 0 for
down
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge rst) begin
6 if (rst)
7 count <= 4’b0000;
8 else if (enable) begin
9 if (up_down)
10 count <= count + 1;
11 else
12 count <= count - 1;
13 end
14 end
15 endmodule

247
Chapter 16 Problems with Solutions

Project 62: 4-bit D Flip-Flop


Problem: Design a 4-bit D flip-flop. The output should store the 4-bit value from
the input ‘d‘ on the rising edge of the clock.

Solution:
1 module d_flip_flop (
2 input clk, rst,
3 input [3:0] d,
4 output reg [3:0] q
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 q <= 4’b0000;
9 else
10 q <= d;
11 end
12 endmodule

Project 63: 4-bit Register with Parallel Load


Problem: Design a 4-bit register that can load data in parallel. The register should
load the input data when the load signal is active.

Solution:
1 module register_4bit (
2 input clk, rst, load,
3 input [3:0] data_in,
4 output reg [3:0] data_out
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 data_out <= 4’b0000;
9 else if (load)
10 data_out <= data_in;
11 end
12 endmodule

248
Chapter 16 Problems with Solutions

Project 64: 4-bit Synchronous Resettable Counter


Problem: Design a 4-bit counter with synchronous reset. The counter should reset
to 0 on the rising edge of the reset signal, and otherwise increment on the rising
edge of the clock.

Solution:
1 module sync_reset_counter (
2 input clk, rst,
3 output reg [3:0] count
4 );
5 always @(posedge clk) begin
6 if (rst)
7 count <= 4’b0000;
8 else
9 count <= count + 1;
10 end
11 endmodule

Project 65: Frequency Divider


Problem: Design a frequency divider that divides the input clock frequency by a
factor of 2. The output should toggle its state on every clock cycle.

Solution:
1 module frequency_divider (
2 input clk,
3 output reg divided_clk
4 );
5 always @(posedge clk) begin
6 divided_clk <= ~divided_clk;
7 end
8 endmodule

249
Chapter 16 Problems with Solutions

Project 66: 4-bit Shift Register


Problem: Design a 4-bit shift register. The register should shift left or right based
on the control signal. The data should shift in on every clock cycle.

Solution:
1 module shift_register (
2 input clk, rst, shift_left, shift_right,
3 input [3:0] data_in,
4 output reg [3:0] data_out
5 );
6 always @(posedge clk or posedge rst) begin
7 if (rst)
8 data_out <= 4’b0000;
9 else if (shift_left)
10 data_out <= {data_out[2:0], data_in[0]}; // Shift
left
11 else if (shift_right)
12 data_out <= {data_in[3], data_out[3:1]}; // Shift
right
13 end
14 endmodule

Project 67: 4-bit Even Parity Generator


Problem: Design a 4-bit even parity generator. The output should be a 4-bit value
along with an additional parity bit, such that the total number of ones in the output
(including the parity bit) is even.

Solution:
1 module even_parity_generator (
2 input [3:0] data_in,
3 output reg [4:0] data_out // 4 data bits + 1 parity bit
4 );
5 always @(*) begin
6 data_out[3:0] = data_in;
7 data_out[4] = ^data_in; // XOR all bits to generate
parity
8 end
9 endmodule

250
Chapter 16 Problems with Solutions

Project 68: 4-bit Even Parity Checker


Problem: Design a 4-bit even parity checker. The output should indicate whether
the 4-bit input has even parity.

Solution:
1 module even_parity_checker (
2 input [3:0] data_in,
3 output reg parity_ok
4 );
5 always @(*) begin
6 parity_ok = (~^data_in); // Check if XOR of all bits is 0
(even parity)
7 end
8 endmodule

Project 69: 4-bit Odd Parity Generator


Problem: Design a 4-bit odd parity generator. The output should be a 4-bit value
along with an additional parity bit, such that the total number of ones in the output
(including the parity bit) is odd.

Solution:
1 module odd_parity_generator (
2 input [3:0] data_in,
3 output reg [4:0] data_out // 4 data bits + 1 parity bit
4 );
5 always @(*) begin
6 data_out[3:0] = data_in;
7 data_out[4] = ~^data_in; // XOR all bits and invert to
generate odd parity
8 end
9 endmodule

251
Chapter 16 Problems with Solutions

Project 70: 4-bit Odd Parity Checker


Problem: Design a 4-bit odd parity checker. The output should indicate whether
the 4-bit input has odd parity.

Solution:
1 module odd_parity_checker (
2 input [3:0] data_in,
3 output reg parity_ok
4 );
5 always @(*) begin
6 parity_ok = ^data_in; // XOR all bits, result is 1 for
odd parity
7 end
8 endmodule

Project 71: 4-bit Binary to Gray Code Converter


Problem: Design a 4-bit binary to Gray code converter. The output should be the
equivalent Gray code for the 4-bit binary input.

Solution:
1 module binary_to_gray (
2 input [3:0] binary,
3 output reg [3:0] gray
4 );
5 always @(*) begin
6 gray[3] = binary[3]; // MSB remains the same
7 gray[2] = binary[3] ^ binary[2];
8 gray[1] = binary[2] ^ binary[1];
9 gray[0] = binary[1] ^ binary[0];
10 end
11 endmodule

252
Chapter 16 Problems with Solutions

Project 72: 4-bit Gray to Binary Converter


Problem: Design a 4-bit Gray code to binary converter. The output should be the
equivalent binary code for the 4-bit Gray code input.

Solution:
1 module gray_to_binary (
2 input [3:0] gray,
3 output reg [3:0] binary
4 );
5 always @(*) begin
6 binary[3] = gray[3]; // MSB remains the same
7 binary[2] = binary[3] ^ gray[2];
8 binary[1] = binary[2] ^ gray[1];
9 binary[0] = binary[1] ^ gray[0];
10 end
11 endmodule

Project 73: 4-bit Priority Encoder


Problem: Design a 4-bit priority encoder. The encoder should output a 2-bit binary
code corresponding to the highest-priority active input.

Solution:
1 module priority_encoder (
2 input [3:0] in,
3 output reg [1:0] out
4 );
5 always @(*) begin
6 casez (in)
7 4’b0001: out = 2’b00;
8 4’b0010: out = 2’b01;
9 4’b0100: out = 2’b10;
10 4’b1000: out = 2’b11;
11 default: out = 2’b00;
12 endcase
13 end
14 endmodule

253
Chapter 16 Problems with Solutions

Project 74: 4-bit 2-to-1 Multiplexer


Problem: Design a 4-bit 2-to-1 multiplexer. The multiplexer should select one of
the two 4-bit inputs based on the select signal.

Solution:
1 module mux_2_to_1 (
2 input [3:0] a, b,
3 input sel,
4 output reg [3:0] out
5 );
6 always @(*) begin
7 if (sel)
8 out = b;
9 else
10 out = a;
11 end
12 endmodule

Project 75: 4-bit 4-to-1 Multiplexer


Problem: Design a 4-bit 4-to-1 multiplexer. The multiplexer should select one of
the four 4-bit inputs based on the 2-bit select signal.

Solution:
1 module mux_4_to_1 (
2 input [3:0] a, b, c, d,
3 input [1:0] sel,
4 output reg [3:0] out
5 );
6 always @(*) begin
7 case(sel)
8 2’b00: out = a;
9 2’b01: out = b;
10 2’b10: out = c;
11 2’b11: out = d;
12 default: out = 4’b0000;
13 endcase
14 end
15 endmodule

254
Chapter 16 Problems with Solutions

Project 76: 4-bit Full Adder


Problem: Design a 4-bit full adder. The adder should take two 4-bit inputs and
produce a 4-bit sum along with a carry-out.

Solution:
1 module full_adder (
2 input [3:0] a, b,
3 input cin,
4 output [3:0] sum,
5 output cout
6 );
7 assign {cout, sum} = a + b + cin;
8 endmodule

Project 77: 4-bit Subtractor


Problem: Design a 4-bit subtractor. The subtractor should take two 4-bit inputs
and produce a 4-bit difference along with a borrow-out.

Solution:
1 module subtractor (
2 input [3:0] a, b,
3 output [3:0] diff,
4 output borrow
5 );
6 assign {borrow, diff} = a - b;
7 endmodule

255
Chapter 16 Problems with Solutions

Project 78: 4-bit Multiplication


Problem: Design a 4-bit multiplier. The multiplier should take two 4-bit inputs
and produce an 8-bit product.

Solution:
1 module multiplier (
2 input [3:0] a, b,
3 output [7:0] product
4 );
5 assign product = a * b;
6 endmodule

Project 79: 4-bit Divider


Problem: Design a 4-bit divider. The divider should take two 4-bit inputs and
produce a quotient and remainder.

Solution:
1 module divider (
2 input [3:0] a, b,
3 output [3:0] quotient,
4 output [3:0] remainder
5 );
6 assign quotient = a / b;
7 assign remainder = a % b;
8 endmodule

256
Chapter 16 Problems with Solutions

Project 80: 4-bit AND Gate


Problem: Design a 4-bit AND gate. The gate should perform a bitwise AND
operation between two 4-bit inputs.

Solution:
1 module and_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = a & b;
6 endmodule

Project 81: 4-bit OR Gate


Problem: Design a 4-bit OR gate. The gate should perform a bitwise OR operation
between two 4-bit inputs.

Solution:
1 module or_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = a | b;
6 endmodule

257
Chapter 16 Problems with Solutions

Project 82: 4-bit XOR Gate


Problem: Design a 4-bit XOR gate. The gate should perform a bitwise XOR
operation between two 4-bit inputs.

Solution:
1 module xor_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = a ^ b;
6 endmodule

Project 83: 4-bit XNOR Gate


Problem: Design a 4-bit XNOR gate. The gate should perform a bitwise XNOR
operation between two 4-bit inputs.

Solution:
1 module xnor_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = ~(a ^ b);
6 endmodule

258
Chapter 16 Problems with Solutions

Project 84: 4-bit NOT Gate


Problem: Design a 4-bit NOT gate. The gate should perform a bitwise NOT
operation on a 4-bit input.

Solution:
1 module not_gate (
2 input [3:0] a,
3 output [3:0] out
4 );
5 assign out = ~a;
6 endmodule

Project 85: 4-bit NAND Gate


Problem: Design a 4-bit NAND gate. The gate should perform a bitwise NAND
operation between two 4-bit inputs.

Solution:
1 module nand_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = ~(a & b);
6 endmodule

259
Chapter 16 Problems with Solutions

Project 86: 4-bit NOR Gate


Problem: Design a 4-bit NOR gate. The gate should perform a bitwise NOR
operation between two 4-bit inputs.

Solution:
1 module nor_gate (
2 input [3:0] a, b,
3 output [3:0] out
4 );
5 assign out = ~(a | b);
6 endmodule

Project 87: 4-bit Comparator


Problem: Design a 4-bit comparator. The comparator should output 1 if both 4-bit
inputs are equal, otherwise 0.

Solution:
1 module comparator (
2 input [3:0] a, b,
3 output reg equal
4 );
5 always @(*) begin
6 if (a == b)
7 equal = 1;
8 else
9 equal = 0;
10 end
11 endmodule

260
Chapter 16 Problems with Solutions

Project 88: 4-bit Decoder


Problem: Design a 4-bit decoder. The decoder should take a 2-bit input and
generate one of the four 1-bit outputs based on the input.

Solution:
1 module decoder (
2 input [1:0] in,
3 output reg [3:0] out
4 );
5 always @(*) begin
6 case (in)
7 2’b00: out = 4’b0001;
8 2’b01: out = 4’b0010;
9 2’b10: out = 4’b0100;
10 2’b11: out = 4’b1000;
11 default: out = 4’b0000;
12 endcase
13 end
14 endmodule

Project 89: 4-bit Up-Counter


Problem: Design a 4-bit up-counter. The counter should increment by 1 with each
clock cycle.

Solution:
1 module up_counter (
2 input clk, reset,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge reset) begin
6 if (reset)
7 count <= 4’b0000;
8 else
9 count <= count + 1;
10 end
11 endmodule

261
Chapter 16 Problems with Solutions

Project 90: 4-bit Down-Counter


Problem: Design a 4-bit down-counter. The counter should decrement by 1 with
each clock cycle.

Solution:
1 module down_counter (
2 input clk, reset,
3 output reg [3:0] count
4 );
5 always @(posedge clk or posedge reset) begin
6 if (reset)
7 count <= 4’b1111;
8 else
9 count <= count - 1;
10 end
11 endmodule

262
Chapter 16 Problems with Solutions

Project 91: 4-bit ALU


Problem: Design a 4-bit ALU (Arithmetic Logic Unit) that supports the following
operations:

• Addition

• Subtraction

• AND

• OR

• XOR

• NOT

The ALU should take two 4-bit inputs and an operation selector input. Based on
the selector, it should perform the desired operation.

Solution:
1 module alu (
2 input [3:0] a, b,
3 input [2:0] op, // Operation selector
4 output reg [3:0] result
5 );
6 always @(*) begin
7 case(op)
8 3’b000: result = a + b; // Addition
9 3’b001: result = a - b; // Subtraction
10 3’b010: result = a & b; // AND
11 3’b011: result = a | b; // OR
12 3’b100: result = a ^ b; // XOR
13 3’b101: result = ~a; // NOT (on a)
14 default: result = 4’b0000; // Default to 0
15 endcase
16 end
17 endmodule

263
Chapter 16 Problems with Solutions

Project 92: 16-bit Shift Register


Problem: Design a 16-bit shift register with left and right shift operations. The
shift register should support both synchronous and asynchronous reset.

Solution:
1 module shift_register (
2 input clk, reset, shift_left, shift_right,
3 input [15:0] data_in,
4 output reg [15:0] data_out
5 );
6 always @(posedge clk or posedge reset) begin
7 if (reset)
8 data_out <= 16’b0;
9 else if (shift_left)
10 data_out <= data_out << 1;
11 else if (shift_right)
12 data_out <= data_out >> 1;
13 end
14 endmodule

Project 93: 8-bit Multiplier


Problem: Design an 8-bit multiplier. The multiplier should take two 8-bit inputs
and produce a 16-bit result. Use a combinational approach without any clocking.

Solution:
1 module multiplier (
2 input [7:0] a, b,
3 output [15:0] product
4 );
5 assign product = a * b;
6 endmodule

264
Chapter 16 Problems with Solutions

Project 94: 4-bit Priority Encoder


Problem: Design a 4-bit priority encoder. The encoder should take a 4-bit input
and produce a 2-bit output that represents the binary code of the highest priority
bit. If no input is active, output should be 00.

Solution:
1 module priority_encoder (
2 input [3:0] in,
3 output reg [1:0] out
4 );
5 always @(*) begin
6 casez(in)
7 4’b0001: out = 2’b00;
8 4’b001x: out = 2’b01;
9 4’b01xx: out = 2’b10;
10 4’b1xxx: out = 2’b11;
11 default: out = 2’b00;
12 endcase
13 end
14 endmodule

Project 95: 16-bit Synchronous Counter


Problem: Design a 16-bit synchronous counter that counts from 0 to 65535 and
resets to 0 on a reset signal. The counter should have a clock enable input.

Solution:
1 module counter (
2 input clk, reset, enable,
3 output reg [15:0] count
4 );
5 always @(posedge clk or posedge reset) begin
6 if (reset)
7 count <= 16’b0;
8 else if (enable)
9 count <= count + 1;
10 end
11 endmodule

265
Chapter 16 Problems with Solutions

Project 96: 8-bit Barrel Shifter


Problem: Design an 8-bit barrel shifter. The barrel shifter should be able to
perform both left and right shift operations. The shift amount should be a 3-bit
value, allowing shifts from 0 to 7 positions.

Solution:
1 module barrel_shifter (
2 input [7:0] data_in,
3 input [2:0] shift_amount,
4 input shift_left, shift_right,
5 output reg [7:0] data_out
6 );
7 always @(*) begin
8 if (shift_left)
9 data_out = data_in << shift_amount;
10 else if (shift_right)
11 data_out = data_in >> shift_amount;
12 else
13 data_out = data_in;
14 end
15 endmodule

Project 97: 8-bit Full Adder with Carry-In


Problem: Design an 8-bit full adder with carry-in. The adder should take two 8-bit
inputs, a carry-in, and produce an 8-bit sum and a carry-out.

Solution:
1 module full_adder (
2 input [7:0] a, b,
3 input carry_in,
4 output [7:0] sum,
5 output carry_out
6 );
7 assign {carry_out, sum} = a + b + carry_in;
8 endmodule

266
Chapter 16 Problems with Solutions

Project 98: 4-bit Register File


Problem: Design a 4-bit register file with 4 registers and a 2-bit register address
input. The register file should have a write-enable signal and be able to read and
write to registers.

Solution:
1 module reg_file (
2 input clk, we,
3 input [1:0] addr,
4 input [3:0] data_in,
5 output reg [3:0] data_out
6 );
7 reg [3:0] registers [3:0]; // 4 registers of 4 bits each
8
9 always @(posedge clk) begin
10 if (we)
11 registers[addr] <= data_in;
12 data_out <= registers[addr];
13 end
14 endmodule

Project 99: 8-bit Comparator


Problem: Design an 8-bit comparator that compares two 8-bit values and outputs
‘1‘ if they are equal, otherwise ‘0‘.

Solution:
1 module comparator (
2 input [7:0] a, b,
3 output reg equal
4 );
5 always @(*) begin
6 if (a == b)
7 equal = 1;
8 else
9 equal = 0;
10 end
11 endmodule

267
Chapter 16 Problems with Solutions

Project 100: 4-bit RAM with Read/Write Enable


Problem: Design a 4-bit RAM with read and write enable. The memory should
have 16 words, each of 4 bits. Use an address bus for selecting the memory location,
and a data bus for reading/writing data. The module should have a read-enable and
write-enable signal to control operations.
Solution:
1 module ram (
2 input clk, reset,
3 input [3:0] addr, data_in,
4 input we, re, // Write enable and Read enable
5 output reg [3:0] data_out
6 );
7 reg [3:0] memory [15:0]; // 16 words of 4 bits each
8
9 always @(posedge clk or posedge reset) begin
10 if (reset)
11 data_out <= 4’b0; // Reset output to 0
12 else if (re)
13 data_out <= memory[addr]; // Read operation
14 else if (we)
15 memory[addr] <= data_in; // Write operation
16 end
17 endmodule

268
Chapter 16 Problems with Solutions

Project 101: 8-bit Dual-Port RAM


Problem: Design an 8-bit dual-port RAM with separate read and write ports. This
memory should allow simultaneous reading and writing to different locations.
Solution:
1 module dual_port_ram (
2 input clk,
3 input [3:0] addr_a, addr_b,
4 input [7:0] data_in_a, data_in_b,
5 input we_a, we_b, // Write enable for both ports
6 output reg [7:0] data_out_a, data_out_b
7 );
8 reg [7:0] memory [15:0]; // 16 words of 8 bits each
9

10 always @(posedge clk) begin


11 if (we_a)
12 memory[addr_a] <= data_in_a; // Write to port A
13 else
14 data_out_a <= memory[addr_a]; // Read from port A
15

16 if (we_b)
17 memory[addr_b] <= data_in_b; // Write to port B
18 else
19 data_out_b <= memory[addr_b]; // Read from port B
20 end
21 endmodule

269
Chapter 16 Problems with Solutions

Project 102: 16-bit FIFO Buffer


Problem: Design a 16-bit FIFO (First In, First Out) buffer. The buffer should have
8 slots, each 16 bits wide. It should have both read and write pointers, and control
signals for read, write, and full/empty indications.
Solution:
1 module fifo_buffer (
2 input clk, reset,
3 input [15:0] data_in,
4 input write_en, read_en, // Write and Read enable
5 output reg [15:0] data_out,
6 output reg full, empty
7 );
8 reg [15:0] memory [7:0]; // 8 slots of 16 bits each
9 reg [2:0] write_ptr, read_ptr;
10

11 always @(posedge clk or posedge reset) begin


12 if (reset) begin
13 write_ptr <= 3’b0;
14 read_ptr <= 3’b0;
15 full <= 0;
16 empty <= 1;
17 end else begin
18 if (write_en && !full) begin
19 memory[write_ptr] <= data_in;
20 write_ptr <= write_ptr + 1;
21 end
22

23 if (read_en && !empty) begin


24 data_out <= memory[read_ptr];
25 read_ptr <= read_ptr + 1;
26 end
27
28 // Check if the FIFO is full or empty
29 full <= (write_ptr == 3’b111);
30 empty <= (read_ptr == write_ptr);
31 end
32 end
33 endmodule

270
Chapter 16 Problems with Solutions

Project 103: 32-bit ROM


Problem: Design a 32-bit Read-Only Memory (ROM). The ROM should have 256
addresses, each of 32 bits. The ROM contents should be predefined as constants.
Solution:
1 module rom (
2 input [7:0] addr,
3 output reg [31:0] data_out
4 );
5 always @(*) begin
6 case (addr)
7 8’h00: data_out = 32’h12345678;
8 8’h01: data_out = 32’h9ABCDEF0;
9 // Add more cases as needed
10 default: data_out = 32’h00000000;
11 endcase
12 end
13 endmodule

Project 104: 8-bit Static RAM (SRAM)


Problem: Design an 8-bit Static RAM (SRAM) with a 64-word address space. The
SRAM should have a read-enable signal and a write-enable signal to control the
data input and output operations.
Solution:
1 module sram (
2 input clk, we, re,
3 input [5:0] addr, // 64 address locations (6 bits)
4 input [7:0] data_in,
5 output reg [7:0] data_out
6 );
7 reg [7:0] memory [63:0]; // 64 words of 8 bits each
8
9 always @(posedge clk) begin
10 if (we)
11 memory[addr] <= data_in; // Write data
12 if (re)
13 data_out <= memory[addr]; // Read data
14 end
15 endmodule

271
Chapter 16 Problems with Solutions

Project 105: 64-bit Shift Register File


Problem: Design a 64-bit shift register file with 8 registers. The shift register file
should have a shift-left and shift-right operation, and each register should be 64 bits
wide.
Solution:
1 module shift_reg_file (
2 input clk, reset, shift_left, shift_right,
3 input [2:0] addr,
4 input [63:0] data_in,
5 output reg [63:0] data_out
6 );
7 reg [63:0] registers [7:0]; // 8 registers of 64 bits each
8
9 always @(posedge clk or posedge reset) begin
10 if (reset)
11 data_out <= 64’b0;
12 else if (shift_left)
13 data_out <= data_in << 1;
14 else if (shift_right)
15 data_out <= data_in >> 1;
16 else
17 data_out <= registers[addr];
18 end
19 endmodule

272
Chapter 16 Problems with Solutions

Project 106: 8-bit FIFO with Full and Empty Flags


Problem: Design an 8-bit FIFO queue with full and empty flags. The FIFO should
have 16 slots, each 8 bits wide, and should manage data with read and write pointers.
Solution:
1 module fifo_queue (
2 input clk, reset, write_en, read_en,
3 input [7:0] data_in,
4 output reg [7:0] data_out,
5 output reg full, empty
6 );
7 reg [7:0] memory [15:0]; // 16 slots of 8 bits each
8 reg [3:0] write_ptr, read_ptr;
9

10 always @(posedge clk or posedge reset) begin


11 if (reset) begin
12 write_ptr <= 4’b0;
13 read_ptr <= 4’b0;
14 full <= 0;
15 empty <= 1;
16 end else begin
17 if (write_en && !full) begin
18 memory[write_ptr] <= data_in;
19 write_ptr <= write_ptr + 1;
20 end
21

22 if (read_en && !empty) begin


23 data_out <= memory[read_ptr];
24 read_ptr <= read_ptr + 1;
25 end
26
27 // Full and empty conditions
28 full <= (write_ptr == 4’b1111);
29 empty <= (write_ptr == read_ptr);
30 end
31 end
32 endmodule

273
Chapter 16 Problems with Solutions

Project 107: 32-bit Synchronous FIFO with Push and Pop


Problem: Design a 32-bit synchronous FIFO with push and pop operations. The
FIFO should have 16 entries and should support read and write operations with full
and empty flags.
Solution:
1 module fifo_sync (
2 input clk, reset, push, pop,
3 input [31:0] data_in,
4 output reg [31:0] data_out,
5 output reg full, empty
6 );
7 reg [31:0] memory [15:0]; // 16 entries of 32 bits each
8 reg [3:0] write_ptr, read_ptr;
9
10 always @(posedge clk or posedge reset) begin
11 if (reset) begin
12 write_ptr <= 4’b0;
13 read_ptr <= 4’b0;
14 full <= 0;
15 empty <= 1;
16 end else begin
17 if (push && !full) begin
18 memory[write_ptr] <= data_in;
19 write_ptr <= write_ptr + 1;
20 end
21
22 if (pop && !empty) begin
23 data_out <= memory[read_ptr];
24 read_ptr <= read_ptr + 1;
25 end
26
27 full <= (write_ptr == 4’b1111);
28 empty <= (write_ptr == read_ptr);
29 end
30 end
31 endmodule

274
Chapter 16 Problems with Solutions

Project 108: 64-bit Register File with Read/Write Enable


Problem: Design a 64-bit register file with 16 registers. The register file should
support read and write operations and include a read-enable and write-enable signal
for controlling these operations.
Solution:
1 module reg_file (
2 input clk, reset,
3 input [3:0] addr, // 4-bit address to select one of 16
registers
4 input [63:0] data_in,
5 input we, re, // Write enable and Read enable
6 output reg [63:0] data_out
7 );
8 reg [63:0] registers [15:0]; // 16 registers of 64 bits each
9

10 always @(posedge clk or posedge reset) begin


11 if (reset)
12 data_out <= 64’b0;
13 else if (we)
14 registers[addr] <= data_in; // Write operation
15 else if (re)
16 data_out <= registers[addr]; // Read operation
17 end
18 endmodule

275
Chapter 16 Problems with Solutions

Project 109: 128-bit Wide Memory with Address Bus and Control Signals
Problem: Design a 128-bit wide memory with a 256 address bus. Implement con-
trol signals for read, write, and reset operations. The memory should allow for
reading and writing data with the specified width.
Solution:
1 module wide_memory (
2 input clk, reset,
3 input [7:0] addr, // 256 addresses (8-bit address bus)
4 input [127:0] data_in,
5 input we, re, // Write and Read enable signals
6 output reg [127:0] data_out
7 );
8 reg [127:0] memory [255:0]; // 256 locations, each 128 bits
wide
9

10 always @(posedge clk or posedge reset) begin


11 if (reset)
12 data_out <= 128’b0;
13 else begin
14 if (we)
15 memory[addr] <= data_in; // Write operation
16 if (re)
17 data_out <= memory[addr]; // Read operation
18 end
19 end
20 endmodule

276
Chapter 16 Problems with Solutions

Project 110: 4-port 32-bit Register File


Problem: Design a 4-port register file where each port has a 32-bit data bus. The
register file should support simultaneous read and write operations on different
ports.
Solution:
1 module four_port_reg_file (
2 input clk, reset,
3 input [3:0] addr_a, addr_b, addr_c, addr_d, // 4 address
inputs for 4 ports
4 input [31:0] data_in_a, data_in_b, data_in_c, data_in_d,
5 input we_a, we_b, we_c, we_d, // Write enables for each port
6 output reg [31:0] data_out_a, data_out_b, data_out_c,
data_out_d
7 );
8 reg [31:0] registers [15:0]; // 16 registers of 32 bits each
9
10 always @(posedge clk or posedge reset) begin
11 if (reset) begin
12 data_out_a <= 32’b0;
13 data_out_b <= 32’b0;
14 data_out_c <= 32’b0;
15 data_out_d <= 32’b0;
16 end else begin
17 if (we_a)
18 registers[addr_a] <= data_in_a;
19 if (we_b)
20 registers[addr_b] <= data_in_b;
21 if (we_c)
22 registers[addr_c] <= data_in_c;
23 if (we_d)
24 registers[addr_d] <= data_in_d;
25
26 data_out_a <= registers[addr_a];
27 data_out_b <= registers[addr_b];
28 data_out_c <= registers[addr_c];
29 data_out_d <= registers[addr_d];
30 end
31 end
32 endmodule

277
Chapter 16 Problems with Solutions

Project 111: 32-bit Shift Register with Load and Shift Operations
Problem: Design a 32-bit shift register with both load and shift operations. The
shift register should allow data to be shifted left or right, and it should have a load
input for loading data directly into the register.
Solution:
1 module shift_reg_32bit (
2 input clk, reset, shift_left, shift_right, load,
3 input [31:0] data_in,
4 output reg [31:0] data_out
5 );
6 reg [31:0] shift_reg;
7
8 always @(posedge clk or posedge reset) begin
9 if (reset)
10 shift_reg <= 32’b0;
11 else if (load)
12 shift_reg <= data_in; // Load operation
13 else if (shift_left)
14 shift_reg <= shift_reg << 1; // Shift left operation
15 else if (shift_right)
16 shift_reg <= shift_reg >> 1; // Shift right operation
17 end
18
19 always @(shift_reg) begin
20 data_out <= shift_reg;
21 end
22 endmodule

278
Chapter 16 Problems with Solutions

Project 112: 64-bit Asynchronous FIFO with Full and Empty Flags
Problem: Design a 64-bit asynchronous FIFO with full and empty flags. The FIFO
should support write and read operations asynchronously, and it should indicate
when it is full or empty.
Solution:
1 module async_fifo (
2 input clk, reset, write_en, read_en,
3 input [63:0] data_in,
4 output reg [63:0] data_out,
5 output reg full, empty
6 );
7 reg [63:0] memory [15:0]; // 16 slots of 64 bits each
8 reg [3:0] write_ptr, read_ptr;
9
10 always @(posedge clk or posedge reset) begin
11 if (reset) begin
12 write_ptr <= 4’b0;
13 read_ptr <= 4’b0;
14 full <= 0;
15 empty <= 1;
16 end else begin
17 if (write_en && !full) begin
18 memory[write_ptr] <= data_in;
19 write_ptr <= write_ptr + 1;
20 end
21
22 if (read_en && !empty) begin
23 data_out <= memory[read_ptr];
24 read_ptr <= read_ptr + 1;
25 end
26
27 full <= (write_ptr == 4’b1111);
28 empty <= (write_ptr == read_ptr);
29 end
30 end
31 endmodule

279
Chapter 16 Problems with Solutions

Project 113: 16x16-bit Dual-Port RAM with Separate Read/Write Ports


Problem: Design a dual-port RAM that allows simultaneous read and write oper-
ations on different ports. Each port should be 16 bits wide, and the RAM should
have 16 words in total.
Solution:
1 module dual_port_ram (
2 input clk, reset,
3 input [3:0] addr_a, addr_b, // 4-bit address for 16 locations
4 input [15:0] data_in_a, data_in_b,
5 input we_a, we_b, // Write enable for each port
6 output reg [15:0] data_out_a, data_out_b
7 );
8 reg [15:0] memory [15:0]; // 16 locations, each 16 bits wide
9
10 always @(posedge clk or posedge reset) begin
11 if (reset) begin
12 data_out_a <= 16’b0;
13 data_out_b <= 16’b0;
14 end else begin
15 if (we_a)
16 memory[addr_a] <= data_in_a; // Write to port A
17 if (we_b)
18 memory[addr_b] <= data_in_b; // Write to port B
19 data_out_a <= memory[addr_a]; // Read from port A
20 data_out_b <= memory[addr_b]; // Read from port B
21 end
22 end
23 endmodule

280
Chapter 16 Problems with Solutions

Project 114: 64-bit Asynchronous RAM with Clock Gating


Problem: Design a 64-bit asynchronous RAM with clock gating to save power.
The RAM should allow reading and writing asynchronously and should include a
clock-enable signal to control clock gating.
Solution:
1 module async_ram_with_clock_gating (
2 input clk, reset, clk_en,
3 input [5:0] addr, // 64 locations with 6-bit address
4 input [63:0] data_in,
5 input we, re, // Write enable and Read enable
6 output reg [63:0] data_out
7 );
8 reg [63:0] memory [63:0]; // 64 locations, each 64 bits wide
9
10 always @(posedge clk or posedge reset) begin
11 if (reset)
12 data_out <= 64’b0;
13 else if (clk_en) begin // Clock gating condition
14 if (we)
15 memory[addr] <= data_in; // Write operation
16 if (re)
17 data_out <= memory[addr]; // Read operation
18 end
19 end
20 endmodule

281
Chapter 16 Problems with Solutions

Project 115: 128-bit 4-way Set-Associative Cache


Problem: Design a 128-bit 4-way set-associative cache with an index width of
6 bits and a block size of 16 bytes. The cache should support read, write, and
invalidation operations.
Solution:
1 module cache_4_way_set_associative (
2 input clk, reset, read_en, write_en,
3 input [5:0] index, // 6-bit index for 64 cache sets
4 input [127:0] data_in,
5 output reg [127:0] data_out,
6 output reg hit
7 );
8 reg [127:0] cache [63:0][3:0]; // 64 sets, 4 ways per set
9
10 always @(posedge clk or posedge reset) begin
11 if (reset)
12 data_out <= 128’b0;
13 else begin
14 hit <= 0;
15 if (read_en) begin
16 // Check for a cache hit
17 if (cache[index][0] == data_in || cache[index][1]
== data_in ||
18 cache[index][2] == data_in || cache[index][3]
== data_in) begin
19 hit <= 1;
20 data_out <= data_in;
21 end
22 end
23 if (write_en) begin
24 cache[index][0] <= data_in; // Write operation
25 end
26 end
27 end
28 endmodule

282
Chapter 16 Problems with Solutions

Project 116: 2D Memory with Row and Column Addressing


Problem: Design a 2D memory array where rows and columns are addressed sep-
arately. The memory should support both row-wise and column-wise access for
reading and writing operations.
Solution:
1 module two_dimensional_memory (
2 input clk, reset,
3 input [3:0] row_addr, col_addr, // 4-bit row and column
address
4 input [31:0] data_in,
5 input we, re, // Write enable and Read
enable
6 output reg [31:0] data_out
7 );
8 reg [31:0] memory [15:0][15:0]; // 16x16 2D array of 32-bit
memory locations
9
10 always @(posedge clk or posedge reset) begin
11 if (reset)
12 data_out <= 32’b0;
13 else begin
14 if (we)
15 memory[row_addr][col_addr] <= data_in; // Write
to memory
16 if (re)
17 data_out <= memory[row_addr][col_addr]; // Read
from memory
18 end
19 end
20 endmodule

283
Chapter 16 Problems with Solutions

Project 117: Dynamic Memory Allocation with Alloc and Free Operations
Problem: Implement a dynamic memory allocation system that supports mem-
ory allocation and deallocation operations. The memory should be organized into
blocks, and each block should support allocation and freeing of memory.
Solution:
1 module dynamic_memory (
2 input clk, reset,
3 input alloc, free,
4 input [7:0] block_size, // Block size for allocation
5 output reg [7:0] allocated_mem
6 );
7 reg [7:0] memory [255:0]; // 256 blocks of memory, each 8
bits wide
8
9 always @(posedge clk or posedge reset) begin
10 if (reset)
11 allocated_mem <= 8’b0;
12 else begin
13 if (alloc)
14 allocated_mem <= block_size; // Allocate memory
block
15 if (free)
16 allocated_mem <= 8’b0; // Free memory block
17 end
18 end
19 endmodule

284
Chapter 16 Problems with Solutions

Project 118: 16-bit Memory-Mapped I/O Interface


Problem: Design a 16-bit memory-mapped I/O interface for communication be-
tween a CPU and external devices. The interface should allow data to be transferred
between the I/O device and the CPU memory.
Solution:
1 module memory_mapped_io (
2 input clk, reset, io_read, io_write,
3 input [15:0] data_in,
4 output reg [15:0] data_out
5 );
6 reg [15:0] io_device; // 16-bit I/O device memory
7
8 always @(posedge clk or posedge reset) begin
9 if (reset)
10 data_out <= 16’b0;
11 else begin
12 if (io_write)
13 io_device <= data_in; // Write to I/O device
14 if (io_read)
15 data_out <= io_device; // Read from I/O device
16 end
17 end
18 endmodule

285
Chapter 16 Problems with Solutions

Project 119: 2-bit Synchronous Counter with Reset


Problem: Design a 2-bit synchronous counter using an FSM. The counter should
have a reset functionality and count from 0 to 3, then roll over to 0.
Solution:
1 module sync_counter_2bit (
2 input clk, reset,
3 output reg [1:0] count
4 );
5 typedef enum logic [1:0] {
6 S0 = 2’b00,
7 S1 = 2’b01,
8 S2 = 2’b10,
9 S3 = 2’b11
10 } state_t;
11
12 state_t state, next_state;
13
14 always_ff @(posedge clk or posedge reset) begin
15 if (reset)
16 state <= S0;
17 else
18 state <= next_state;
19 end
20
21 always_comb begin
22 case(state)
23 S0: next_state = S1;
24 S1: next_state = S2;
25 S2: next_state = S3;
26 S3: next_state = S0;
27 default: next_state = S0;
28 endcase
29 end
30
31 always_ff @(posedge clk) begin
32 count <= state;
33 end
34 endmodule

286
Chapter 16 Problems with Solutions

Project 120: 4-bit Johnson Counter FSM


Problem: Design a 4-bit Johnson counter using FSM. The counter should produce
a unique sequence of binary values, where the output toggles between states in a
specific order.
Solution:
1 module johnson_counter (
2 input clk, reset,
3 output reg [3:0] count
4 );
5 typedef enum logic [3:0] {
6 S0 = 4’b0000,
7 S1 = 4’b0001,
8 S2 = 4’b0011,
9 S3 = 4’b0111,
10 S4 = 4’b1111,
11 S5 = 4’b1110,
12 S6 = 4’b1100,
13 S7 = 4’b1000
14 } state_t;
15
16 state_t state, next_state;
17
18 always_ff @(posedge clk or posedge reset) begin
19 if (reset)
20 state <= S0;
21 else
22 state <= next_state;
23 end
24
25 always_comb begin
26 case(state)
27 S0: next_state = S1;
28 S1: next_state = S2;
29 S2: next_state = S3;
30 S3: next_state = S4;
31 S4: next_state = S5;
32 S5: next_state = S6;
33 S6: next_state = S7;
34 S7: next_state = S0;
35 default: next_state = S0;
36 endcase
37 end
38
39 always_ff @(posedge clk) begin
40 count <= state;
41 end
42 endmodule 287
Chapter 16 Problems with Solutions

Project 121: FSM for Traffic Light Controller


Problem: Design an FSM-based traffic light controller. The system should have
three lights (Green, Yellow, Red), with the proper sequence for vehicle traffic.
Solution:
1 module traffic_light_controller (
2 input clk, reset,
3 output reg green, yellow, red
4 );
5 typedef enum logic [1:0] {
6 RED = 2’b00,
7 GREEN = 2’b01,
8 YELLOW = 2’b10
9 } state_t;
10
11 state_t state, next_state;
12
13 always_ff @(posedge clk or posedge reset) begin
14 if (reset)
15 state <= RED;
16 else
17 state <= next_state;
18 end
19
20 always_comb begin
21 case(state)
22 RED: next_state = GREEN;
23 GREEN: next_state = YELLOW;
24 YELLOW: next_state = RED;
25 default: next_state = RED;
26 endcase
27 end
28
29 always_ff @(posedge clk) begin
30 case(state)
31 RED: {red, yellow, green} = 3’b100;
32 GREEN: {red, yellow, green} = 3’b001;
33 YELLOW: {red, yellow, green} = 3’b010;
34 default: {red, yellow, green} = 3’b100;
35 endcase
36 end
37 endmodule

288
Chapter 16 Problems with Solutions

Project 122: FSM for 4-bit Sequence Detector


Problem: Design an FSM to detect a specific 4-bit sequence (e.g., 1011) in a serial
data stream.
Solution:
1 module sequence_detector (
2 input clk, reset, serial_in,
3 output reg detected
4 );
5 typedef enum logic [3:0] {
6 S0 = 4’b0000,
7 S1 = 4’b0001,
8 S2 = 4’b0010,
9 S3 = 4’b0011,
10 S4 = 4’b0100
11 } state_t;
12
13 state_t state, next_state;
14
15 always_ff @(posedge clk or posedge reset) begin
16 if (reset)
17 state <= S0;
18 else
19 state <= next_state;
20 end
21

22 always_comb begin
23 case(state)
24 S0: next_state = (serial_in) ? S1 : S0;
25 S1: next_state = (serial_in) ? S1 : S2;
26 S2: next_state = (serial_in) ? S3 : S0;
27 S3: next_state = (serial_in) ? S4 : S0;
28 S4: next_state = (serial_in) ? S1 : S0;
29 default: next_state = S0;
30 endcase
31 end
32
33 always_ff @(posedge clk) begin
34 detected <= (state == S4); // Sequence detected at S4
35 end
36 endmodule

289
Chapter 16 Problems with Solutions

Project 123: FSM for Vending Machine


Problem: Design an FSM to control a vending machine that accepts coins (1, 5,
and 10 units). The machine dispenses an item when the total amount reaches or
exceeds the price.
Solution:
1 module vending_machine (
2 input clk, reset,
3 input [3:0] coin, // Accept 1, 5, or 10 units
4 output reg dispense
5 );
6 typedef enum logic [2:0] {
7 S0 = 3’b000, // Initial state
8 S1 = 3’b001, // Total = 1
9 S2 = 3’b010, // Total = 5
10 S3 = 3’b011, // Total = 10
11 S4 = 3’b100 // Dispense
12 } state_t;
13
14 state_t state, next_state;
15 reg [3:0] total; // Keeps track of total amount inserted
16

17 always_ff @(posedge clk or posedge reset) begin


18 if (reset)
19 state <= S0;
20 else
21 state <= next_state;
22 end
23
24 always_comb begin
25 case(state)
26 S0: next_state = (coin == 1) ? S1 : (coin == 5) ? S2 :
(coin == 10) ? S3 : S0;
27 S1: next_state = (coin == 1) ? S2 : (coin == 5) ? S3 :
S4;
28 S2: next_state = (coin == 1) ? S3 : S4;
29 S3: next_state = (coin == 1) ? S4 : S4;
30 S4: next_state = S0; // Reset after dispensing
31 default: next_state = S0;
32 endcase
33 end
34
35 always_ff @(posedge clk) begin
36 total <= total + coin;
37 dispense <= (total >= 10); // Dispense item if total
reaches 10
38 end
39 endmodule 290
Chapter 16 Problems with Solutions

Project 124: FSM for Simple Elevator Control


Problem: Design an FSM for a simple elevator control system with 4 floors. The
elevator should respond to requests to move between floors.
Solution:
1 module elevator_controller (
2 input clk, reset,
3 input [1:0] floor_request, // Floor request (2-bit input)
4 output reg [1:0] current_floor
5 );
6 typedef enum logic [1:0] {
7 FLOOR0 = 2’b00,
8 FLOOR1 = 2’b01,
9 FLOOR2 = 2’b10,
10 FLOOR3 = 2’b11
11 } state_t;
12
13 state_t state, next_state;
14
15 always_ff @(posedge clk or posedge reset) begin
16 if (reset)
17 state <= FLOOR0;
18 else
19 state <= next_state;
20 end
21

22 always_comb begin
23 case(state)
24 FLOOR0: next_state = (floor_request == 2’b01) ? FLOOR1
:
25 (floor_request == 2’b10) ?
FLOOR2 :
26 (floor_request == 2’b11) ?
FLOOR3 : FLOOR0;
27 FLOOR1: next_state = (floor_request == 2’b00) ? FLOOR0
:
28 (floor_request == 2’b10) ?
FLOOR2 :
29 (floor_request == 2’b11) ?
FLOOR3 : FLOOR1;
30 FLOOR2: next_state = (floor_request == 2’b00) ? FLOOR0
:
31 (floor_request == 2’b01) ?
FLOOR1 :
32 (floor_request == 2’b11) ?
FLOOR3 : FLOOR2;
33 FLOOR3: next_state = (floor_request == 2’b00) ? FLOOR0
: 291
34 (floor_request == 2’b01) ?
FLOOR1 :
35 (floor_request == 2’b10) ?
FLOOR2 : FLOOR3;
36 default: next_state = FLOOR0;
37 endcase
38 end
39
40 always_ff @(posedge clk) begin
Chapter 16 Problems with Solutions

Project 125: FSM for Password Checker


Problem: Design an FSM-based password checker. The FSM should verify a 4-
character password (e.g., "1101") by transitioning through states based on the input
sequence.
Solution:
1 module password_checker (
2 input clk, reset,
3 input user_input,
4 output reg valid_password
5 );
6 typedef enum logic [2:0] {
7 S0 = 3’b000, // Initial state
8 S1 = 3’b001, // Input 1
9 S2 = 3’b010, // Input 2
10 S3 = 3’b011, // Input 3
11 S4 = 3’b100 // Valid password
12 } state_t;
13
14 state_t state, next_state;
15
16 always_ff @(posedge clk or posedge reset) begin
17 if (reset)
18 state <= S0;
19 else
20 state <= next_state;
21 end
22

23 always_comb begin
24 case(state)
25 S0: next_state = (user_input) ? S1 : S0;
26 S1: next_state = (user_input) ? S2 : S0;
27 S2: next_state = (user_input) ? S3 : S0;
28 S3: next_state = (user_input) ? S4 : S0;
29 S4: next_state = S4; // Stay in valid password state
30 default: next_state = S0;
31 endcase
32 end
33

34 always_ff @(posedge clk) begin


35 valid_password <= (state == S4); // Password is valid at
S4
36 end
37 endmodule

292
Chapter 16 Problems with Solutions

Project 126: FSM for Traffic Light with Pedestrian Button


Problem: Design an FSM-based traffic light controller with a pedestrian button.
The pedestrian light should turn green when requested and the system should handle
pedestrian and vehicle light transitions.
Solution:
1 module traffic_light_with_pedestrian (
2 input clk, reset, pedestrian_button,
3 output reg green, yellow, red, pedestrian
4 );
5 typedef enum logic [2:0] {
6 VEHICLE_RED = 3’b000,
7 VEHICLE_GREEN = 3’b001,
8 VEHICLE_YELLOW = 3’b010,
9 PEDESTRIAN_GREEN = 3’b011,
10 PEDESTRIAN_WAIT = 3’b100
11 } state_t;
12
13 state_t state, next_state;
14
15 always_ff @(posedge clk or posedge reset) begin
16 if (reset)
17 state <= VEHICLE_RED;
18 else
19 state <= next_state;
20 end
21
22 always_comb begin
23 case(state)
24 VEHICLE_RED: next_state = (pedestrian_button) ?
PEDESTRIAN_GREEN : VEHICLE_GREEN;
25 VEHICLE_GREEN: next_state = VEHICLE_YELLOW;
26 VEHICLE_YELLOW: next_state = VEHICLE_RED;
27 PEDESTRIAN_GREEN: next_state = PEDESTRIAN_WAIT;
28 PEDESTRIAN_WAIT: next_state = VEHICLE_GREEN;
29 default: next_state = VEHICLE_RED;
30 endcase
31 end
32

33 always_ff @(posedge clk) begin


34 case(state)
35 VEHICLE_RED: {red, yellow, green, pedestrian} = 4’
b1000;
36 VEHICLE_GREEN: {red, yellow, green, pedestrian} = 4’
b0010;
37 VEHICLE_YELLOW: {red, yellow, green, pedestrian} = 4’
b0100;
38
293 yellow, green, pedestrian} =
PEDESTRIAN_GREEN: {red,
4’b0001;
39 PEDESTRIAN_WAIT: {red, yellow, green, pedestrian} = 4’
b0100;
40 default: {red, yellow, green, pedestrian} = 4’b1000;
41 endcase
42 end
43 endmodule
Chapter 16 Problems with Solutions

Project 127: FSM for Traffic Light with Emergency Override


Problem: Design an FSM-based traffic light controller with an emergency override.
When the emergency override button is pressed, the traffic lights should turn red for
all directions except for one.
Solution:
1 module traffic_light_with_emergency (
2 input clk, reset, emergency_button,
3 output reg green, yellow, red
4 );
5 typedef enum logic [2:0] {
6 NORMAL = 3’b000,
7 EMERGENCY = 3’b001,
8 RED = 3’b010
9 } state_t;
10

11 state_t state, next_state;


12
13 always_ff @(posedge clk or posedge reset) begin
14 if (reset)
15 state <= NORMAL;
16 else
17 state <= next_state;
18 end
19
20 always_comb begin
21 case(state)
22 NORMAL: next_state = (emergency_button) ? EMERGENCY :
NORMAL;
23 EMERGENCY: next_state = RED;
24 RED: next_state = NORMAL;
25 default: next_state = NORMAL;
26 endcase
27 end
28
29 always_ff @(posedge clk) begin
30 case(state)
31 NORMAL: {red, yellow, green} = 3’b001;
32 EMERGENCY: {red, yellow, green} = 3’b100;
33 RED: {red, yellow, green} = 3’b000;
34 default: {red, yellow, green} = 3’b001;
35 endcase
36 end
37 endmodule

294
Chapter 16 Problems with Solutions

Predict the Output - Basic Logic Gate Operations


Problem: Given the following Verilog code, predict the output for the input values
of A = 1 and B = 0.
1 module logic_gates (
2 input A, B,
3 output AND_out, OR_out, XOR_out
4 );
5 assign AND_out = A & B;
6 assign OR_out = A | B;
7 assign XOR_out = A ^ B;
8 endmodule

Answer:

• AND_out = 0

• OR_out = 1

• XOR_out = 1

Predict the Output - Flip-Flop Behavior


Problem: Given the following Verilog code for a D flip-flop, predict the output Q
for the input D = 1 and clk changes from 0 to 1.
1 module d_flip_flop (
2 input clk, reset, D,
3 output reg Q
4 );
5 always_ff @(posedge clk or posedge reset) begin
6 if (reset)
7 Q <= 0;
8 else
9 Q <= D;
10 end
11 endmodule

Answer:

• At the positive edge of clk, the output Q will be 1 (since D = 1).

295
Chapter 16 Problems with Solutions

Predict the Output - Case Statement


Problem: Given the following Verilog code with a case statement, predict the
output for input_signal = 2.
1 module case_example (
2 input [1:0] input_signal,
3 output reg [3:0] output_signal
4 );
5 always_comb begin
6 case (input_signal)
7 2’b00: output_signal = 4’b0001;
8 2’b01: output_signal = 4’b0010;
9 2’b10: output_signal = 4’b0100;
10 2’b11: output_signal = 4’b1000;
11 default: output_signal = 4’b1111;
12 endcase
13 end
14 endmodule

Answer:

• For input_signal = 2 (2’b10), the output output_signal will be


4’b0100.

296
Chapter 16 Problems with Solutions

Predict the Output - Shift Register


Problem: Given the following Verilog code for a 4-bit shift register, predict the
output for D = 1 when the clock cycles twice.
1 module shift_register (
2 input clk, reset, D,
3 output reg [3:0] Q
4 );
5 always_ff @(posedge clk or posedge reset) begin
6 if (reset)
7 Q <= 4’b0000;
8 else
9 Q <= {Q[2:0], D}; // Shift left and insert D
10 end
11 endmodule

Answer:

• Initial state of Q = 4’b0000.

• After first clock cycle with D = 1, Q becomes 4’b0001.

• After second clock cycle with D = 1, Q becomes 4’b0011.

297
Chapter 16 Problems with Solutions

Predict the Output - Up/Down Counter


Problem: Given the following Verilog code for an up/down counter, predict the
output for count_direction = 1 (Up mode) and initial value Q = 3.
1 module counter (
2 input clk, reset, count_direction, // 1 for up, 0 for down
3 output reg [3:0] Q
4 );
5 always_ff @(posedge clk or posedge reset) begin
6 if (reset)
7 Q <= 4’b0000;
8 else if (count_direction)
9 Q <= Q + 1;
10 else
11 Q <= Q - 1;
12 end
13 endmodule

Answer:

• Starting value Q = 3.

• After one clock cycle in up mode, Q becomes 4.

• After two clock cycles in up mode, Q becomes 5.

298

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy