[CIRCT-VERILOG][ARC] arcilator fails on valid SystemVerilog always_ff with async reset
Tool: CIRCT (circt-verilog + arcilator)
Version: 1.144.0
Severity: Compilation Error
Description
A valid SystemVerilog always_ff block with an asynchronous reset (or posedge rst) triggers a compilation error in the CIRCT arcilator tool. The StripSV pass throws "only synchronous resets are currently supported" even though the seq.firreg operation is explicitly designed to support async resets via the isAsync attribute. This is a regression where CIRCT can parse and represent async resets but fails to process them.
Minimal Reproducible Example
module m(input clk, input rst);
logic r;
always_ff @(posedge clk or posedge rst) if (rst) r <= 0; else r <= 0;
endmodule
Reproduction Steps
circt-verilog --ir-hw minimal_testcase.sv -o /tmp/circt_out.mlir
arcilator /tmp/circt_out.mlir -o /tmp/arcilator.ll
Actual Output
/tmp/circt_out.mlir:5:10: error: 'seq.firreg' op only synchronous resets are currently supported
%r = seq.firreg %false clock %0 reset async %rst, %false : i1
^
/tmp/circt_out.mlir:5:10: note: see current operation: %2 = "seq.firreg"(%0, %1, %arg1, %0) <{isAsync, name = "r"}> : (i1, !seq.clock, i1, i1) -> i1
Expected Output
The code should compile successfully. The seq.firreg operation correctly captures the async reset semantics (as shown by reset async %rst in the MLIR), but the StripSV pass fails to process it instead of properly lowering it to arc-level constructs.
Cross-Tool Comparison
| Tool |
Version |
Result |
| CIRCT (circt-verilog + arcilator) |
5dc62fe (LLVM 23.0.0git) |
FAIL - Compilation error in StripSV pass |
| Verilator |
5.046 2026-02-28 |
PASS - Compiles successfully |
| Icarus Verilog |
13.0 (stable) |
PASS - Compiles and simulates successfully |
Root Cause (Preliminary)
The StripSV pass in lib/Dialect/Arc/Transforms/StripSV.cpp:140-142 emits an error when it encounters seq.firreg with isAsync=true, instead of properly lowering async reset registers. The seq.firreg operation CAN represent async resets (defined in SeqOps.td:238, built in SeqOps.cpp:419-430, parsed in SeqOps.cpp:456-467), and LowerToHW.cpp:3827-3831 correctly sets isAsync=true for AsyncResetType — but the StripSV pass does not handle it. Workaround: --async-resets-as-sync flag (changes semantics).
Standard Compliance Assessment
Classification: tool_bug
IEEE References: IEEE 1800-2017 Section 9.2.2.4 (page 209) — "Sequential logic always_ff procedure" explicitly allows asynchronous resets in the event control. Syntax always_ff @(posedge clock or posedge reset) for async reset is valid standard SystemVerilog.
Analysis:
- The SV code
always_ff @(posedge clk or posedge rst) with posedge rst in the sensitivity list is valid IEEE 1800.
- The
seq.firreg operation CAN represent async resets — all CIRCT internal components (operation definition, builder, parser, HW lowering) correctly support isAsync.
- The error comes from
StripSV failing to process async resets, not from a representation limitation.
- Verilator and Icarus Verilog both successfully compile the same code.
[CIRCT-VERILOG][ARC] arcilator fails on valid SystemVerilog always_ff with async reset
Tool: CIRCT (circt-verilog + arcilator)
Version: 1.144.0
Severity: Compilation Error
Description
A valid SystemVerilog
always_ffblock with an asynchronous reset (or posedge rst) triggers a compilation error in the CIRCT arcilator tool. TheStripSVpass throws "only synchronous resets are currently supported" even though theseq.firregoperation is explicitly designed to support async resets via theisAsyncattribute. This is a regression where CIRCT can parse and represent async resets but fails to process them.Minimal Reproducible Example
Reproduction Steps
Actual Output
Expected Output
The code should compile successfully. The
seq.firregoperation correctly captures the async reset semantics (as shown byreset async %rstin the MLIR), but theStripSVpass fails to process it instead of properly lowering it to arc-level constructs.Cross-Tool Comparison
Root Cause (Preliminary)
The
StripSVpass inlib/Dialect/Arc/Transforms/StripSV.cpp:140-142emits an error when it encountersseq.firregwithisAsync=true, instead of properly lowering async reset registers. Theseq.firregoperation CAN represent async resets (defined inSeqOps.td:238, built inSeqOps.cpp:419-430, parsed inSeqOps.cpp:456-467), andLowerToHW.cpp:3827-3831correctly setsisAsync=trueforAsyncResetType— but theStripSVpass does not handle it. Workaround:--async-resets-as-syncflag (changes semantics).Standard Compliance Assessment
Classification: tool_bug
IEEE References: IEEE 1800-2017 Section 9.2.2.4 (page 209) — "Sequential logic always_ff procedure" explicitly allows asynchronous resets in the event control. Syntax
always_ff @(posedge clock or posedge reset)for async reset is valid standard SystemVerilog.Analysis:
always_ff @(posedge clk or posedge rst)withposedge rstin the sensitivity list is valid IEEE 1800.seq.firregoperation CAN represent async resets — all CIRCT internal components (operation definition, builder, parser, HW lowering) correctly supportisAsync.StripSVfailing to process async resets, not from a representation limitation.