0
0
Verilogprogramming~15 mins

Always block sensitivity list in Verilog - Deep Dive

Choose your learning style9 modes available
Overview - Always block sensitivity list
What is it?
In Verilog, an always block runs code repeatedly based on changes in signals listed in its sensitivity list. The sensitivity list tells the simulator which signals to watch for changes to trigger the block. This helps model hardware behavior that reacts to inputs or clocks. Without it, the always block wouldn't know when to update its outputs.
Why it matters
The sensitivity list ensures that hardware simulation matches real circuits, which only react when inputs change. Without it, simulations could miss changes or run unnecessarily, causing incorrect behavior or slow simulation. This is crucial for designing reliable digital circuits that behave as expected in the real world.
Where it fits
Before learning always block sensitivity lists, you should understand basic Verilog syntax and signals (wires and regs). After this, you can learn about different types of always blocks (combinational vs sequential) and how to write correct hardware descriptions.
Mental Model
Core Idea
An always block runs only when signals in its sensitivity list change, mimicking hardware reacting to input changes.
Think of it like...
It's like a motion sensor light that turns on only when it detects movement in certain areas; the sensitivity list is the set of areas it watches.
┌───────────────────────────────┐
│          always block          │
│ ┌───────────────────────────┐ │
│ │ Sensitivity List: signals │ │
│ │  (e.g., a, b, clk)        │ │
│ └─────────────┬─────────────┘ │
│               │               │
│      Signal changes trigger   │
│      execution of the block   │
└───────────────────────────────┘
Build-Up - 7 Steps
1
FoundationWhat is an always block
🤔
Concept: Introduce the always block as a fundamental Verilog construct for describing behavior.
An always block is a piece of code that runs repeatedly during simulation. It models hardware that reacts to changes. For example: always @(a or b) begin y = a & b; end This block runs whenever 'a' or 'b' changes, updating 'y'.
Result
The output 'y' updates whenever inputs 'a' or 'b' change.
Understanding that always blocks describe hardware reactions is key to writing correct Verilog.
2
FoundationWhat is a sensitivity list
🤔
Concept: Explain the sensitivity list as the signals that trigger the always block to run.
The sensitivity list is the list of signals inside parentheses after '@' in an always block. It tells the simulator which signals to watch. For example: always @(clk or reset) begin // code end This block runs only when 'clk' or 'reset' changes.
Result
The always block triggers only on changes to signals in the sensitivity list.
Knowing the sensitivity list controls when code runs helps avoid unnecessary or missed updates.
3
IntermediateDifference between combinational and sequential sensitivity lists
🤔Before reading on: do you think sensitivity lists for combinational and sequential logic are the same or different? Commit to your answer.
Concept: Show how combinational always blocks list all inputs, while sequential blocks usually list only clock and reset.
Combinational logic depends on all inputs, so sensitivity lists include all signals read inside the block: always @(a or b or c) begin y = a & b | c; end Sequential logic runs on clock edges: always @(posedge clk or posedge reset) begin if (reset) y <= 0; else y <= d; end Here, only 'clk' and 'reset' are in the list.
Result
Combinational blocks react to any input change; sequential blocks react only to clock or reset edges.
Recognizing sensitivity list differences prevents simulation mismatches and hardware bugs.
4
IntermediateUsing wildcard '*' in sensitivity lists
🤔Before reading on: does using '*' in sensitivity lists always produce correct simulation results? Commit to your answer.
Concept: Introduce the '*' wildcard to automatically include all signals read in the block, simplifying combinational logic sensitivity lists.
Instead of listing every input, you can write: always @(*) begin y = a & b | c; end The '*' means 'all signals read inside this block'. This reduces errors from missing signals.
Result
The always block triggers on any input change used inside it, ensuring correct combinational behavior.
Using '*' helps avoid bugs from incomplete sensitivity lists and makes code easier to maintain.
5
AdvancedConsequences of incomplete sensitivity lists
🤔Before reading on: what happens if a signal used inside an always block is missing from its sensitivity list? Commit to your answer.
Concept: Explain how missing signals cause simulation mismatches and incorrect hardware behavior.
If a signal used inside the always block is not in the sensitivity list, the block won't run when that signal changes. For example: always @(a or b) begin y = a & b | c; // 'c' missing from list end Changes to 'c' won't trigger the block, so 'y' won't update correctly in simulation.
Result
Simulation results differ from real hardware, causing bugs that are hard to find.
Understanding this prevents subtle bugs that only appear during simulation, saving debugging time.
6
AdvancedSensitivity lists in SystemVerilog and modern tools
🤔
Concept: Discuss how SystemVerilog and modern simulators handle sensitivity lists, including automatic sensitivity and best practices.
SystemVerilog allows always_comb blocks that automatically infer sensitivity lists: always_comb begin y = a & b | c; end This avoids manual sensitivity lists and reduces errors. Modern tools support this and recommend it for combinational logic.
Result
More reliable simulation and cleaner code without manual sensitivity list errors.
Knowing modern features helps write safer, more maintainable hardware descriptions.
7
ExpertWhy sensitivity lists matter for synthesis and timing
🤔Before reading on: do sensitivity lists affect only simulation or also hardware synthesis? Commit to your answer.
Concept: Explain how sensitivity lists influence synthesis tools and timing analysis, not just simulation.
Sensitivity lists guide simulation triggers but synthesis tools infer hardware from code structure. However, incorrect sensitivity lists can hide bugs that cause synthesis mismatches. Also, sensitivity lists affect how simulators model timing and glitches, impacting verification accuracy.
Result
Correct sensitivity lists ensure simulation matches synthesized hardware behavior and timing.
Understanding this connection helps avoid costly hardware bugs and verification failures.
Under the Hood
The simulator monitors signals in the sensitivity list. When any listed signal changes value, the simulator schedules the always block to run. This mimics hardware where combinational logic reacts instantly to input changes, and sequential logic reacts on clock edges. Internally, the simulator uses event-driven simulation to efficiently update only affected blocks.
Why designed this way?
Sensitivity lists were designed to model real hardware behavior where circuits react only to input changes, not continuously. Early Verilog required manual lists to give designers control and efficiency. Later, automatic sensitivity was added to reduce human error. This design balances simulation speed and accuracy.
┌───────────────┐
│ Signal Change │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Sensitivity   │
│ List Check    │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│ Run always    │
│ block code   │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does an always block run continuously regardless of sensitivity list? Commit yes or no.
Common Belief:An always block runs all the time, ignoring the sensitivity list.
Tap to reveal reality
Reality:An always block runs only when signals in its sensitivity list change.
Why it matters:Believing this causes confusion about simulation behavior and leads to incorrect code assumptions.
Quick: Does using '*' in sensitivity lists guarantee correct simulation for all logic? Commit yes or no.
Common Belief:Using '*' always produces correct sensitivity lists and simulation results.
Tap to reveal reality
Reality:'*' works well for combinational logic but can cause issues if the block contains non-combinational constructs or delays.
Why it matters:Misusing '*' can hide bugs or cause simulation mismatches, especially in complex designs.
Quick: Do sensitivity lists affect hardware synthesis? Commit yes or no.
Common Belief:Sensitivity lists only affect simulation, not synthesis.
Tap to reveal reality
Reality:Sensitivity lists do not directly affect synthesis, but incorrect lists can hide bugs that cause synthesis mismatches.
Why it matters:Ignoring this can lead to hardware that behaves differently than simulation predicts.
Quick: Can you omit signals from sensitivity lists without any problem? Commit yes or no.
Common Belief:It's okay to omit some signals from sensitivity lists if you think they won't change often.
Tap to reveal reality
Reality:Omitting signals causes the always block not to run when those signals change, leading to incorrect simulation results.
Why it matters:This leads to subtle bugs that are hard to detect and fix.
Expert Zone
1
Sensitivity lists must include all signals read in combinational always blocks to avoid simulation mismatches, but synthesis tools infer hardware from code structure, not sensitivity lists.
2
Using always_comb in SystemVerilog automatically manages sensitivity lists, but legacy Verilog requires manual lists, so understanding both is important for mixed codebases.
3
Sensitivity lists influence simulation event scheduling and timing accuracy, affecting glitch modeling and verification of race conditions.
When NOT to use
Manual sensitivity lists are error-prone for complex combinational logic; use SystemVerilog's always_comb instead. For sequential logic, always use clock and reset edges explicitly. Avoid '*' in blocks with delays or non-blocking assignments to prevent simulation mismatches.
Production Patterns
In real projects, always_comb is preferred for combinational logic to avoid missing signals. Sequential always blocks list only clock and reset edges. Code reviews check sensitivity lists to prevent bugs. Simulation warnings help detect incomplete lists.
Connections
Event-driven simulation
Sensitivity lists are the triggers for event-driven simulation to run code blocks.
Understanding sensitivity lists clarifies how simulators efficiently update only affected parts of a design.
Reactive programming
Both sensitivity lists and reactive programming respond to changes in data or signals to trigger actions.
Knowing sensitivity lists helps grasp reactive programming concepts where code reacts automatically to data changes.
Human sensory perception
Sensitivity lists are like sensory receptors that detect changes and trigger responses.
This cross-domain link shows how systems, biological or digital, rely on detecting changes to act efficiently.
Common Pitfalls
#1Omitting signals from the sensitivity list in combinational always blocks.
Wrong approach:always @(a or b) begin y = a & b | c; // 'c' missing end
Correct approach:always @(a or b or c) begin y = a & b | c; end
Root cause:Not realizing that all signals read inside the block must be in the sensitivity list to trigger updates.
#2Using '*' in sensitivity list with non-combinational constructs causing simulation mismatches.
Wrong approach:always @(*) begin y <= a + b; // non-blocking assignment inside combinational block end
Correct approach:always @(a or b) begin y = a + b; // blocking assignment for combinational logic end
Root cause:Confusing blocking and non-blocking assignments and their impact on sensitivity and simulation.
#3Leaving sensitivity list empty or missing entirely in older Verilog code.
Wrong approach:always @() begin y = a & b; end
Correct approach:always @(a or b) begin y = a & b; end
Root cause:Misunderstanding that sensitivity lists cannot be empty and must include all relevant signals.
Key Takeaways
Always blocks run only when signals in their sensitivity list change, modeling hardware reactions.
Sensitivity lists must include all signals read inside combinational always blocks to ensure correct simulation.
Using '*' in sensitivity lists simplifies code but must be used carefully to avoid simulation errors.
Sequential always blocks typically list only clock and reset signals to trigger on edges.
Modern SystemVerilog features like always_comb automate sensitivity lists, reducing human error and improving reliability.