Skip to content

Commit

Permalink
Merge pull request #1 from DaveMcEwan/rule-procedural-continuous-assi…
Browse files Browse the repository at this point in the history
…gnment

Rule procedural continuous assignment
  • Loading branch information
remes-codasip authored Dec 22, 2023
2 parents 4884471 + f4ecadd commit cf91a86
Show file tree
Hide file tree
Showing 15 changed files with 144 additions and 48 deletions.
99 changes: 77 additions & 22 deletions MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -4815,47 +4815,98 @@ The most relevant clauses of IEEE1800-2017 are:

### Hint

Move continuous assignment out of procedural block.
Move `assign` out of `always` block.

### Reason

Continuous assigments ('assign a = b') in procedural blocks ('always*') are not synthesizable.
Procedural continuous assigments are not synthesizable.

### Pass Example (1 of 1)
### Pass Example (1 of 4)
```systemverilog
module M (
input logic a,
input logic b,
output logic c
);
module M;
assign c = a + b; // Continuous assignment
endmodule
```

assign c = a + b;
### Pass Example (2 of 4)
```systemverilog
module M;
always_ff @(posedge clk)
c <= a + b; // Procedural non-blocking assignment
endmodule
```

### Pass Example (3 of 4)
```systemverilog
module M;
always_comb
c = a + b; // Procedural blocking assignment
endmodule
```

### Pass Example (4 of 4)
```systemverilog
module M;
always @*
c = a + b; // Procedural blocking assignment, Verilog 2001
endmodule
```

### Fail Example (1 of 1)
### Fail Example (1 of 4)
```systemverilog
module M;
always @*
assign c = a + b;
endmodule
```

### Fail Example (2 of 4)
```systemverilog
module M (
input logic clk,
input logic a,
input logic b,
output logic c
);
module M;
always_comb
assign c = a + b;
endmodule
```

always_ff @(posedge clk)
### Fail Example (3 of 4)
```systemverilog
module M;
always_latch
assign c = a + b;
endmodule
```

### Fail Example (4 of 4)
```systemverilog
module M;
always_ff @(posedge clk)
assign c = a + b;
endmodule
```

### Explanation

SystemVerilog continuous assignment (`assign x = y`) infers combinatorial logic
that continuously drives the LHS and changes with any change on the RHS.
Continuous assignment, e.g. `assign x = y;` outside of any `always` process,
continuously drives the LHS and changes with any change on the RHS.
The same keyword `assign` has different meaning when used within an `always`
process (or `always_ff`, `always_comb`, `initial`, etc.) where it can be used
to override procedural assignments.
Using this construct in a procedural block (`always*`) which is only triggered
on changes to signals in the sensitivity list may not be synthesizable.

This SystemVerilog language feature is being considered for deprecation, as
noted in IEEE1800-2017 Annex C, because it is easily abused and difficult to
implement while not providing additional capability.
Users are strongly encouraged to migrate their cod to use one of the alternate
methods of procedural or continuous assignments.

Such construct in a procedural (`always*`) block which is only triggered
on the changes of the signals in the sensitivity list may not be synthesizable.
See also:
- **non_blocking_assignment_in_always_comb** - Useful companion rule.
- **blocking_assignment_in_always_ff** - Useful companion rule.

The most relevant clauses of IEEE1800-2017 are:
- 10.6.1 The assign and deassign procedural statements
- Annex C.4 Constructs identified for deprecation



Expand Down Expand Up @@ -11187,6 +11238,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true

# Common to **ruleset-designintent**.
syntaxrules.action_block_with_side_effect = true
Expand Down Expand Up @@ -11923,6 +11975,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
#syntaxrules.general_always_no_edge = true # Redundant with keyword_forbidden_always.
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
```

This ruleset has further rules which don't depend on each other or combine
Expand All @@ -11939,7 +11992,6 @@ syntaxrules.function_same_as_system_function = true
syntaxrules.keyword_forbidden_always = true
syntaxrules.keyword_forbidden_wire_reg = true
syntaxrules.module_nonansi_forbidden = true
syntaxrules.procedural_continuous_assignment = true
```

When synthesised into a netlist, generate blocks should have labels so that
Expand Down Expand Up @@ -12061,6 +12113,7 @@ syntaxrules.operator_case_equality = true
syntaxrules.action_block_with_side_effect = true
syntaxrules.default_nettype_none = true
syntaxrules.function_same_as_system_function = true
syntaxrules.procedural_continuous_assignment = true
```

Verilog does allow both ANSI and non-ANSI forms of module declaration, but
Expand Down Expand Up @@ -12207,6 +12260,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
```


Expand Down Expand Up @@ -12534,6 +12588,7 @@ syntaxrules.enum_with_type = true
syntaxrules.keyword_forbidden_priority = true
syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.procedural_continuous_assignment = true
```

This ruleset has further rules which don't depend on each other or combine
Expand Down
1 change: 1 addition & 0 deletions md/ruleset-DaveMcEwan-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true

# Common to **ruleset-designintent**.
syntaxrules.action_block_with_side_effect = true
Expand Down
2 changes: 1 addition & 1 deletion md/ruleset-designintent.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
#syntaxrules.general_always_no_edge = true # Redundant with keyword_forbidden_always.
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
```

This ruleset has further rules which don't depend on each other or combine
Expand All @@ -33,7 +34,6 @@ syntaxrules.function_same_as_system_function = true
syntaxrules.keyword_forbidden_always = true
syntaxrules.keyword_forbidden_wire_reg = true
syntaxrules.module_nonansi_forbidden = true
syntaxrules.procedural_continuous_assignment = true
```

When synthesised into a netlist, generate blocks should have labels so that
Expand Down
1 change: 1 addition & 0 deletions md/ruleset-designintentV2001.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ syntaxrules.operator_case_equality = true
syntaxrules.action_block_with_side_effect = true
syntaxrules.default_nettype_none = true
syntaxrules.function_same_as_system_function = true
syntaxrules.procedural_continuous_assignment = true
```

Verilog does allow both ANSI and non-ANSI forms of module declaration, but
Expand Down
1 change: 1 addition & 0 deletions md/ruleset-simsynth.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
```

1 change: 1 addition & 0 deletions md/ruleset-verifintent.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ syntaxrules.enum_with_type = true
syntaxrules.keyword_forbidden_priority = true
syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.procedural_continuous_assignment = true
```

This ruleset has further rules which don't depend on each other or combine
Expand Down
24 changes: 20 additions & 4 deletions md/syntaxrules-explanation-procedural_continuous_assignment.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
SystemVerilog continuous assignment (`assign x = y`) infers combinatorial logic
that continuously drives the LHS and changes with any change on the RHS.
Continuous assignment, e.g. `assign x = y;` outside of any `always` process,
continuously drives the LHS and changes with any change on the RHS.
The same keyword `assign` has different meaning when used within an `always`
process (or `always_ff`, `always_comb`, `initial`, etc.) where it can be used
to override procedural assignments.
Using this construct in a procedural block (`always*`) which is only triggered
on changes to signals in the sensitivity list may not be synthesizable.

Such construct in a procedural (`always*`) block which is only triggered
on the changes of the signals in the sensitivity list may not be synthesizable.
This SystemVerilog language feature is being considered for deprecation, as
noted in IEEE1800-2017 Annex C, because it is easily abused and difficult to
implement while not providing additional capability.
Users are strongly encouraged to migrate their cod to use one of the alternate
methods of procedural or continuous assignments.

See also:
- **non_blocking_assignment_in_always_comb** - Useful companion rule.
- **blocking_assignment_in_always_ff** - Useful companion rule.

The most relevant clauses of IEEE1800-2017 are:
- 10.6.1 The assign and deassign procedural statements
- Annex C.4 Constructs identified for deprecation
1 change: 1 addition & 0 deletions rulesets/DaveMcEwan-design.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true

# Common to **ruleset-designintent**.
syntaxrules.action_block_with_side_effect = true
Expand Down
2 changes: 1 addition & 1 deletion rulesets/designintent.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
#syntaxrules.general_always_no_edge = true # Redundant with keyword_forbidden_always.
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
syntaxrules.action_block_with_side_effect = true
syntaxrules.default_nettype_none = true
syntaxrules.function_same_as_system_function = true
syntaxrules.keyword_forbidden_always = true
syntaxrules.keyword_forbidden_wire_reg = true
syntaxrules.module_nonansi_forbidden = true
syntaxrules.procedural_continuous_assignment = true
syntaxrules.generate_case_with_label = true
syntaxrules.generate_for_with_label = true
syntaxrules.generate_if_with_label = true
Expand Down
1 change: 1 addition & 0 deletions rulesets/designintentV2001.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ syntaxrules.operator_case_equality = true
syntaxrules.action_block_with_side_effect = true
syntaxrules.default_nettype_none = true
syntaxrules.function_same_as_system_function = true
syntaxrules.procedural_continuous_assignment = true
syntaxrules.module_ansi_forbidden = true
syntaxrules.general_always_level_sensitive = true
syntaxrules.blocking_assignment_in_always_at_edge = true
Expand Down
1 change: 1 addition & 0 deletions rulesets/simsynth.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.general_always_no_edge = true
syntaxrules.operator_case_equality = true
syntaxrules.procedural_continuous_assignment = true
1 change: 1 addition & 0 deletions rulesets/verifintent.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ syntaxrules.enum_with_type = true
syntaxrules.keyword_forbidden_priority = true
syntaxrules.keyword_forbidden_unique = true
syntaxrules.keyword_forbidden_unique0 = true
syntaxrules.procedural_continuous_assignment = true
syntaxrules.action_block_with_side_effect = true
syntaxrules.default_nettype_none = true
syntaxrules.function_same_as_system_function = true
Expand Down
4 changes: 2 additions & 2 deletions src/syntaxrules/procedural_continuous_assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ impl SyntaxRule for ProceduralContinuousAssignment {
}

fn hint(&self, _option: &ConfigOption) -> String {
String::from("Move continuous assignment out of procedural block.")
String::from("Move `assign` out of `always` block.")
}

fn reason(&self) -> String {
String::from("Continuous assigments ('assign a = b') in procedural blocks ('always*') are not synthesizable.")
String::from("Procedural continuous assigments are not synthesizable.")
}
}
28 changes: 18 additions & 10 deletions testcases/syntaxrules/fail/procedural_continuous_assignment.sv
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
module M (
input logic clk,
input logic a,
input logic b,
output logic c
);

always_ff @(posedge clk)
assign c = a + b;

module M;
always @*
assign c = a + b;
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always_comb
assign c = a + b;
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always_latch
assign c = a + b;
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always_ff @(posedge clk)
assign c = a + b;
endmodule
25 changes: 17 additions & 8 deletions testcases/syntaxrules/pass/procedural_continuous_assignment.sv
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
module M (
input logic a,
input logic b,
output logic c
);

assign c = a + b;

module M;
assign c = a + b; // Continuous assignment
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always_ff @(posedge clk)
c <= a + b; // Procedural non-blocking assignment
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always_comb
c = a + b; // Procedural blocking assignment
endmodule
////////////////////////////////////////////////////////////////////////////////
module M;
always @*
c = a + b; // Procedural blocking assignment, Verilog 2001
endmodule

0 comments on commit cf91a86

Please sign in to comment.