1

I am trying to port some Verilog source code to SystemVerilog. This question is specific to Icarus Verilog (tested with 10.3 and 11 providing the same result), since I did not get any errors with tools (e.g. Yosys 0.9.0, Cadence Xcelium 19.09). The issue I have boils down to the following minimal example:

module main();
  logic sel;
  wire [31:0] wired;
  logic show;

  initial begin
    $monitor("show = %d", show);

    sel = 1'b1;
    #10;
    sel = 1'b0;
  end

  subout a(.sel_i(sel), .val_o(wired));
  subin  b(.val_i(wired), .out_o(show));
endmodule

module subout(
  input logic sel_i,
  output logic [31:0] val_o
);
  always @(sel_i) begin
    val_o   = 32'b0;

    if (sel_i) begin
      val_o = 32'b101010;
    end
  end
endmodule

module subin(
  input logic [31:0] val_i,
  output logic out_o
);
  assign out_o = val_i[0];
endmodule

Apparently, I want to create some val_o value in subout and wire it up in main to pass it to subin. subin takes the value and returns one bit which is monitored. In other words, a value is passed from one submodule to the other.

The error, I get with iverilog <file-with-above-content> is:

iverilog_issue.sv:35: error: reg out_o; cannot be driven by primitives or continuous assignment.
iverilog_issue.sv:15: error: reg show; cannot be driven by primitives or continuous assignment.
iverilog_issue.sv:15: error: Output port expression must support continuous assignment.
iverilog_issue.sv:15:      : Port 2 (out_o) of subin is connected to show
3 error(s) during elaboration.

As far as I understand the situation, it should create one register for val_o in subout and one register sel in main. Everything else are just wires. Since, we are using SystemVerilog, I use logic and do not specify wire/reg. To me the conclusion reg show; is already incorrect.

  1. How does Icarus Verilog conclude reg show;?
  2. Can you make this example run with iverilog?
meisterluk
  • 804
  • 10
  • 19

1 Answers1

2

The code runs correctly on EDAplayground with an older Icarus 10.0. So my guess is you didn't enable the SystemVerilog flag -g2012. By default Icarus runs in Verilog IEEE1364-2005 [1]; which is the same as setting the flag -g2005

Verilog only allows wires to be driven by assign statements or output ports. SystemVerilog relaxed the rule so reg and logic driven by assign statements or output ports so long as that is the only driver. (Bit off topic but, I personally prefer following the stricter Verilog rules because not all tools have strong single source driver checking for reg and logic driven by assign statements or output ports)

Anyway, try this command:

iverilog -Wall -g2012 <file-with-above-content>
Greg
  • 18,111
  • 5
  • 46
  • 68