Skip to main content...
S2 · Verilog RTL Design
25 min

Day 73: Peripheral: GPIO with interrupt lines

GPIO seems trivial until you add interrupts — edge detection and synchronization are where the real design lives.

Peripheral: GPIO with interrupt lines

GPIO (general-purpose I/O) gives software direct pins: a direction register (input/output per pin), an output register, and an input register. The interesting part is interrupts: pins configured to raise an interrupt on a rising edge, falling edge, or level. That needs synchronizing the async pin (Stage 0 metastability!) and then edge detection on the synchronized value.

GPIO input synchronizer + rising-edge interrupt
// synchronize the async pin, then detect a rising edge
reg [1:0] sync;
reg       pin_d;
always @(posedge clk) begin
    sync  <= {sync[0], gpio_in};      // 2-FF synchronizer
    pin_d <= sync[1];
end
wire pin_sync   = sync[1];
wire rise_edge  = pin_sync & ~pin_d;   // 0 -> 1 transition

// set interrupt-pending on an enabled rising edge
always @(posedge clk)
    if (rise_edge & int_enable) irq_pending <= 1'b1;
    else if (irq_clear)         irq_pending <= 1'b0;

Synchronize before you detect

A raw external pin is asynchronous — feed it straight into edge-detection logic and you'll get metastability-induced false edges. Always pass it through a 2-FF synchronizer (Stage 0, Day 28) *first*, then detect edges on the clean, synchronized signal. This ordering is a small but real correctness point, and a favorite interview trap.

Ship for Day 73

Why synchronize a GPIO input pin before doing edge detection on it?

We use cookies

We use cookies to enhance your browsing experience, serve personalized content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies. Learn more

    Day 73: Peripheral: GPIO with interrupt lines | RBTechIconX