SV Guide
SV Guide
SV Guide
The SystemVerilog coding guidelines and rules in this article are based on Siemens EDA's
experience and are designed to steer users away from coding practices that result in
SystemVerilog that is either hard to understand or debug.
Please send any suggestions, corrections or additions to vmdoc@mentor.com.
General Coding Style
Although bad coding style does not stop your code from working, it does make it harder for
others to understand and makes it more difficult to maintain. Take pride in writing well-ordered
and uniformly formatted code.
1.1 Guideline: Indent your code with spaces
Use a consistent number of spaces to indent your code every time you start a new nested block,
2 or 3 spaces is recommended. Do not use tabs since the tab settings vary in different editors
and viewers and your formatting may not look as you intended. Many text editors have an
indenting mode that automatically replaces tabs with a defined number of spaces.
1.2 Guideline: Only one statement per line
Only have one declaration or statement per line. This makes the code clearer and easier to
understand and debug.
The SystemVerilog coding guidelines and rules in this article are based on Siemens EDA's
experience and are designed to steer users away from coding practices that result in
SystemVerilog that is either hard to understand or debug.
General Coding Style
Although bad coding style does not stop your code from working, it does make it harder for
others to understand and makes it more difficult to maintain. Take pride in writing well-ordered
and uniformly formatted code.
1.1 Guideline: Indent your code with spaces
Use a consistent number of spaces to indent your code every time you start a new nested block, 2 or
3 spaces is recommended. Do not use tabs since the tab settings vary in different editors and viewers
and your formatting may not look as you intended. Many text editors have an indenting mode that
automatically replaces tabs with a defined number of spaces.
1.2 Guideline: Only one statement per line
Only have one declaration or statement per line. This makes the code clearer and easier to
understand and debug.
Recommended Not Recommended
if(!$cast(rhs_, rhs))begin
`uvm_error("do_compare","cast failed, check ty
pe compatibility")
Not
return0;
Recommended
end
do_compare=super.do_compare(rhs, comparer)&&(MADDR
== rhs_.MADDR)&&(MWDATA== rhs_.MWDATA)&&(MREAD== rhs
_.MREAD)&&(MOPCODE== rhs_.MOPCODE)&&(MPHASE== rhs_.M
PHASE)&&(MRESP== rhs_.MRESP)&& (MRDATA== rhs_.MRDATA
);
endfunction: do_compare
if(!$cast(rhs_, rhs))begin
`uvm_error("do_compare","cast failed, check ty
pe compatibility")
return0;
end
Recommended
do_compare=super.do_compare(rhs, comparer)&&
(MADDR== rhs_.MADDR)&&
(MWDATA== rhs_.MWDATA)&&
(MREAD== rhs_.MREAD)&&
(MOPCODE== rhs_.MOPCODE)&&
(MPHASE== rhs_.MPHASE)&&
(MRESP== rhs_.MRESP)&&
(MRDATA== rhs_.MRDATA);
endfunction: do_compare
1.7 Guideline: Use lowercase for names, using underscores to separate fields
This makes it clearer what the name is, as opposed to other naming styles such as CamelCase which
are harder to read.
Recommended Not Recommended
axi_fabric_scoreboard_error AxiFabricScoreboardError
1.10 Guideline: Use the end label for classes, functions, tasks, and packages
This forces the compiler to check that the name of the item matches the end label which can trap cut
and paste errors. It is also useful to a person reading the code.
task my_task;
// ...
endtask: my_task
endclass: my_class
endpackage: my_pkg
// function: new
// Constructor - initializes valid
extern function new();
// function: compress_sample
// Applies compression algorithm to raw sample
// inputs: none
// returns: void
extern function void compress_sample();
// function: set_new_sample
// Set a new raw sample value
// inputs:
// raw_sample_t new_sample
// returns: void
extern function void set_new_sample(raw_sample_t new_sample);
endclass: audio_compress
function audio_compress::new();
valid=0;
iteration_limit= $bits(processed_sample_t);
endfunction
For a complex package (such as a UVC) that may contain tests, examples and documentation, create
subdirectories:
abc_pkg/examples
abc_pkg/docs
abc_pkg/tests
abc_pkg/src/abc_pkg.sv
./abc_pkg/src/abc_macros.svh
./abc_pkg/src/abc_env.svh
./abc_pkg/src/abc_interface.sv
./abc_pkg/src/abc_driver.svh
./abc_pkg/src/abc_monitor.svh
./abc_pkg/src/abc_scoreboard.svh
./abc_pkg/src/abc_sequence_item.svh
./abc_pkg/src/abc_sequencer.svh
./abc_pkg/src/abc_sequences.svh
./abc_pkg/docs/
./abc_pkg/docs/abc_user_guide.docx
./abc_pkg/tests/
./abc_pkg/tests/......
./abc_pkg/examples/
./abc_pkg/examples/a/....
./abc_pkg/examples/b/....
./abc_pkg/examples/c/....
./testbench1/makefile
./testbench1/tb_env.sv
./testbench1/tb_top.sv
./testbench1/test.sv
Using Packages
3.7 Rule: Import packages to reference their contents
When you use a function or a class from a package, you import it, and `include any macro definitions.
If you `include the package source, then you will be creating a new namespace for that package in
every file that you `include it into, this will result in type matching issues.
import abc_pkg::*;
`include"abc_macros.svh"
3.8 Rule: When compiling a package, use +incdir+ to reference its source directory
To compile the package itself, you use a +incdir to reference the source directory. Make sure that
there are no hard coded paths in the path string for the `included file.
vlog+incdir+$ABC_PKG/src abc_pkg.sv
To compile code that uses the package, you also use a +incdir to reference the source directory if a
macro file needs to be `included.
vlog+incdir+$ABC_PKG/src tb_top.sv
# Simulate
vsim-uvm=debug-coverage+UVM_TESTNAME=test \
-c tb_top-do"run -all; quit -f"
if(!$cast(t, to_be_cloned.clone())begin
`uvm_error("get_a_clone","$cast failed for to_be_cloned")
end
if(t==null)begin
`uvm_fatal("get_a_clone","$cast operation resulted in a null hand
le, check to_be_cloned handle")
end
return t;
endfunction: get_a_clone
4.3 Rule: Use if rather than assert to check the status of method calls
Assert results in the code check appearing in the coverage database, which is undesired. Incorrectly
turning off the action blocks of assertions may also produce undesired results.
Constructs to be Avoided
The SystemVerilog language has been a collaborative effort with a long history of constructs
borrowed from other languages. Some constructs have been improved upon with newer constructs,
but the old constructs remain for backward compatibility and should be avoided. Other constructs
were added before being proven out and in practice cause more problems than they solve.
4.4 Rule: Do not place any code in $unit, place it in a package
The compilation unit, $unit, is the scope outside of a design element (package, module, interface,
program). There are a number of problems with timescales, visibility, and re-usability when you place
code in $unit. Always place this code in a package.
4.5 Guideline: Do not use associative arrays with a wildcard index[*]
A wildcard index on an associative array is an un-sized integral index. SystemVerilog places severe
restrictions on other constructs that cannot be used with associative arrays having a wildcard index.
In most cases, an index type of [int] is sufficient. For example, a foreach loop requires a fixed type to
declare its iterator variable.
string names[*];// cannot be used with foreach, find_index, ...
string names[int];
...
foreach(names[i])
$display("element %0d: %s",i,names[i]);
Covergroups
4.9 Guideline: Create covergroups within wrapper classes
Covergroups have to be constructed within the constructor of a class. In order to make the inclusion
of a covergroup within a testbench conditional, it should be wrapped within a wrapper class.
4.10 Guideline: Covergroup sampling should be conditional
Build your covergroups so that their sample can be turned on or off. For example use the 'iff' clause
of covergroups.
// Wrapped covergroup with sample control:
class cg_wrapper extends uvm_component;
logic[31:0] address;
bit coverage_enabled
covergroup detail_group;
ADDRESS: coverpoint addr iff(coverage_enabled){
bins low_range={[0:32'h0000_FFFF]};
bins med_range={[32'h0001_0000:32'h0200_FFFF]};
bins high_range={[32'h0201_0000:32'h0220_FFFF]};
}
// ....
endgroup: detail_group
Coverpoint sampling may not be valid in certain situations, for instance during reset.
// Using iff to turn off unnecessary sampling:
Collecting Coverage
4.11 Guideline: Use the covergroup sample() method to collect coverage
Sample a covergroup by calling the sample routine, this allows precise control on when the sampling
takes place.
4.12 Rule: Label coverpoints and crosses
Labelling coverpoints allows them to be referenced in crosses and easily identified in reports and
viewers.
payload_size_cvpt:coverpoint ...