From 10383ab2a4b9a14eec5c4d33da21c1f2ea23c368 Mon Sep 17 00:00:00 2001 From: Gus Smith Date: Mon, 23 Mar 2026 15:04:47 -0700 Subject: [PATCH 1/3] Tests for both issues --- tests/verilog/issue4402.ys | 20 ++++++++++++++++++++ tests/verilog/issue5745.ys | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/verilog/issue4402.ys create mode 100644 tests/verilog/issue5745.ys diff --git a/tests/verilog/issue4402.ys b/tests/verilog/issue4402.ys new file mode 100644 index 000000000..82133f60e --- /dev/null +++ b/tests/verilog/issue4402.ys @@ -0,0 +1,20 @@ +# Issue #4402: read_verilog doesn't respect signed keyword +# +# write_verilog drops the signed keyword from input port declarations, +# even though the internal comparison logic is correctly preserved via +# explicit $signed() casts. The port declaration should retain signed +# so that the interface contract is correct for downstream tools. + +! mkdir -p temp + +read_verilog < 11), giving k = 0. + +read_verilog < Date: Mon, 23 Mar 2026 15:20:42 -0700 Subject: [PATCH 2/3] Add `signed` keyword in write_verilog --- backends/verilog/verilog_backend.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 73ffcbf3e..d5f83aefc 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -456,21 +456,22 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) if (wire->attributes.count(ID::single_bit_vector)) range = stringf(" [%d:%d]", wire->start_offset, wire->start_offset); } + std::string sign = wire->is_signed ? " signed" : ""; if (wire->port_input && !wire->port_output) - f << stringf("%s" "input%s %s;\n", indent, range, id(wire->name)); + f << stringf("%s" "input%s%s %s;\n", indent, sign, range, id(wire->name)); if (!wire->port_input && wire->port_output) - f << stringf("%s" "output%s %s;\n", indent, range, id(wire->name)); + f << stringf("%s" "output%s%s %s;\n", indent, sign, range, id(wire->name)); if (wire->port_input && wire->port_output) - f << stringf("%s" "inout%s %s;\n", indent, range, id(wire->name)); + f << stringf("%s" "inout%s%s %s;\n", indent, sign, range, id(wire->name)); if (reg_wires.count(wire->name)) { - f << stringf("%s" "reg%s %s", indent, range, id(wire->name)); + f << stringf("%s" "reg%s%s %s", indent, sign, range, id(wire->name)); if (wire->attributes.count(ID::init)) { f << stringf(" = "); dump_const(f, wire->attributes.at(ID::init)); } f << stringf(";\n"); } else - f << stringf("%s" "wire%s %s;\n", indent, range, id(wire->name)); + f << stringf("%s" "wire%s%s %s;\n", indent, sign, range, id(wire->name)); #endif } From 8a282b3c1753c28833dfe15ca034f125fa78f678 Mon Sep 17 00:00:00 2001 From: Gus Smith Date: Mon, 23 Mar 2026 15:21:48 -0700 Subject: [PATCH 3/3] Update test --- tests/verilog/issue4402.ys | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/verilog/issue4402.ys b/tests/verilog/issue4402.ys index 82133f60e..f08c43229 100644 --- a/tests/verilog/issue4402.ys +++ b/tests/verilog/issue4402.ys @@ -1,9 +1,6 @@ # Issue #4402: read_verilog doesn't respect signed keyword # -# write_verilog drops the signed keyword from input port declarations, -# even though the internal comparison logic is correctly preserved via -# explicit $signed() casts. The port declaration should retain signed -# so that the interface contract is correct for downstream tools. +# write_verilog was not emitting the signed keyword for port declarations. ! mkdir -p temp @@ -16,5 +13,4 @@ hierarchy -top mod write_verilog temp/issue4402_roundtrip.v # The output port declaration must include the signed keyword. -# Bug: write_verilog emits `input [5:0] wire0` instead of `input signed [5:0] wire0`. ! grep -q "input signed" temp/issue4402_roundtrip.v