Rising-edge detector

One rising edge of an input produces exactly one clock period of output. The flip-flop that remembers the last cycle, and the gate that compares.

Level
rtl
Code
rising-edge-detector
Checked
Verilator 5.052, Icarus Verilog 13.0, Yosys 0.66
Published
Authorship
Drafted with AI assistance
Status
In progress — published so it can be reviewed, not finished.

Read this page in Turkish

A rising-edge detector turns a level into an event: while sig_in stays high the output pulse is high for exactly one clock period, on the cycle after the rise. It is the circuit behind every "do this once when that happens" in a synchronous design — a button press, a FIFO write, a start signal.

The whole thing is one flip-flop and one gate. The flip-flop remembers what sig_in was a cycle ago; the gate asks whether it is high now and was not then.

sig_in 0clk 0rst_n 1DQrstlines 15–210line 24line 9pulse 0sig_d~sig_d

Run plays this scenario from the start; driving an input continues from here.

A circuit that runs: a schematic and its waveform on one time axis. Inputs: sig_in, rst_n. Outputs: pulse. clk runs at 8 ticks a period. It is built from 1 D flip-flop, 1 inverter, 1 AND gate. The waveform shows clk, rst_n, sig_in, sig_d, pulse.

Figure 1. Press Run. sig_in rises at the second edge; pulse is high for the one period that follows.

How it works, edge by edge

Follow the waveform under the drawing. Before the first rising edge sig_d is X: nothing has reset the flip-flop and no edge has arrived, so it holds no value at all — which is why the reset is part of the circuit and not an afterthought.

At the first edge sig_d takes the 0 that sig_in is holding, and pulse stays 0 because sig_in is still 0.

sig_in rises at the second edge, and that edge still samples the 0 it held just before. Now sig_in is 1 while sig_d is still the 0 the flip-flop captured, so ~sig_d is 1 and pulse goes high. This is the whole trick, and it happens combinationally: pulse follows sig_in without waiting for a clock.

At the third edge the flip-flop catches up. sig_d becomes 1, ~sig_d becomes 0, and pulse falls — one clock period after it rose, whatever sig_in does next.

The code

rising_edge_detector.sv
// One rising edge of sig_in produces one clock period of pulse.
//
// Reset style for this module: asynchronous, active low. One style per page,
// stated up front, so nothing on the page has to be read twice.
module rising_edge_detector (
    input  logic clk,
    input  logic rst_n,
    input  logic sig_in,
    output logic pulse
);

  // The value sig_in had one clock period ago.
  logic sig_d;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      sig_d <= 1'b0;
    end else begin
      sig_d <= sig_in;
    end
  end

  // High for exactly one clock period, on the cycle after sig_in rises.
  assign pulse = sig_in & ~sig_d;

endmodule

The reset style is stated at the top of the file and used once: asynchronous, active low. The always_ff block is the flip-flop in the drawing, and the assign is the AND gate with its inverted input. Nothing else is needed, and nothing else should be added: a second always_ff here would be a second flip-flop nobody asked for.

Synthesis result

Yosys's generic synthesis turns rising_edge_detector.sv into 2 cells, 1 of them a flip-flop. The cells are Yosys's own gate library, not an FPGA's or a standard-cell library's: the count measures the logic, not the area of any chip.

Cells after synth -nofsm, by type
CellWhat it isCount
$_DFF_PN0_D flip-flop on the rising edge, active-low asynchronous reset to 01
$_ANDNOT_AND with its second input inverted, A & ~B1
Total2

Lint by Verilator 5.052, the testbench by Icarus Verilog 13.0, synthesis by Yosys 0.66.

Icarus replayed this page's two scenarios on this code, and all 340 values the waveform draws match.

The netlist before synthesis

What Yosys's prep reads in rising_edge_detector.sv, before any gate is chosen, drawn by netlistsvg 1.0.2.

$adffARSTCLKDQclkrst_nsig_inpulse

Pitfalls

An asynchronous input. If sig_in comes from another clock domain, this circuit is the wrong place to put it. The flip-flop can sample sig_in exactly as it changes and go metastable, and the AND gate can produce a pulse far shorter than a clock period — short enough for the next stage to miss, or to catch on one edge and not another. Synchronize first, detect the edge second.

Reset that only reaches half the circuit. sig_d is reset; pulse is not, because it is combinational. Coming out of reset with sig_in already high produces a pulse immediately. That is usually what you want; it is never what you want by accident.

Check yourself

Why is the pulse exactly one clock period long, rather than as long as sig_in stays high?
Because the flip-flop catches up. One edge after sig_in rises, sig_d is 1 too, so sig_in & ~sig_d is 0 again — however long sig_in stays high.
What does this circuit do with an input that is not synchronous to clk?
It produces a pulse that is not a clock period long, and can produce none at all. The flip-flop can sample a change as it happens, and the AND gate sees a glitch. An asynchronous input needs a synchronizer before this circuit, not after it.

Challenge: Three pulses

You drive sig_in, and pulse must be 1 at the edges numbered 1, 3 and 6.

Your input
  • sig_in, starting at 0
The script
  • rst_n starts at 0.
  • rst_n becomes 1 before the edge numbered 0.
The goal
  • pulse is 1 at the edge numbered 1.
  • pulse is 1 at the edge numbered 3.
  • pulse is 1 at the edge numbered 6.

With JavaScript on, Start plays this challenge in the figure.

All challenges

Tags rtl flip-flop edge-detection

Found an error? Send a correction