编码规则 - coding guidelines

  

 Writing testbenches involves writing a lot of code and also requires coding guidelines. These guidelines are designed to enhance code maintainability and readability, as well as to prevent common or obscure mistakes.

The specifics of a guideline may not be important. It is the fact that it is specified and that everyone does it the same way that is important.

 

Define guidelines as a group, then follow them

Coding guidelines have no functional benefits. Their primary contribution is toward creating  a readable and maintainable design.Having common design guidelines makes code familiar to anyone familiar with the implied style, regardless of who wrote it. The primary obstacle to coding guidelines are personal preferences. It is
important that the obstacle be recognized for what it is: personal taste. There is no intrinsic value  to a particular set of guidelines.The value is in the fact that these guidelines are shared by the entire group. If even one individual does not follow them, the entire group is diminished.Coding guidelines should be enforced by using a linting tool or code reviews.

 

1. Use an identical directory structure for every project

2. Use a single module, interface, program or package in a file.

3. Specify files required by the current file using the `include directive.

4. Surround source files with ‘ifndef, ‘define and ‘endif directives.

It is very likely that more than one file would depend on the same file. If each file includes all of the file it depends on, the file would included more than once, causing compilation errors. By surrounding source files with conditional compilation directives, it will be compiled only once, even if it is included multiple times.

‘ifndef DESIGN__SV
‘define DESIGN__SV
  module design(...);
   ...
  endmodule
‘endif

5. Include a mechanism to exclude all debug statements automatically.

Debug information should be excluded by default and should be
enabled automatically via a control file or command-line options.
Do not comment out debug statements and then uncomment them
when debugging. This approach requires significant editing. When
available, use a preprocessor to achieve better runtime perfor-
mance.

Example of poor debug statement exclusion:
// $write("Address = %h, Data = %d\n", 
//        address, data);
Example of proper debug statement exclusion:
‘ifdef DEBUG
   $write("Address = %h, Data = %d\n", 
           address, data);
‘endif


6. Use this. when referring to data members.

Explicitly using  this. documents that you are referring to a data members instead of a variable currently in scope. Variables in scope are usually declared nearby whereas data members can be inherited and their declarations located in different files. Furthermore, it avoid having to come up with artificially different names for the
same thing in method arguments.

class bfm;
   virtual interf sigs;
   function new(virtual interf sigs);
      this.sigs = sigs;
   endfunction: new
endclass: bfm


7.Name all begin blocks

Declarations inside an unnamed block cannot be accessed using hierarchical references. Naming a block makes it possible to be explicitly disabled. If a block is not named, some features in debugging tools may not be available. Labeling also provides for an additional opportunity to document the code.

foreach (data[i]) begin: scan_bits_lp
...
end


8. Label closing “end” keywords.

The start and end of a block may be separated by hundreds of lines. Labeling matching end keywords facilitates recognizing the end of a particular construct.

Example:
moduleFIFO(...);
...
endmodule: FIFO


9.Use symbolic constants instead of “magic” hard-coded numeric values.

Numeric values have no meaning in and of themselves. Symbolic constants add meaning and are easier to change globally. This result  is especially true if several constants have an identical value but a different meaning. Parameters, enumerals and ‘define symbols.

Example of poor constant usage:
inttable[256];
for(i=0;i<=255;i++)...
Example of good constant usage:
parameterTABLE_LENGTH = 256;
inttable[TABLE_LENGTH];
for(i=0;i<TABLE_LENGTH;i++)...
 
10. Do not specify a bit range when referring to a complete vector.
If the range of a vector is modified, all references would need to be changed to reflect the new size of the vector. Using bit ranges implicitly means that you are referring to a subset of a vector. If you want to refer to the entire vector, do not specify a bit range.
Example of poor vector reference:
bit [15:0] count;
...
count[15:0] <= count[15:0] + 1;
carry <= count[15];
Example of proper vector reference:
bit [15:0] count;
...
count <= count + 1;
carry <= count[15];

 

11. Avoid using `define symbols.

`define symbols are global to the compilation and may interfere with other symbols defined in another source file. For constant values, use parameters. If  `define symbols must be used, undefine them by using `undef when they are no longer needed.

Example of poor style using `define symbols:
`defineCYCLE100
`definens*1
always
begin
#(`CYCLE/2`ns);
clk=~clk;
end


 

Example of good style avoiding `define symbols:
parameterCYCLE=100;
`definens*1
always
begin
#(CYCLE/2`ns);
clk=~clk;
end
`undefns


12. Use prefixes to differentiate identifiers in shared space

When declaring an identifier in a shared name space, prefix it with a unique prefix that will ensure it will not collide with a similar identifier declared in another component. The suffix used has to be unique to the author or the authoring group or organization.

Example of poor shared identifier naming:
‘define DEBUG
Example of good shared identifier naming:
‘define MII_DEBUG


13. Use a nonblocking assignment for variables used outside the always or initial block where the variable was assigned.

Using nonblocking assignments prevents race conditions between blocks that read the current value of the variable and the block that updates the variable value. This assignment guarantees that simulation results will be the same across simulators or with different command-line options.

Example of coding creating race conditions:
always@(s)
begin
if(s)q=q+1;
end
always@(s)
begin
$write("Q=%b\n",q);
end


 

Example of good portable code:
always@(s)
begin
if(s)q<=q+1;
end
always@(s)
begin
$write("Q=%b\n",q);
end


14. Assign variables from a single always or initial block.

Assigning variables from a single block prevents race conditions  between blocks that may be setting a variable to different values at the same time. This assignment convention guarantees that simulation results will be the same across simulators or with different command-line options.

Example of coding that creates race conditions:
always@(s)
begin
if(s)q<=1;
end
always@(r)
begin
if(r)q<=0;
end


 

Example of good portable code:
always@(sorr)
begin
if(s)q<=1;
elseif(r)q<=0;
end


15. Do not disable tasks with output or inout arguments.

The return value of output or inout arguments of a task that is disabled is not specified in the SystemVerilog standard. Use the return statement or disable an inner begin/end block instead. This technique guarantees that simulation results will be the same across simulators or with different command-line options.

Example of coding with unspecified behavior:
taskcpu_read(output[15:0]rdat);
...
if(data_rdy)begin
rdat=data;
disablecpu_read;
end
...
endtask


 

Example of good portable code:
taskcpu_read(output[15:0]rdat);
...
if(data_rdy)begin
rdat=data;
return;
end
...
endtask


16. Do not disable blocks containing nonblocking assignments with delays.

What happens to pending nonblocking assignments performed in a disabled block is not specified in the SystemVerilog standard. Not disabling this type of block guarantees that simulation results will be the same across simulators or with different command-line options.

Example of coding with unspecified behavior:
begin:drive
addr<=#1016'hZZZZ;
...
end 
 
always @ (rst) 
begin 
if (rst) disable drive; 
end 

 

17. Do not read a wire after updating a register in the right-hang side of a continu-
ous assignment, after a delay equal to the delay of the continuous assign-
ment.                

If you read the driven wire after a delay equal to the delay of the
continuous assignment, a race condition will occur. The wire may
or may not have been updated.

Example creating a race condition: 
 
assign qb = ~q; 
assign #5 qq = q; 
initial 
begin 
Q = 1’b0; 
$write(“Qb = %b\n”, qb); 
#5; 
$write(“QQ = %b\n”, qq); 
end 


18. Do not use the bitwise operators in a Boolean context. 
 Some code coverage tools cannot interpret a bitwise operator as a logical operator and will not provide coverage on the various com- ponents of the conditions that caused the execution to take a particular branch.

Example of poor use of bitwise operator:
reg [3:0] BYTE;
reg VALID
if (BYTE & VALID) begin
   ...
end


 

Example of good use of Boolean operator:
reg [3:0] BYTE;
reg VALID
if (BYTE != 4’b0000 && VALID) begin
   ...
end


 

 



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值