The packet processor routes done, configuration error, timeout, and datapath fault events into this one pending bank. The earlier set-wins equation is reused unchanged, so the interrupt view and STATUS view cannot disagree about collision policy.
// snippet: set-dominant interrupt bank
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
pending_q <= '0;
enable_q <= '0;
end else begin
if (wr_enable) enable_q <= (enable_q & ~write_mask) | (wdata & write_mask);
pending_q <= (pending_q & ~w1c_clear) | event_i;
end
end
assign irq_o = |(pending_q & enable_q);Pending is sticky so one-cycle events survive software latency.
Enable controls notification, not event capture; disabled events may remain visible in status.
The interrupt output is normally level-sensitive until all enabled pending causes are cleared.
Software reads cause bits, services sources, then clears only those handled.
Each slot is one clock cycle, and an input takes effect at the edge that ends its slot, so pending and irq change one slot later. The enable is held at 1, so irq follows pending. The page's four edges E0 to E3 end slots 1 to 4.
Slots 1 and 2 (E0, E1): event A sets pending, and irq rises in slot 2. Event B arrives while pending is already 1, so the two events coalesce into one bit.
Slot 3 (E2): the clear removes pending in slot 4. No count of B remains.
Slot 4 (E3): event C and the clear arrive on the same edge. Set wins, so pending is 1 again in slot 5.
A sticky bit retains a captured pending cause, not every occurrence. For lossless completions, count events with a defined saturation/overflow policy, enqueue records, or drain an underlying FIFO and use a level condition. Service/W1C alone cannot reconstruct two occurrences that coalesced.
Usually yes: capture and notification are separate policies. The status remains observable, and enabling later may raise the interrupt. If the product requires masked events to be discarded, state that explicitly.