Why is this an issue?
Avoiding the use of both the rising and falling edges of a clock signal in the same clock domain for triggering logic
is recommended for several reasons:
- Metastability: Using both edges of a clock can increase the likelihood of metastability,
especially in timing-critical designs. Metastability occurs when a flip-flop does not have enough time to settle
into a stable state (either 0 or 1) before the next clock edge arrives. By only using one edge, you give the
flip-flop more time to stabilize.
- Timing Constraints and Clock Uncertainty: When you use both edges, the timing analysis becomes
more complex because the time between a falling edge and a rising edge (or vice versa) can vary significantly due to
clock jitter, skew, or other environmental factors. This reduces the setup and hold times available for each
flip-flop, making timing closure more difficult.
- Clock Duty Cycle Variations: Real clocks might not have a perfect 50% duty cycle where the high
and low times are equal. If you depend on both edges, variations in duty cycle can lead to timing issues. With one
edge, you only need to worry about the interval between that edge on consecutive cycles.
- Power Consumption: Using both edges of the clock can lead to higher power consumption because
the logic is toggling more frequently. In power-sensitive designs, this can be a significant issue.
- Design Complexity and Readability:
Using only one edge simplifies the design and makes the code easier to read and maintain. It reduces the potential
for errors in logic where the designer might confuse which edge is intended for which operation.
- Synchronization and Data Integrity:
For data integrity, especially in clock domain crossings, using a single edge (typically rising) ensures that data
is sampled at predictable times. This is crucial for multi-clock domain designs where synchronization is necessary
to avoid data corruption.
By using only one edge, you align your design with best practices for timing, stability, and maintainability. If
there's a need to use both edges for specific logic, consider using two separate clocks or another method like double
data rate (DDR) techniques, which are designed for handling such scenarios with care for timing and power
considerations.
How to fix it
Code examples
Noncompliant code example
module clock_both_edges (
input logic clk,
input logic rst,
input logic i1, i2,
output logic o1, o2
);
always @(posedge clk)
begin
if (rst == 1'b0)
o1 <= 1'b0;
else
o1 <= i1;
end
always @(negedge clk)
begin
if (rst == 1'b0)
o2 <= 1'b0;
else
o2 <= i2;
end
endmodule