diff --git a/tools/rtl-coding/RTL-Coding-Guidelines.md b/tools/rtl-coding/RTL-Coding-Guidelines.md index 9de6c015759f0fe73f14cf2c97a0c9211d64562f..dc2bb125cc934264123a4853fa65a472741c30f8 100644 --- a/tools/rtl-coding/RTL-Coding-Guidelines.md +++ b/tools/rtl-coding/RTL-Coding-Guidelines.md @@ -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 -```