Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Concept Map
  • How to Read the Diagrams
  • Part 0: What Is a Protocol?10
  • Part 1: Timing and Clocking11
  • Part 2: Encoding and Framing12
  • Part 3: Handshakes13
  • Part 4: Flow Control17
  • Part 5: Transactions19
  • Part 6: Concurrency and Performance17
  • Part 7: Ordering13
  • Part 8: Sharing and Arbitration12
  • Part 9: Deadlock and Liveness13
  • Part 10: Reliability and Recovery20
  • Part 11: Bring-Up and Link Management10
  • Part 12: Power8
  • Part 13: Shared State and Coherence9
  • Part 14: Security and Isolation7
  • Part 15: Specifying and Verifying11
  • Part 16: Protocols Dissected17
  • Part 17: Capstones5
    • Read Any Spec
    • The Protocol Comparison Matrix
    • Design a Protocol
    • Design Review
    • Debug the Hang
  • Part 18: Interview Preparation6
Loading lesson

‹Part 17: Capstones
  1. Topics
  2. First Principles of Hardware Protocols
  3. Part 17: Capstones
  4. Debug the Hang

Part 17 · Capstones · Senior (S)

Debug the Hang

Capstone 5: a waveform mystery. A device with a sleep handshake serves its first request and never serves the second. Apply the debug method from Parts 9 and 15 to find the root cause before reading the solution. Runnable design included.

On this page

    Note

    Level: Senior (S) · Answers: Can you apply all of it?

    Before this: A Waveform Debug Method, Low-Power Handshakes

    A bug report arrives: "After the first transfer, the device stops responding. Happens every time on the power-saving build, never on the performance build." The design below reproduces it. It has a requester, a device that takes two cycles per request, and a power controller using the request/accept/deny sleep handshake from Part 12. Everything looks reasonable. One request never completes.

    Can you find the root cause of a hang from the waveform alone?

    The design

    tb.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    // Capstone: debug the hang. A requester sends two requests to a device over a
    // valid/ready interface. A power controller puts the device to sleep with the
    // step 11 handshake when the device reports no activity for two cycles, and wakes
    // it when the device reports activity again. The first request is served; the
    // second never is. Find out why from the waveform before reading the solution.
    // The checker reports whether the hang reproduced.
    module tb;
      logic clk = 0;
      always #5 clk = ~clk;
      initial begin $dumpfile("wave.vcd"); $dumpvars(0, tb); end
    
      int cyc = 0;
      always @(posedge clk) cyc <= cyc + 1;
    
      // Requester: request 1 in cycle 1, request 2 in cycle 8; holds vld until accepted
      logic vld = 0;
      logic rdy;
      always @(posedge clk) begin
        if ((cyc == 1 || cyc == 8) && !vld) vld <= 1;
        else if (vld && rdy) vld <= 0;
      end
    
      // Device: busy for 2 cycles per request; cannot accept while asleep or busy
      logic busy = 0, slp_acc = 0, slp_req = 0, active;
      logic [1:0] work = 0;
      always_comb begin
        rdy    = !slp_acc && !busy;
        active = busy;                                 // activity reported to the controller
      end
      always @(posedge clk) begin
        if (vld && rdy) begin busy <= 1; work <= 1; end
        else if (busy) begin if (work == 0) busy <= 0; else work <= work - 1; end
        // sleep handshake (device side): accept when idle and nothing is arriving
        if (slp_req && !slp_acc && !busy && !vld) slp_acc <= 1;
        else if (!slp_req) slp_acc <= 0;
      end
    
      // Power controller: sleep after 2 idle cycles, wake on activity
      logic [1:0] idle = 0;
      always @(posedge clk) begin
        idle <= active ? 0 : (idle == 3 ? 3 : idle + 1);
        if (!slp_req && idle >= 2) slp_req <= 1;
        else if (slp_req && slp_acc && active) slp_req <= 0;
      end
    
      int served = 0, stuck = 0;
      always @(posedge clk) begin
        if (vld && rdy) served++;
        if (vld && !rdy) stuck++;
      end
      initial begin
        #300;
        if (served == 1 && stuck > 15 && slp_acc)
          $display("PASS: hang reproduced: request 2 has waited %0d cycles while the device sleeps", stuck);
        else $display("FAIL: served %0d stuck %0d asleep %0d", served, stuck, slp_acc);
        $finish;
      end
    endmodule

    When run, it prints a PASS line confirming the hang reproduced: request 2 waits for ever while the device sleeps.

    The waveform

    Apply the method (lesson 15.10): find the stuck handshake, the missing condition, the state behind it, and the first cycle that state went wrong. Write your answer before opening the solution.

    Solution

    Check yourself Step 1: which handshake is stuck?

    From slot 8, vld is high and rdy is low, for ever: request 2 is never accepted.

    Check yourself Step 2: which condition keeps rdy low?

    rdy = !slp_acc && !busy. busy is 0, so slp_acc is the cause: the device has been asleep since slot 5.

    Check yourself Step 3: why does the device stay asleep?

    It wakes only when the controller drops slp_req, which happens only when active is high. active stays 0 throughout.

    Check yourself Step 4: the root cause?

    active = busy reports only work the device is doing, not work waiting at its input. A request that arrives after the device accepted sleep is invisible to the controller, so nobody wakes the device. Request 1 arrived before any sleep request and was served normally; the controller's request (slot 2) was accepted only in slot 5, once the device was idle, and from then on any new request is stranded.

    Check yourself Step 5: the fix?

    Report pending input as activity: active = busy || vld (the role of AMBA's QACTIVE, fact A22). The controller then sees request 2, drops slp_req, the device wakes and serves it. Add an assertion: vld && slp_acc must lead to !slp_acc within a bounded number of cycles.

    What this capstone used

    • Part 3: the valid/ready handshake and what stalls it.

    • Part 9: a liveness failure that no safety check caught.

    • Part 12: the sleep handshake and the wake path (lessons 12.4, 12.6).

    • Part 15: the debug method and a bounded-liveness assertion.

    Why this matters

    Senior lens. Wake paths fail more often than sleep paths, because tests exercise entering low power far more than leaving it with work arriving at the worst moment. For every low-power state, check that every input that can carry new work is part of the wake condition, and assert bounded wake-up whenever work is pending.

    Key takeaways

    • Follow the wait: stuck handshake, missing condition, the state behind it, the first wrong cycle.

    • Here, activity reporting ignored pending input, so nothing could wake the sleeping device.

    • Every input that carries work must be part of the wake condition; assert bounded wake-up.

    Keep going

    Next: Part 18: Interview Preparation. Can you explain it under pressure?

    Related topics

    • Part 17 overview: Capstones

    Previous

    228 / 234

    Next: Part 18: Interview Preparation

    Up next

    Up nextPart 18: Interview Preparation

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Read Any Spec
    • The Protocol Comparison Matrix
    • Design a Protocol
    clkvldrdybusyactiveslp_reqslp_acc
    Simulation output: request 1 is served; the device then sleeps; request 2 arrives and is never accepted.