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.
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.
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
// 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;
endmoduleThe 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.
| Cell | What it is | Count |
|---|---|---|
$_DFF_PN0_ | D flip-flop on the rising edge, active-low asynchronous reset to 0 | 1 |
$_ANDNOT_ | AND with its second input inverted, A & ~B | 1 |
| Total | 2 | |
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.
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.