errors · sim, bitdewfpga sim and dewfpga bit, yosys (or yosys-slang)

design.sv:7: ERROR [implicit-port-width]: the .* connection of u (module sub) joins the port sub_out, 8 bits wide with N = 8, to the signal sub_out declared 4 bits wide: an implicit connection (.* or .sub_out) takes the port and the signal exactly as declared, with no padding or cutting (IEEE 1800-2017 23.3.2.3), so neither reader builds it, where dewfpga sim (iverilog) widened the signal to the port, so the port's 4 high bits reach nothing (its line: Padding 4 high bits of the port) and ran. Fix: declare sub_out with the port's width (logic [7:0] sub_out;), or connect it by name, .sub_out(sub_out), which pads or cuts to the port's width as the simulation did.

dewfpga sim and dewfpga bit print the same line. The simulation first, where iverilog's own warning comes before it:

design.sv:7: warning: Port 1 (sub_in) of module sub expects 8 bit(s), given 4.
design.sv:7:        : Padding 4 high bits of the port.
design.sv:7: warning: Port 2 (sub_out) of module sub expects 8 bit(s), given 4.
design.sv:7:        : Padding 4 high bits of the port.
ERROR: Width mismatch between wire (4 bits) and port (8 bits) for implicit port connection `sub_out' of cell top.u ($paramod\sub\N=s32'00000000000000000000000000001000).
design.sv:7: ERROR [implicit-port-width]: the .* connection of u (module sub) joins the port sub_out, 8 bits wide with N = 8, to the signal sub_out declared 4 bits wide: an implicit connection (.* or .sub_out) takes the port and the signal exactly as declared, with no padding or cutting (IEEE 1800-2017 23.3.2.3), so neither reader builds it, where dewfpga sim (iverilog) widened the signal to the port, so the port's 4 high bits reach nothing (its line: Padding 4 high bits of the port) and ran. Fix: declare sub_out with the port's width (logic [7:0] sub_out;), or connect it by name, .sub_out(sub_out), which pads or cuts to the port's width as the simulation did. https://nosey-dewdrop.github.io/dewfpga/errors/implicit-port-width/

The design that printed it (test/sv/102_dotstar_param_width): a submodule whose ports are N bits wide, instantiated with N = 8 and connected with .* to signals declared 4 bits wide.

module sub #(parameter N = 4) (input logic [N-1:0] sub_in, output logic [N-1:0] sub_out);
  assign sub_out = ~sub_in;
endmodule
module top(input logic [15:0] sw, output logic [15:0] led);
  logic [3:0] sub_in, sub_out;
  assign sub_in = sw[3:0];
  sub #(.N(8)) u (.*);
  assign led = {12'b0, sub_out};
endmodule

Why does it happen?

A named connection, .sub_in(sub_in), is an assignment: the signal is padded or cut to the port's width, as any assignment is (IEEE 1800-2017 23.3.2.2). The implicit forms, .sub_in and .*, are not: the standard says the port and the signal must be of equivalent type (23.3.2.3 for .name, 23.3.2.4 for .*), and a 4-bit logic is not equivalent to an 8-bit one. The three tools read that differently. iverilog warns and pads (or cuts, 'Pruning 2 high bits of the expression' when the signal is wider), and the simulation runs; yosys' own reader stops on a .* with 'Width mismatch between wire (4 bits) and port (8 bits)', with no file:line, and builds a .name with 'Warning: Resizing cell port top.u.sub_in from 4 bits to 8 bits.'; yosys-slang, the second reader, refuses both with 'implicit named port 'sub_in' of type 'logic[7:0]' connects to value of inequivalent type 'logic[3:0]''. Before this check the student got a PASS from the simulation and two slang-refused lines with a caret under .* from the build, and 20 of the 500 generated designs of test/fuzz ended that way. With the check, test/fuzz/run.sh 1 500 refuses 22 designs with this code: those 20, and 2 (seeds 192 and 200) whose .* mismatch sat behind a package-file-not-given refusal until #33 handed the tools the package file; the other 12 of the 14 package seeds build equal to their simulation, and no design that built before is refused now (fuzz: ok 428 of 500; silent-wrong 19; warned 7; refused-coded 46, from 416 before #33). Vivado's behaviour here is not documented: UG901 lists lower my_inst (.*); and the .name form as supported (Ch.10, p.281-282) and does not say what it does when the widths differ.

Now the product has one verdict of its own, the same at dewfpga sim and at dewfpga bit: the instance line, the port, the two widths, what the simulation did with the difference, and the fix. The simulation finds the case in iverilog's warning, refuses, and prints the build's line, so the student never sees a simulation pass that the board cannot be built from.

What the simulation did depends on the port's direction, and the message says it the way iverilog's own second line does: an input port cuts a wider signal ('Pruning 2 high bits of the expression') or pads a narrower one ('Padding 2 high bits of the expression'); an output port narrower than the signal pads the signal's high bits ('Padding 8 high bits of the expression'), and an output port wider than the signal widens the signal to the port, so the port's high bits reach nothing ('Padding 4 high bits of the port', the case above).

When the mismatched signal is a port of the parent module itself (sub u (.*) inside top(input logic [15:0] sw, output logic [15:0] led) with an 8-bit led on sub), redeclaring it is not a fix: its width is the board's wiring, pinned in the XDC. The message then says so and gives the named form instead: .led(led[7:0]) for an output port narrower than the parent's (the other bits need their own driver), .sw(sw) for an input port, which cuts or pads as the simulation did.

The check reads the design's files only. The same mismatch on the testbench's own instance line (top dut (.*) with an 8-bit led in the testbench) is not this error: no reader ever builds the testbench, iverilog pads it with its warning and the simulation runs, and dewfpga bit is unaffected. And a port whose type is not a plain vector (input int a joined by .* to a logic [31:0] a: 32 bits on both sides, slang's objection is the 2-state type against the 4-state one, IEEE 1800-2017 6.22.2) is not this error either: the build prints yosys-slang's own line as slang-refused. A .name connection with the same mismatch is refused the same way (yosys' own reader would have resized it silently, slang refuses it); a named connection .sub_in(sub_in) with the same widths builds in all three tools, with iverilog's 'Padding' and yosys' 'Resizing' warnings passed through, and is not this error.

What is the fix?

Declare the signal with the port's width, so the implicit connection joins two signals of the same type:

logic [7:0] sub_in, sub_out;

Or connect the port by name, which pads or cuts the signal to the port's width, as the simulation did:

sub #(.N(8)) u (.sub_in(sub_in), .sub_out(sub_out));

Which command prints it?

Which probes in test/sv print this code?

Every probe, with what Vivado does and what each stage does here: the probes, stage by stage.