Lesson 09: Sequential Behavioral Modeling
Sequential behavioral modeling is used to describe digital circuits that store state. Unlike combinational logic, sequential logic does not depend only on current input values. Its behavior also depends on previously stored values, which are usually updated at clock edges.
In this lesson, we will study how to model sequential logic in Verilog using edge-triggered always blocks, registers, enable signals, and reset logic.
9.1 Introduction to Sequential Behavioral Modeling
Introduction to Sequential Behavioral Modeling
Sequential behavioral modeling is used to describe digital circuits that store information over time. Unlike combinational logic, whose outputs depend only on the current input values, sequential logic depends on both the current inputs and the previously stored internal state.
In Verilog, sequential circuits are commonly described using behavioral constructs that model registers, counters, and other state-holding elements. This modeling style is essential in modern digital design because many useful systems require memory and controlled state transitions.
What Is Sequential Logic?
Sequential logic is a type of digital logic in which the output is determined by:
- the current input values, and
- the previously stored value of the circuit.
This means sequential circuits contain memory elements. These memory elements allow the circuit to remember information from one moment to the next.
Common examples of sequential circuits include:
- Registers
- Counters
- Shift Registers
- Finite State Machines (FSMs)
Why Sequential Logic Is Important
Many practical digital systems cannot be implemented solely with combinational logic. A circuit often needs to remember a previous value, count clock pulses, or move through a series of control steps.
For example:
- A counter must remember its current count
- A register must store data until the next update
- An FSM must remember its current state
These functions require sequential logic.
Sequential Logic vs Combinational Logic
| Type | Depends On | Memory | Typical Example |
|---|---|---|---|
| Combinational Logic | Current inputs only | No | Multiplexer, decoder, comparator |
| Sequential Logic | Current inputs + previous state | Yes | Register, counter, FSM |
This lesson focuses on sequential logic, while the previous lesson focused on combinational logic.
Behavioral Modeling of Sequential Logic
In Verilog, sequential logic is usually modeled using an always block that is triggered by a clock edge.
always @(posedge clk) begin
// sequential logic
end
This structure means the circuit updates its stored value only when the clock transitions from low to high.
In real hardware, these models exhibit the behavior of flip-flops and registers.
Clock-Controlled Behavior
A key feature of sequential logic is that changes do not happen immediately when the input changes. Instead, the update occurs only at specific clock events.
This makes digital systems more organized and predictable because all state updates happen at well-defined times.
For this reason, sequential logic is often described as clocked logic.
Example: Simple Register
always @(posedge clk) begin
q <= d;
end
In this example:
- d is the input data,
- q is the stored output,
- The update happens only at the rising edge of the clock.
This is one of the simplest examples of sequential behavioral modeling.
Key Characteristics of Sequential Behavioral Modeling
- The circuit stores state.
- The output may depend on previous values.
- A clock signal is usually required.
- Changes occur at clock edges rather than immediately.
- The design often models registers, counters, and state machines.
Important Note
Sequential logic should not be confused with combinational logic. In particular:
- Combinational logic uses always @(*)
- Sequential logic uses edge-triggered blocks such as always @(posedge clk)
Using the wrong block type may result in hardware that is completely different from what the designer intended.
Summary
Sequential behavioral modeling is used to describe digital circuits that store and update state over time. It is essential to implement registers, counters, and finite state machines in Verilog.
In the following sections, we will study how sequential logic is modeled using clock edges, registers, non-blocking assignments, and reset signals.
9.2 Using always @(posedge clk) for Sequential Logic
Using always @(posedge clk) for Sequential Logic
In Verilog, sequential logic is commonly described using an always block that is triggered by a clock edge. The most common form is:
always @(posedge clk) begin
// sequential logic
end
This means the statements within the block are executed only when the clock changes from 0 to 1. This type of behavior models flip-flops and registers in digital hardware.
What Does posedge clk Mean?
The keyword posedge stands for positive edge, also called the rising edge.
A rising edge occurs when the clock changes from:
- 0 → 1
At this moment, the sequential circuit samples its inputs and updates its stored values.
Why Sequential Logic Uses Clock Edges
Sequential logic must update its stored values at well-defined times. A clock edge provides that timing reference.
Without a clock edge, the circuit would respond immediately to input changes, which would make it behave like combinational logic instead of sequential logic.
By updating only at clock edges, digital systems become:
- more predictable,
- easier to synchronize,
- easier to design and debug.
Basic Example: A Simple Register
always @(posedge clk) begin
q <= d;
end
In this example:
- d is the input value,
- q is the stored output,
- q changes only when the rising clock edge occurs.
If the input d changes between clock edges, the output q does not change immediately.
Sequential Logic Does Not Update Immediately
This is one of the most important differences between combinational and sequential logic.
- In combinational logic, output changes immediately when input changes.
- In sequential logic, output changes only at the clock edge.
Therefore, even if the input changes many times during one clock period, the register updates only at the active edge.
Comparing Combinational and Sequential Blocks
| Logic Type | Typical Block | Trigger |
|---|---|---|
| Combinational Logic | always @(*) | Any input change |
| Sequential Logic | always @(posedge clk) | Rising clock edge |
This distinction is fundamental in Verilog design. Choosing the wrong type of always block will produce the wrong hardware.
Another Common Edge-Triggered Form
In some cases, sequential logic may use the falling edge of the clock:
always @(negedge clk) begin
q <= d;
end
The keyword negedge stands for negative edge, or falling edge.
However, in most introductory FPGA design, the rising edge posedge clk is used as the standard form.
Common Mistake: Using always @(*) for Sequential Logic
// Incorrect
always @(*) begin
q <= d;
end
This is incorrect because there is no clock edge. The circuit would not behave like a proper register.
Sequential logic must use an edge-triggered sensitivity list.
Design Guidelines
- Use always @(posedge clk) for standard sequential logic.
- Use clock edges to model register behavior.
- Do not use always @(*) for sequential circuits.
- Remember that sequential outputs do not change immediately when inputs change.
Summary
The always @(posedge clk) block is the standard way to describe sequential logic in Verilog. It models circuits that store state and update only at clock edges.
In the next section, we will examine registers and state storage in more detail.
9.3 Registers and State Storage
Registers and State Storage
Registers are the fundamental building blocks of sequential logic. They are used to store data and represent the internal state of a digital circuit.
In behavioral modeling, registers are described using edge-triggered always blocks and are updated at clock edges.
What Is a Register?
A register is a storage element that holds a value from one clock cycle to the next.
It can be viewed as a group of flip-flops that store binary data.
In sequential logic, registers are used to:
- store intermediate results,
- hold system state,
- synchronize data between clock cycles.
Basic Register Model
always @(posedge clk) begin
q <= d;
end
In this model:
- d is the input data,
- q is the stored output,
- The value of q updates only at the rising edge of the clock.
This represents a D flip-flop, one of the most important elements in digital design.
State Storage Concept
The value stored in a register represents the system's state.
At any given time:
- The current state is stored in the register,
- The next state is computed based on the inputs and the current state
- The register updates to the next state at the clock edge
This concept is essential for understanding more complex designs, such as finite-state machines (FSMs).
Example: Register Holding Its Value
always @(posedge clk) begin
q <= q;
end
In this case, the register keeps its current value.
This behavior is called holding state. It is a normal and expected behavior in sequential logic.
Register with Conditional Update
always @(posedge clk) begin
if (en)
q <= d;
end
In this design:
- If en = 1, the register loads new data.
- If en = 0, the register holds its previous value.
This is a very common structure in practical designs.
Important Difference from Latch Behavior
It is important to distinguish register behavior from latch behavior:
- A register updates only at clock edges.
- A latch updates whenever its enable condition is active.
Even though a register can hold its value, it is still a clocked element and does not behave like a latch.
Multi-bit Registers
Registers can store multiple bits of data:
reg [7:0] q;
always @(posedge clk) begin
q <= d;
end
In this example, the register stores 8-bit data.
Key Characteristics of Registers
- Registers store data between clock cycles.
- They update only at clock edges.
- They represent a system's internal state.
- They are implemented using flip-flops in hardware.
Design Guidelines
- Use edge-triggered blocks to model registers.
- Use non-blocking assignment for register updates (covered in the next section).
- Clearly distinguish between input signals and stored state.
Summary
Registers are the core elements of sequential logic. They store values and define the system's state.
Understanding how registers work is essential for designing counters, pipelines, and finite state machines.
In the next section, we will examine why non-blocking assignment is required when modeling sequential logic.
9.4 Non-blocking Assignment (<=) in Sequential Logic
Non-blocking Assignment (<=) in Sequential Logic
In sequential behavioral modeling, the recommended assignment operator is <=, known as the non-blocking assignment operator.
Non-blocking assignment is used because sequential logic models registers and flip-flops, which update their stored values at clock edges. In real hardware, multiple registers triggered by the same clock edge update together. Non-blocking assignment matches this behavior correctly.
Why Non-blocking Assignment Is Needed
In a sequential circuit, several registers may be updated at the same clock edge. All of them should behave as if they sample their inputs first and then update their outputs together.
The non-blocking assignment operator <= models this behavior.
always @(posedge clk) begin
q <= d;
end
In this example, the register output q updates at the rising edge of the clock using the value of d sampled at that edge.
Basic Rule
In RTL design:
- Use = for combinational logic.
- Use <= for sequential logic.
This is one of the most important coding rules in Verilog.
Blocking vs. Non-Blocking Assignment Comparison
The two procedural assignment operators behave differently:
| Assignment Type | Symbol | Typical Usage | Behavior |
|---|---|---|---|
| Blocking Assignment | = | Combinational Logic | Executes immediately, line by line |
| Non-blocking Assignment | <= | Sequential Logic | Schedules update to occur together at the end of the time step |
Comparison Example
Consider the following two examples:
// Using blocking assignment
always @(posedge clk) begin
a = b;
b = a;
end
// Using non-blocking assignment
always @(posedge clk) begin
a <= b;
b <= a;
end
These two descriptions do not produce the same behavior.
Behavior of Blocking Assignment
In the blocking version:
- The first statement executes immediately: a = b
- The second statement then uses the new value of a
As a result, both registers may end up holding the same value.
This is usually not the intended hardware behavior for two registers triggered by the same clock.
Behavior of Non-blocking Assignment
In the non-blocking version:
- Both right-hand side values are evaluated first.
- The updates to a and b occur together.
This matches the behavior of real hardware registers sharing the same clock.
Waveform Interpretation
In waveform analysis, the difference between blocking and non-blocking assignment is very important.
With non-blocking assignment:
- The old values are sampled at the clock edge.
- The register outputs update together after that edge.
This means the waveform reflects true parallel register updates.
With blocking assignment:
- The first assignment may affect the second statement immediately
- The simulation may no longer reflect real register behavior
Therefore, when students observe waveforms of sequential logic, they should expect non-blocking assignments to produce behavior that matches edge-triggered state updates.
Example: Shift Register
A shift register clearly shows why non-blocking assignment is necessary:
// Correct
always @(posedge clk) begin
q2 <= q1;
q1 <= din;
end
In this design:
- q1 receives the new input,
- q2 receives the old value of q1.
This is the expected hardware behavior.
If blocking assignments were used, the shift operation could be simulated incorrectly.
Common Mistake
// Incorrect for sequential logic
always @(posedge clk) begin
q = d;
end
This may appear to work in simple cases, but it is not the recommended RTL coding style. In more complex sequential circuits, using blocking assignment can produce incorrect simulation behavior.
Exam-Focused Key Points
- Sequential logic should use <=.
- Combinational logic should use =.
- Blocking assignment executes immediately.
- Non-blocking assignment models parallel register updates.
- Using the wrong assignment type is a common exam and lab mistake.
Recommended Coding Practice
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
This is the standard and recommended style for sequential RTL modeling.
Summary
Non-blocking assignment <= is the correct assignment type for sequential logic because it models how hardware registers update at clock edges.
Understanding the difference between blocking and non-blocking assignment is essential for writing correct RTL code and interpreting waveforms properly.
9.5 Register with Enable
Register with Enable
In many practical digital designs, a register should not always update its value at every clock edge. Instead, it should update only when a control signal is active.
This behavior is implemented using an enable signal. A register with enable updates its value only when the enable signal is asserted. Otherwise, it keeps its previous value.
Basic Concept
A register with enable behaves as follows:
- If enable is active → load new data
- If enable is inactive → hold current value
Basic Verilog Model
always @(posedge clk) begin
if (en)
q <= d;
end
In this design:
- When en = 1, the register updates with the value of d.
- When en = 0, the register keeps its previous value.
Hold Behavior (Important Concept)
When the enable signal is not active, the register does not update. Instead, it keeps its current value.
This is called hold behavior.
It is important to understand that this does not create a latch.
- The register is still updated only at clock edges.
- The value is stored in a flip-flop, not a latch.
Therefore, holding a value in a clocked block is normal and expected behavior.
Expanded Form (Explicit Hold)
The same behavior can be written more explicitly:
always @(posedge clk) begin
if (en)
q <= d;
else
q <= q;
end
However, the else branch is usually omitted, because the register automatically holds its value.
Register with Enable and Reset
In practical designs, registers often include both enable and reset signals:
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else if (en)
q <= d;
end
In this design:
- If rst = 1, the register is reset.
- If rst = 0 and en = 1, the register updates.
- If both are inactive, the register holds its value.
Practical Example: Data Load Control
A register with enable is commonly used to control when data is loaded:
always @(posedge clk) begin
if (load)
data_reg <= data_in;
end
In this example, new data is loaded only when load is active.
Design Guidelines
- Use enable signals to control when registers update.
- Do not force unnecessary assignments when holding values.
- Use non-blocking assignment <=.
- Understand that holding a value is normal for sequential logic.
Common Mistake
Some students mistakenly believe that the following code creates a latch:
always @(posedge clk) begin
if (en)
q <= d;
end
This is incorrect. Since the block is edge-triggered, the circuit is still a register.
The value is simply held between clock edges.
Exam-Focused Key Points
- Register with enable updates only when enable is active.
- Holding a value does not mean a latch is created.
- Sequential logic naturally supports state retention.
- Enable control is commonly used in FSM and datapath design.
Summary
A register with enable allows controlled data updates in sequential circuits. It is widely used in practical digital systems.
Understanding enable-controlled registers is essential for designing FSMs, pipelines, and control logic.
9.6 Sequential Logic with Reset
Sequential Logic with Reset (Synchronous vs Asynchronous)
In sequential logic design, a reset signal is used to initialize registers to a known state. This ensures that the circuit starts in a predictable state when power is applied or a reset event occurs.
In Verilog, reset logic is typically implemented inside an edge-triggered always block. There are two main types of reset:
- Synchronous Reset
- Asynchronous Reset
1. Synchronous Reset
A synchronous reset is applied only at the clock edge. The register updates its value at the clock edge.
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
In this design:
- The reset is checked only at the rising edge of the clock.
- The register will not reset immediately when the rst changes.
This behavior makes synchronous reset easier to control and integrate with the rest of the design.
2. Asynchronous Reset
An asynchronous reset takes effect immediately, without waiting for a clock edge.
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
In this design:
- The register resets immediately when rst is asserted.
- No clock edge is required for the reset to take effect.
This is useful when a system must be reset quickly and independently of the clock.
Comparison: Synchronous vs Asynchronous Reset
| Feature | Synchronous Reset | Asynchronous Reset |
|---|---|---|
| Trigger | Clock edge | Reset signal edge |
| Response Time | Delayed (wait for clock) | Immediate |
| Design Complexity | Simpler timing | Requires careful handling |
| Typical Use | General FPGA design | FSM initialization, system reset |
Rule 4: Reset Usage in Sequential Logic
Rule 4:
All registers that require a known initial state must be initialized using reset logic.
Since initial blocks are not reliably supported in FPGA synthesis, reset signals must be used to define startup behavior.
Why Reset Is Important
- Ensures predictable startup behavior
- Prevents unknown states (X values)
- Required for FSM initialization
Common Mistakes
1. Missing Reset
// Risky
always @(posedge clk) begin
q <= d;
end
Without a reset, the initial value of q is undefined.
2. Mixing Reset Types Incorrectly
Inconsistent reset usage across modules can cause design issues.
3. Incorrect Sensitivity List
// Incorrect
always @(posedge clk or rst) begin
...
end
The reset edge must be explicitly defined as posedge or negedge.
Recommended Coding Template
Synchronous Reset Template:
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
Asynchronous Reset Template:
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
Design Guidelines
- Use reset to initialize all critical registers.
- Use synchronous reset for most FPGA designs.
- Use an asynchronous reset when an immediate reset is required.
- Keep reset logic simple and consistent across the design.
Exam-Focused Key Points
- Reset defines initial register values.
- Synchronous reset waits for the clock edge.
- Asynchronous reset acts immediately.
- initial is not reliable for synthesis.
Summary
Reset logic is essential in sequential design to ensure predictable behavior. Understanding the difference between synchronous and asynchronous reset is critical for designing reliable FPGA systems.
A proper reset design is especially important for registers, counters, and finite state machines.
9.7 Recommended Coding Style for Sequential Logic
Recommended Coding Style for Sequential Logic
After learning how sequential logic uses clock edges, registers, non-blocking assignments, enable signals, and reset logic, it is important to follow a consistent coding style.
A good coding style improves correctness, readability, and debugging efficiency. It also helps students write synthesizable RTL code that matches the intended hardware behavior.
1. Use Edge-Triggered always Blocks
Sequential logic should be described using an edge-triggered always block.
// Recommended
always @(posedge clk) begin
q <= d;
end
If asynchronous reset is required, include the reset edge explicitly:
// Recommended
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
2. Use Non-blocking Assignment
In sequential logic, always use <= to model register updates correctly.
// Correct
q <= d;
Do not use blocking assignment = in sequential RTL code unless there is a very specific reason and the designer fully understands the consequences.
3. Keep Sequential and Combinational Logic Separate
A clean RTL design separates:
- sequential logic in edge-triggered blocks,
- combinational logic in always @(*) blocks.
This separation makes the code easier to understand and reduces the risk of design errors.
4. Use Reset Only Where Needed
Registers that must start from a known value should include reset logic. Other registers may not need to be reset if their values are overwritten before use.
In general:
- Use reset for FSM state registers, counters, and control flags.
- Use synchronous reset as the default choice in FPGA design.
- Use asynchronous reset only when immediate reset behavior is required.
5. Use Enable Signals Clearly
When a register updates only under a condition, place the enable logic clearly inside the sequential block.
always @(posedge clk) begin
if (en)
q <= d;
end
This indicates that the register updates only when the enable condition is active. Otherwise, it holds its previous value.
6. Use Clear Priority Order in Sequential Logic
When reset and enable are both used, write them in a clear priority order. A common and recommended order is:
- reset first,
- enable second,
- normal update last.
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else if (en)
q <= d;
end
7. Keep the Code Clean and Consistent
- Indent conditional branches clearly.
- Use meaningful signal names such as clk, rst, en, and q.
- Use a consistent reset style throughout the design.
- Avoid mixing multiple coding styles in one module without a reason.
8. Standard Sequential Coding Templates
Template A: Simple Register
always @(posedge clk) begin
q <= d;
end
Template B: Register with Enable
always @(posedge clk) begin
if (en)
q <= d;
end
Template C: Register with Synchronous Reset
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
Template D: Register with Synchronous Reset and Enable
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else if (en)
q <= d;
end
Template E: Register with Asynchronous Reset
always @(posedge clk or posedge rst) begin
if (rst)
q <= 1'b0;
else
q <= d;
end
9. Final Recommended Sequential Coding Template
For most student-level FPGA designs, the following template is a strong default choice:
// Recommended sequential RTL template
always @(posedge clk) begin
if (rst)
q <= 1'b0;
else if (en)
q <= d;
end
This template is clean, synthesizable, easy to read, and suitable for many common register-based designs.
10. Exam-Focused Key Points
- Use always @(posedge clk) for sequential logic.
- Use <= for sequential assignments.
- Separate sequential logic from combinational logic.
- Put reset first in the priority order.
- Holding a value in a clocked block does not mean latch inference.
Summary
A consistent coding style is essential for writing correct sequential RTL code. By using edge-triggered blocks, non-blocking assignments, proper reset logic, and clear enable structure, designers can create reliable and maintainable sequential circuits.
These coding patterns will be used repeatedly in later topics, such as counters, finite-state machines, and control logic.
9.8 Common Mistakes
Common Mistakes
This section summarizes the most common mistakes in sequential behavioral modeling. These errors frequently appear in exams, quizzes, and practical FPGA labs.
Students should be able to quickly identify incorrect designs and apply the correct coding style.
1. Using Blocking Assignment in Sequential Logic
// Exam Trap
always @(posedge clk) begin
q = d;
end
Problem: Incorrect assignment type
Result: Simulation mismatch with real hardware
Fix:
always @(posedge clk) begin
q <= d;
end
2. Using always @(*) for Sequential Logic
// Exam Trap
always @(*) begin
q <= d;
end
Problem: Missing clock edge
Result: Not a register (incorrect hardware)
Fix:
always @(posedge clk) begin
q <= d;
end
3. Incorrect Reset Sensitivity List
// Exam Trap
always @(posedge clk or rst) begin
if (rst)
q <= 0;
end
Problem: Missing edge definition
Fix:
always @(posedge clk or posedge rst) begin
if (rst)
q <= 0;
end
4. Missing Reset for Critical Registers
// Risky design
always @(posedge clk) begin
state <= next_state;
end
Problem: Initial state is undefined
Result: FSM may start in an unknown state
Fix:
always @(posedge clk or posedge rst) begin
if (rst)
state <= IDLE;
else
state <= next_state;
end
5. Confusing Hold Behavior with Latch
// Correct sequential logic
always @(posedge clk) begin
if (en)
q <= d;
end
Misconception: "Missing else creates a latch."
Correct Understanding:
- This is a register with enable.
- Holding value is normal behavior in sequential logic.
- No latch is created because the block is edge-triggered.
6. Mixing Blocking and Non-blocking Incorrectly
// Exam Trap
always @(posedge clk) begin
a = b;
b <= a;
end
Problem: Inconsistent assignment behavior
Fix:
always @(posedge clk) begin
a <= b;
b <= a;
end
7. Incorrect Priority Order (Reset vs Enable)
// Problematic order
always @(posedge clk) begin
if (en)
q <= d;
else if (rst)
q <= 0;
end
Problem: Reset may be ignored when enable is active
Fix:
always @(posedge clk) begin
if (rst)
q <= 0;
else if (en)
q <= d;
end
8. Expecting Immediate Output Change
Common Mistake:
- Assuming output changes immediately when input changes
Correct Behavior:
- Sequential outputs update only at clock edges
9. Using the initial for Hardware Initialization
// Not reliable for synthesis
initial begin
q = 0;
end
Problem: Not supported in many synthesis flows
Fix: Use reset logic
10. Quick Exam Checklist
Before submitting your design, check:
- Is always @(posedge clk) used?
- Is <= used?
- Is the reset implemented correctly?
- Is the reset placed before enable?
- Is the behavior edge-triggered?
- Are you mistakenly expecting immediate updates?
Summary
Most sequential logic errors are not syntax errors but misunderstandings of timing and update behavior.
By recognizing these patterns, students can quickly detect and correct incorrect RTL code.
These concepts are especially important when designing registers, counters, and finite state machines.
9.9 Summary
Summary
In this lesson, we introduced sequential behavioral modeling in Verilog. Unlike combinational logic, sequential logic stores data and updates its outputs at clock edges.
This type of modeling is essential for designing digital systems that require memory and controlled state transitions.
Key Concepts Review
- Sequential logic depends on both current inputs and previously stored values.
- Registers store data and represent a system's internal state.
- Updates occur at clock edges using the always @(posedge clk).
- Non-blocking assignment <= must be used for sequential logic.
- Enable signal control when registers update.
- Reset signals define the initial state of registers.
The Core Idea: Register = State
The most important concept from this lesson is:
A register stores the system's current state.
At each clock cycle:
- The current state is stored in registers
- The next state is computed using combinational logic
- The register updates to the next state at the clock edge
From Registers to State Machines
Many real-world digital systems require a sequence of operations. These systems move from one state to another based on inputs and conditions.
This type of behavior is described using a Finite State Machine (FSM).
An FSM is built using:
- A register to store the current state
- Combinational logic to determine the next state
- Combinational logic to generate outputs
Basic FSM Structure in Verilog
// State register (sequential logic)
always @(posedge clk or posedge rst) begin
if (rst)
state <= S_IDLE;
else
state <= next_state;
end
// Next-state logic (combinational logic)
always @(*) begin
case (state)
IDLE: next_state = S_START;
START: next_state = S_IDLE;
default: next_state = S_IDLE;
endcase
end
This structure combines both sequential and combinational logic.
How Lessons 08 and 09 Work Together
| Lesson | Focus | Role in FSM |
|---|---|---|
| Lesson 08 | Combinational Logic | Next-state logic and output logic |
| Lesson 09 | Sequential Logic | State register |
Together, these two lessons provide the complete foundation for designing FSMs.
Important Design Insight
A digital system can be viewed as:
- Combinational Logic → computes next values
- Registers → store current state
This separation is a key principle in modern RTL design.
What You Should Be Able to Do Now
- Write sequential logic using always @(posedge clk)
- Use non-blocking assignment correctly
- Design registers with enable and reset
- Understand how the state is stored and updated
Looking Ahead
In the next lesson, we will study Finite State Machines (FSMs), which combine sequential and combinational logic to control the behavior of complex systems.
You will learn how to:
- design state diagrams,
- convert them into Verilog code,
- build complete control logic systems.
The concepts of registers, clock edges, and non-blocking assignments introduced in this lesson will be used extensively in FSM design.