Summary
When implementing hardware designs that require negedge-clocked registers, the current FIRRTL/CIRCT infrastructure requires low-level workarounds that are fragile, non-portable, and produce suboptimal Verilog output.
Use cases: Negedge-clocked registers:
Many standard cell designs require registers clocked on the negative edge of a clock signal (e.g., CDC synchronizers, JTAG TAP state machines with negedge tck for shift/output registers, timing reference registers in clock-ratio synchronizers).
Current workaround: Manually construct an inverted clock using low-level MLIR C-API operations clk → AsUIntPrim → NotPrim → AsClockPrim use as clock in a locally scoped register
This works but:
- Requires importing java.lang.foreign.Arena, org.llvm.mlir.scalalib.capi.ir.{Block, Context}, and CIRCT FIRRTL dialect operations — none of which are user-facing APIs
- The generated Verilog uses posedge _inverted_clk with an explicit assign _inverted_clk = ~clk, instead of the idiomatic negedge clk that downstream tools expect
- Formal verification tools (e.g., Synopsys Formality) sometimes cannot automatically match posedge ~clk against negedge clk in equivalence checking
Proposed Improvements
First-class negedge clock support — Allow Clock to carry an edge attribute, or provide a NegEdgeClock(clk) primitive that generates idiomatic negedge clk in Verilog output
AI-assisted declaimer
This Issue is drafted by Claude, and edited by Jiuyang Liu. We are using AI to migrate many old Verilog-based modules with Zaozi eDSL, and found these incompatibilities.
Summary
When implementing hardware designs that require negedge-clocked registers, the current FIRRTL/CIRCT infrastructure requires low-level workarounds that are fragile, non-portable, and produce suboptimal Verilog output.
Use cases: Negedge-clocked registers:
Many standard cell designs require registers clocked on the negative edge of a clock signal (e.g., CDC synchronizers, JTAG TAP state machines with negedge tck for shift/output registers, timing reference registers in clock-ratio synchronizers).
Current workaround: Manually construct an inverted clock using low-level MLIR C-API operations
clk → AsUIntPrim → NotPrim → AsClockPrimuse as clock in a locally scoped registerThis works but:
Proposed Improvements
First-class negedge clock support — Allow Clock to carry an edge attribute, or provide a
NegEdgeClock(clk)primitive that generates idiomaticnegedge clkin Verilog outputAI-assisted declaimer
This Issue is drafted by Claude, and edited by Jiuyang Liu. We are using AI to migrate many old Verilog-based modules with Zaozi eDSL, and found these incompatibilities.