Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No error thrown for nonblocking procedural assignment to a wire #1059

Open
mkurc-ant opened this issue May 31, 2019 · 3 comments
Open

No error thrown for nonblocking procedural assignment to a wire #1059

mkurc-ant opened this issue May 31, 2019 · 3 comments

Comments

@mkurc-ant
Copy link
Contributor

Consider the following Verilog design.

module bar (d, q, clk, rst);
  input  wire d;
  output wire q;
  input  wire clk;
  input  wire rst;

  always @(posedge clk or posedge rst)
    if (rst) q <= 1'd0;
    else     q <= d;
endmodule

module foo (d, q, clk, rst);
  input  wire d;
  output wire q;
  input  wire clk;
  input  wire rst;

  bar bar_instance (d, q, clk, rst);

endmodule

It contains an obvious error, the signal q in the module bar declared as wire instead of reg and used as l-value for procedural assignment in the always block.

Expected behavior

For the following call:

yosys -p "read_verilog foo_bar.v; write_verilog foo_bar_out.v"

Yosys should throw an error that the nonblocking procedural assignment cannot be used on a non-memory signal (eg. wire)

Actual behavior

Yosys infers that the signal q is a register and throws no error.

When the design is written to Verilog again using the write_verilog command, the signal q appears as reg:

/* Generated by Yosys 0.8+509 (git sha1 90ec2cda, gcc 7.4.0-1ubuntu1~18.04 -fPIC -Os) */

(* cells_not_processed =  1  *)
(* src = "foo_bar.v:1" *)
module bar(d, q, clk, rst);
  (* src = "foo_bar.v:7" *)
  reg _0_;
  (* src = "foo_bar.v:4" *)
  input clk;
  (* src = "foo_bar.v:2" *)
  input d;
  (* src = "foo_bar.v:3" *)
  output q;
  reg q;
  (* src = "foo_bar.v:5" *)
  input rst;
  always @* begin
    _0_ = q;
    casez (rst)
      1'h1:
          _0_ = 1'h0;
      default:
          _0_ = d;
    endcase
  end
  always @(posedge clk) begin
      q <= _0_;
  end
  always @(posedge rst) begin
      q <= _0_;
  end
endmodule

(* cells_not_processed =  1  *)
(* src = "foo_bar.v:12" *)
module foo(d, q, clk, rst);
  (* src = "foo_bar.v:15" *)
  input clk;
  (* src = "foo_bar.v:13" *)
  input d;
  (* src = "foo_bar.v:14" *)
  output q;
  (* src = "foo_bar.v:16" *)
  input rst;
  (* module_not_derived = 32'd1 *)
  (* src = "foo_bar.v:18" *)
  bar bar_instance (
    d,
    q,
    clk,
    rst
  );
endmodule
@daveshah1
Copy link

This is currently a warning:

Warning: wire '\q' is assigned in a block at foo.v:8.
Warning: wire '\q' is assigned in a block at foo.v:9.

This was decided when this feature was added to mitigate against false positives (given the complexity of the Verilog standard and frontend), and because Yosys has incorrectly accepted this without any warning for some time beforehand (several other tools do accept this too). If you really need this to be an error, you can use -e 'is assigned in a block' to make this warning into an error.

@mkurc-ant
Copy link
Contributor Author

In my opinion it should be an error by default and there should be the -w option to make it a warning. But since you are aware of that issue than I leave it up to you.

@albaEDA
Copy link

albaEDA commented May 31, 2019

+1 for default error, if I’m not mistaken it violates IEEE 1800-2017 (6.5 nets and variables)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants