Skip to content
Snippets Groups Projects
Unverified Commit c52dba71 authored by whatmough's avatar whatmough Committed by GitHub
Browse files

Update RTL-Coding-Guidelines.md

parent 92556324
No related branches found
No related tags found
No related merge requests found
......@@ -13,7 +13,7 @@ SV includes a number of more advanced language features that prevent a whole cla
This document outlines some coding guidelines for writing bug-free RTL in SV.
More generally, we offer advice for arranging RTL projects.
## SystemVerilog Coding Style
## SystemVerilog RTL Coding Style Overview
SV is a very large language with many verification-oriented features that are not relevant to writing synthesizable RTL.
Therefore, we use a strict RTL coding style, which can be summarized in the following directives:
......@@ -75,7 +75,7 @@ endmodule // my_counter
```
In addition to these guidelines, we also recommend the strict use of a pre-processor macro for register inference.
This has a number of advantages, including: 1) significant reduction in lines of code, 2) removes the risk of poor inference style, e.g. embedded logic, 3) enforces use of a rising-edge, async active-low reset, 4) allows the register inference template to be changed to suit ASIC or FPGA.
This is a fairly common practice in industry and has a number of advantages, including: 1) significant reduction in lines of code, 2) removes the risk of poor inference style, e.g. embedded logic, 3) enforces use of a rising-edge, async active-low reset, 4) allows the register inference template to be changed to suit ASIC or FPGA.
A macro is used instead of a module to reduce simulation overhead.
The CHIPKIT RTL header file (`RTL.svh`) includes a macro definition `` `FF()`` for this purpose, which replaces the traditional inference template, as shown in the snippet below.
When using FPGAs with an RTL codebase, this macro can be easily redefined to infer a synchronous reset, which is more common.
......@@ -96,176 +96,56 @@ end
`FF(count_next, count, clock, enable, reset_n, '0);
```
### Instantiated Library Components
\subsection{Instantiated Library Components}
Physical IP such as SRAMs, IO cells, clock oscillators, and synchronizers need to be instantiated in the RTL.
It's worth remembering that various versions of these cells may be required over the lifetime of the IP or full-chip, including RTL functional models as well as various ASIC and FPGA libraries.
Therefore, it is helpful to wrap instantiated components inside a module, which can then be easily switched.
Each set of wrapped component instantiation modules is stored in a different directory for each library, with the correct directory included at compile time.
%This allows the developer to swap out RTL models with ASIC or FPGA models or inference templates at both simulation and implementation time.
TODO
add intro on importance of coding guidelines and explain not much currently around
add examples of common gotchas, especially with Verilog (and how SV helps)
add all the references on this stuff
We’ve had very fast results with HLS, potentially great for exploration
For higher-performance designs, sometimes it’s nice to have more control over pipelining
We’ve used SystemVerilog extensively
Native support in commercial EDA tools
Much more compile time checking
No translation step
We’ve used a strict subset of SV for synthesizable code with good results
Easy to learn
Removes a large number of common bug classes
Great PPA results
Great correlation through front-end and back-end
One drawback is less support for some features in open source simulators
## Combinational Logic
Separate combinational logic and sequential logic (flops)
Extra compile time checking, easier pipeline adjustments, code readability
Use logic type exclusively
No need for the confusing wire/reg types
Except for netlists – use wire and use `default_nettype none to catch undeclared nets that are usually typos
Use lower-case signal names with underscores (_)
Except for top-level module port signals – all caps by convention
Use always_comb keyword for all combinational logic
Compile-time checking that latches or flops are not inferred (enforces above)
Be careful with multiplexers
Be careful with signed numbers in SV
```systemverilog
module my_module (
// …signals…
);
// Always split out logic and flops!
logic a, b, c; // Use logic type only
logic d, e, f; // Lower-case signals
always_comb a = b & c; // Single-line logic
Therefore, it is helpful to wrap instantiated components inside a module, which can then be easily switched as needed.
Each set of wrapped component instantiation modules is stored in a different directory for each library, with the correct directory included at compile time or physical implementation time.
TODO - example
### Project Directory Organization
.
+-- _config.yml
+-- _drafts
| +-- begin-with-the-crazy-ideas.textile
| +-- on-simplicity-in-technology.markdown
+-- _includes
| +-- footer.html
| +-- header.html
+-- _layouts
| +-- default.html
| +-- post.html
+-- _posts
| +-- 2007-10-29-why-every-programmer-should-play-nethack.textile
| +-- 2009-04-26-barcamp-boston-4-roundup.textile
+-- _data
| +-- members.yml
+-- _site
+-- index.html
always_comb begin // multi-line logic
d = e & f;
// more code
end
endmodule // my_module
```
```systemverilog
`default_nettype none
module my_netlist (
// …signals…
);
// No logic in netlists!
wire sig_a, sig_b; // Use wire type only
My_module0 u0 (
.clk,
.rstn,
.sig_a,
.sig_b
);
// more code
endmodule // my_netlist
`default_nettype wire
project
│ README.md
│ file001.txt
└───folder1
│ │ file011.txt
│ │ file012.txt
│ │
│ └───subfolder1
│ │ file111.txt
│ │ file112.txt
│ │ ...
└───folder2
│ file021.txt
│ file022.txt
```
## Sequential Logic
Separate combinational logic and sequential logic (flops)
Extra compile time checking, easier pipeline adjustments, code readability
Use the always_ff keyword
Compile-time checking that no flops are inferred in block (enforces above)
Stick to positive-edge clocked, active-low asynchronous reset flops
Use macro definition for inferring flops
Enforces separation of logic and flops
More compact, but still readable
Easily swap out for different flops, e.g. synchronous reset for FPGA
Use flop/RAM enable terms -> clock/RAM gating
```systemverilog
module my_module (
// …signals…
);
// Always split out logic and flops!
logic d_in, q_out; // Use logic type only
always_ff @(posedge clk, negedge rstn) begin
if(!rstn)
q_out <= ‘0;
else
if(en)
q_out <= d_in;
end
endmodule // my_module
```
```systemverilog
`include RTL.svh
module my_module (
// …signals…
);
// Always split out logic and flops!
logic d_in, q_out; // Use logic type only
`FF(d_in, q_out, clk, en, rstn, ‘0);
endmodule // my_module
```
## Module Declarations and Instantiations
Use the SV syntax for module declarations
Saves typing
For module instantiation, use the automatic SV connections
Use SV packages to group common functions and definitions
```systemverilog
module my_module (
input logic clk,
input logic rstn,
// …more signals…
);
// Module body
my_module2 u0 (
.clk, // automatic connect
.rstn,
// …more signals…
.signal99(),v // unused output
.signal100(other_sig) // override automatic
);
endmodule // my_module
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment