// snippet
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) q <= '0;
else if (en) q <= d; // synthesis can replace the enable mux with a clock gateThis is the recommended default. Plain RTL lets the tool turn shared-enable feedback muxes into clock gates where they pay off, keeping the design synchronous and portable.
Use this when you need control over the gating structure (a power domain, a hand-built clock tree) or when the tool cannot infer it.
Compare the two clock pins first, then the D inputs.
Style A: the flop is clocked on every edge. When en is 0 the mux feeds q back to D, so the flop reloads its own value and its clock pin still toggles.
Style B: the mux is gone. The ICG stops gclk when en is 0, so the flop is not clocked at all and holds its value for free.
Same behaviour, different power: both registers load d when en is 1 and hold when en is 0. Synthesis can turn style A into style B for you when the register group is large enough.
Use the library ICG cell, via a wrapper module, not a hand-written AND or latch. Keep the wrapper so that you can swap models for simulation, FPGA or ASIC.
Drive the enable from registered logic (or a short, well-bounded path). A late enable fails the gating check.
Always provide a test enable (te) so that scan shifting still clocks the gated flops.
Put reset on the gated flops with an asynchronous reset (as above) or ensure the clock runs during reset; a synchronous reset on a gated clock will not take effect while the clock is off.
Never drive data from the gated clock domain into the ungated one without remembering the skew between them. They are the same clock source, but the gate adds insertion delay on one branch: the clock-tree tool balances the two branches only as well as its target allows, and STA must see the remaining skew on every crossing path (it often shows up as a hold problem).
Driving during the low phase avoids the latch-closing edge; delayed comparisons observe completed NBA updates. These offsets define a nonracy ideal-model stimulus, not measured clock-to-Q or library setup/hold margins.
The draft checker uses independent load/hold references, directed load/hold and 300-cycle idle/wake-up scenarios, then 2,000 random functional cycles. Under test enable the gated register must load every edge even with en=0, while the plain enable register holds.
`timescale 1ns/1ps
module icg (input logic clk, en, te, output logic gclk);
logic en_l;
always_latch if (!clk) en_l = en | te;
assign gclk = clk & en_l;
endmodule
// Style A: a register with an enable (what you normally write; synthesis may turn it into a gated clock)
module reg_en #(parameter int W = 8) (input logic clk, rst_n, en, input logic [W-1:0] d, output logic [W-1:0] q);
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) q <= '0;
else if (en) q <= d;
endmodule
// Style B: the same register behind an explicit clock gate; no enable mux in front of the flops
module reg_gated #(parameter int W = 8) (input logic clk, rst_n, en, te, input logic [W-1:0] d, output logic [W-1:0] q, output logic gclk);
icg u_icg (.clk, .en, .te, .gclk);
always_ff @(posedge gclk or negedge rst_n)
if (!rst_n) q <= '0;
else q <= d;
endmodule
The checker drives en, te and d 1 ns after falling source edges and samples outputs 1 ns after rising edges. The independent reference loads on en for style A and en|te for style B; changing test data checks bypass semantics, not just edge counts. The 300 idle cycles must deliver zero gated edges, retain 0x3c, then load 0xa5 on the first enabled edge and hold it on the next idle edge.
In the random part, 380 of the 2,000 cycles delivered a gated-clock edge.
Testbench, run with Icarus Verilog 13.0 (2026-10-16): iverilog -g2012 -s tb_gated, then vvp with +SEED=163, prints PASS. In the random part, 380 of the 2,000 cycles delivered a gated-clock edge. The 300 idle cycles deliver zero gated edges and the register keeps 0x3c.
The comparison is a finite model check. It is not formal equivalence or physical signoff, and it measures no activity or power reduction. The stimulus offsets define a non-racy ideal-model stimulus, not measured clock-to-Q or library setup and hold margins.