What is the proper way to implement clock gating in RTL?
The clock gating signal should only toggle when the latch is closed, otherwise there is a chance for glitches and metastability issues. For an active high latch, the gating signal should toggle on the falling edge of the clock. Rising edge for active low latches.
Normally you would use an edge sensitive flop to hold latch_update_en
to prevent noise on the gating signal.
always_ff @(negedge clk)
latch_update_en <= next_latch_update_en;
always_comb
gated_clk = (* clock_gating = "clk" *) clk & latch_update_en;
always_latch
if(gated_clk)
latch_data <= new_data;
Reminder: if you have a latch only deign: edge trigger flops are just master/slave latches
always_latch
if (clk)
sync_latch_update_en <= next_latch_update_en;
always_latch
if (!clk)
latch_update_en <= sync_latch_update_en;
Does the tool have hard time in synthesis if clk is directly "and"-ed in a always_comb block with another enable signal?
Most synthesis do have have issues with directly AND-ing a clocking. It is not always intuitive how the gating should be used. A synthesizer often has many AND gates in the library to choose from, each one has different slew, skew, and loading that very on input combinations. Though functionally the same, A & B
will get different time results then B & A
.
Instantiating an explicit cell from the synthesizer's library narrows the possibilities to know and anticipated behavior. A predefined clock gating cell also has attributes used by the synthesizer. Attributes include timing information for balancing the clock tree (buffer placement in the design for managing loads and parasitic).
Some synthesizers support setting attributes tags in RTL (ex: // synthesis attributes
or (* attributes *)
) instead of needing to explicitly instantiate a cell. There isn't a standard for how this is do so refer to your user manual.
What is the purpose of using custom clock gating cell?
The custom cell is a per-defined cell in the synthesis library with know timing information, load balancing, and other attributes. With this information, the synthesizer knows where and how to add or calibrate the buffer delay in the clock tree. This making sure the non-gated flop doesn't see the clock edge before gated flop.
_____ _____
IN -------------|D Q|-----|D Q|--- OUT
| | | |
|\ |\ | | | |
+-| >| >---|> | +-|> |
| |/ |/ |_____| | |_____|
| ___ |
CLK -+-| \ |
| & )-------------+ BALANCED CLOCK : correct data sampled
GATE --|___/
Without the guidance, the gated flop's could get a delayed clock. The skew would cause the wrong data to get sampled.
_____ _____
IN -------------|D Q|-----|D Q|--- OUT
| | | |
| | | |
+----------|> | +-|> |
| |_____| | |_____|
| ___ |
CLK -+-| \ |\ |\ |
| & )---| >| >----+ UNBALANCED CLOCK : wrong data sampled
GATE --|___/ |/ |/
clock_gator
is not a standard Verilog module; it's being pulled in somewhere by your code. You'll have to show us how it's implemented if you want us to make sense of it. – Forgetmenotclock_gator
cell should be a glitch-free implementation I think. In your example 1, it is the very basic idea of using clock gating. However, it would produce glitches and cause wrong behavior. – Clavicorn