Loading header...

Exercise: Find and Fix a Timing Failure

This exercise teaches a core FPGA skill: when timing fails, do not panic. Read the path, understand the logic depth, and change the architecture.

Learning Objectives

You will:

  • recognize a long combinational path;
  • understand why pipelining improves timing;
  • preserve functional behavior while adding latency;
  • verify the new latency in simulation.

Prerequisites

  • Sequential logic and testbenches.
  • Basic static timing concepts: clock period, data path delay, slack.
  • Any FPGA tool or open-source flow that reports timing.

Task

Start with an intentionally heavy one-cycle datapath:

module slow_mix (
    input  wire        clk,
    input  wire [15:0] a,
    input  wire [15:0] b,
    input  wire [15:0] c,
    input  wire [15:0] d,
    output reg  [31:0] y
);
    always @(posedge clk) begin
        y <= ((a * b) + (c * d)) ^ ((a + c) * (b + d));
    end
endmodule

At a high clock frequency this may fail timing because multiplication, addition, XOR, and routing all sit between two clock edges.

Buildable Pipelined Version

Split the work across stages:

module pipelined_mix (
    input  wire        clk,
    input  wire [15:0] a,
    input  wire [15:0] b,
    input  wire [15:0] c,
    input  wire [15:0] d,
    output reg  [31:0] y
);
    reg [31:0] p0;
    reg [31:0] p1;
    reg [16:0] s0;
    reg [16:0] s1;
    reg [33:0] p2;

    always @(posedge clk) begin
        p0 <= a * b;
        p1 <= c * d;
        s0 <= a + c;
        s1 <= b + d;

        p2 <= s0 * s1;
        y  <= (p0 + p1) ^ p2[31:0];
    end
endmodule

This version has extra latency, but each stage has less work per cycle.

Expected Behavior

The output of pipelined_mix should match the original expression after pipeline latency. It will not match in the same cycle.

title "Illustrative pipeline latency"
time start=0 end=8 unit=cycles divisions=8

CLK: square label="clk" low=0 high=1 duty=50 cycles=4 unit=logic color=#2563eb
IN: pulse label="input sample" low=0 high=1 at=1 width=1 unit=logic color=#dc2626
STAGE1: pulse label="stage 1 result" low=0 high=1 at=2 width=1 unit=logic color=#7c3aed
OUT: pulse label="output valid later" low=0 high=1 at=3 width=1 unit=logic color=#16a34a

marker LAT at=3 label="latency"

Verification Steps

  1. Simulate the original and pipelined versions with the same input stream.
  2. Add a queue or shift register in the testbench for expected results.
  3. Compare pipelined_mix.y against the delayed expected value.
  4. Implement both versions with the same clock constraint.
  5. Compare timing reports.
  6. Confirm the pipelined version has better slack.

Common Failure Symptoms

Symptom Likely cause
Pipelined output is numerically wrong stage alignment bug
Output is right but one cycle early/late expected-value delay mismatch
Timing still fails multiplier too large, DSP not inferred, or clock too aggressive
Resource use increases normal cost of pipeline registers

Debugging Guidance

  • Add valid signals through the pipeline.
  • Name each stage clearly.
  • Check bit widths after multiplication and addition.
  • Read the timing path: identify whether the multiplier, adder, or routing dominates.
  • Do not add random registers without preserving data alignment.

Extension Challenge

Add valid_in and valid_out signals so the pipeline can process bursts and idle cycles. Then update the testbench to compare only when valid_out is high.

Explained Solution

Pipelining works because timing is checked between adjacent registers. The original version puts several arithmetic operations in one cycle. The pipelined version places registers between operations, reducing the maximum combinational delay per stage. The tradeoff is latency: the result appears later, but throughput can still be one result per clock after the pipeline fills.

Summary

Timing failures are design feedback. Read the critical path, reduce logic depth, use dedicated FPGA resources, and verify any added latency. Pipelining is one of the most important FPGA techniques because it improves frequency without reducing throughput.

Next: Exercise: Design an Asynchronous FIFO.

Further Reading

  • Vendor timing closure methodology guides
  • DSP block inference guides
  • Project F tutorials on pipelining

Mind Map

mindmap root((Timing Exercise)) Core concept Find critical path Add pipeline stage Preserve behavior Latency changes Applications Applications STA practice Pipeline design Design checks Checks Slack positive Testbench updated Common mistakes Common mistakes Ignoring latency Breaking reset alignment