| --- |
| title: "Verilog Coding Style Guide" |
| --- |
| |
| ## Basics |
| |
| ### Summary |
| |
| Verilog is the main logic design language for lowRISC Comportable IP. |
| |
| Verilog and SystemVerilog (often generically referred to as just "Verilog" in this document) can be written in vastly different styles, which can lead to code conflicts and code review latency. |
| This style guide aims to promote Verilog readability across groups. |
| To quote the C++ style guide: "Creating common, required idioms and patterns makes code much easier to understand." |
| |
| This guide defines the Comportable style for Verilog. |
| The goals are to: |
| |
| * promote consistency across hardware development projects |
| * promote best practices |
| * increase code sharing and re-use |
| |
| This style guide defines style for both Verilog-2001 and SystemVerilog compliant code. |
| Additionally, this style guide defines style for both synthesizable and test bench code. |
| |
| See the [Appendix](#appendix---condensed-style-guide) for a condensed tabular representation of this style guide. |
| |
| |
| ### Terminology Conventions |
| |
| Unless otherwise noted, the following terminology conventions apply to this |
| style guide: |
| |
| * The word ***must*** indicates a mandatory requirement. |
| Similarly, ***do not*** indicates a prohibition. |
| Imperative and declarative statements correspond to ***must***. |
| * The word ***recommended*** indicates that a certain course of action is preferred or is most suitable. |
| Similarly, ***not recommended*** indicates that a course of action is unsuitable, but not prohibited. |
| There may be reasons to use other options, but the implications and reasons for doing so must be fully understood. |
| * The word ***may*** indicates a course of action is permitted and optional. |
| * The word ***can*** indicates a course of action is possible given material, physical, or causal constraints. |
| |
| ### Default to C-like Formatting |
| |
| ***Where appropriate, format code consistent with |
| https://google.github.io/styleguide/cppguide.html*** |
| |
| Verilog is a C-like language, and where appropriate, we default to being consistent with |
| [Google's C++ Style Guide](https://google.github.io/styleguide/cppguide.html). |
| |
| In particular, we inherit these specific formatting guidelines: |
| |
| * Generally, [names](#naming) should be descriptive and avoid abbreviations. |
| * Non-ASCII characters are forbidden. |
| * Indentation uses spaces, no tabs. |
| Indentation is two spaces for nesting, four spaces for line continuation. |
| * Place a space between `if` and the parenthesis in [conditional expressions](https://google.github.io/styleguide/cppguide.html#Conditionals). |
| * Use horizontal whitespace around operators, and avoid trailing whitespace at the end of lines. |
| * Maintain consistent and good [punctuation, spelling, and grammar](https://google.github.io/styleguide/cppguide.html#Punctuation,_Spelling_and_Grammar) (within comments). |
| * Use standard formatting for [comments](#comments), including C-like formatting for [TODO](https://google.github.io/styleguide/cppguide.html#TODO_Comments) and [deprecation](https://google.github.io/styleguide/cppguide.html#Deprecation_Comments). |
| |
| ### Style Guide Exceptions |
| |
| ***Justify all exceptions with a comment.*** |
| |
| No style guide is perfect. |
| There are times when the best path to a working design, or for working around a tool issue, is to simply cut the Gordian Knot and create code that is at variance with this style guide. |
| It is always okay to deviate from the style guide by necessity, as long as that necessity is clearly justified by a brief comment, as well as a lint waiver pragma where appropriate. |
| |
| ### Which Verilog to Use |
| |
| ***Prefer SystemVerilog-2012.*** |
| |
| All RTL and tests should be developed in SystemVerilog, following the [SystemVerilog-2012 standard], except for [prohibited features](#problematic-language-features-and-constructs). |
| |
| [SystemVerilog-2012 standard]: http://ieeexplore.ieee.org/servlet/opac?punumber=6469138 |
| |
| ## Verilog/SystemVerilog Conventions |
| |
| ### Summary |
| |
| This section addresses primarily aesthetic aspects of style: line length, indentation, spacing, etc. |
| |
| ### File Extensions |
| |
| ***Use the `.sv` extension for SystemVerilog files (or `.svh` for files that are included via the preprocessor).*** |
| |
| File extensions have the following meanings: |
| |
| * `.sv` indicates a SystemVerilog file defining a module or package. |
| * `.svh` indicates a SystemVerilog header file intended to be included in another file using a preprocessor `` `include`` directive. |
| * `.v` indicates a Verilog-2001 file defining a module or package. |
| * `.vh` indicates a Verilog-2001 header file. |
| |
| Only `.sv` and `.v` files are intended to be compilation units. |
| `.svh` and `.vh` files may only be `` `include``-ed into other files. |
| |
| With exceptions of netlist files, each .sv or .v file should contain only one module, and the name should be associated. |
| For instance, file `foo.sv` should contain only the module `foo`. |
| |
| ### General File Appearance |
| |
| #### Characters |
| |
| ***Use only ASCII characters with UNIX-style line endings(`"\n"`).*** |
| |
| #### POSIX File Endings |
| |
| ***All lines on non-empty files must end with a newline (`"\n"`).*** |
| |
| #### Line Length |
| |
| ***Wrap the code at 100 characters per line.*** |
| |
| The maximum line length for style-compliant Verilog code is 100 characters per line. |
| |
| Exceptions: |
| |
| - Any place where line wraps are impossible (for example, an include path might extend past 100 characters). |
| |
| [Line-wrapping](#line-wrapping) contains additional guidelines on how to wrap long lines. |
| |
| #### No Tabs |
| |
| ***Do not use tabs anywhere.*** |
| |
| Use spaces to indent or align text. |
| See [Indentation](#indentation) for rules about indentation and wrapping. |
| |
| To convert tabs to spaces on any file, you can use the [UNIX `expand`](http://linux.die.net/man/1/expand) utility. |
| |
| #### No Trailing Spaces |
| |
| ***Delete trailing whitespace at the end of lines.*** |
| |
| ### Begin / End |
| |
| ***Use `begin` and `end` unless the whole statement fits on a single line.*** |
| |
| If a statement wraps at a block boundary, it must use `begin` and `end.` Only if a whole semicolon-terminated statement fits on a single line can `begin` and `end` be omitted. |
| |
| 👍 |
| ```systemverilog {.good} |
| // Wrapped procedural block requires begin and end. |
| always_ff @(posedge clk) begin |
| q <= d; |
| end |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| // The exception case, where begin and end may be omitted as the entire |
| // structure fits on a single line. |
| always_ff @(posedge clk) q <= d; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| // Incorrect because a wrapped statement must have begin and end. |
| always_ff @(posedge clk) |
| q <= d; |
| ``` |
| |
| `begin` must be on the same line as the preceding keyword, and ends the line. |
| `end` must start a new line. |
| `end else begin` must be together on one line. |
| The only exception is if `end` has a label, a following `else` should be on a new line. |
| |
| 👍 |
| ```systemverilog {.good} |
| // "end else begin" are on the same line. |
| if (condition) begin |
| foo = bar; |
| end else begin |
| foo = bum; |
| end |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| // begin/end are omitted because each semicolon-terminated statement fits on |
| // a single line. |
| if (condition) foo = bar; |
| else foo = bum; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| // Incorrect because "else" must be on the same line as "end". |
| if (condition) begin |
| foo = bar; |
| end |
| else begin |
| foo = bum; |
| end |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| // An exception is made for labeled blocks. |
| if (condition) begin : a |
| foo = bar; |
| end : a |
| else begin : b |
| foo = bum; |
| end : b |
| ``` |
| |
| The above style also applies to individual case items within a case statement. |
| `begin` and `end` may be omitted if the entire case item (the case expression and the associated statement) fits on a single line. |
| Otherwise, use the `begin` keyword on the same line as the case expression. |
| |
| 👍 |
| ```systemverilog {.good} |
| // Consistent use of begin and end for each case item is good. |
| unique case (state) |
| StIdle: begin |
| next_state = StA; |
| end |
| StA: begin |
| next_state = StB; |
| end |
| StB: begin |
| next_state = StIdle; |
| foo = bar; |
| end |
| default: begin |
| next_state = StIdle; |
| end |
| endcase |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| // Case items that fit on a single line may omit begin and end. |
| unique case (state) |
| StIdle: next_state = StA; |
| StA: next_state = StB; |
| StB: begin |
| next_state = StIdle; |
| foo = bar; |
| end |
| default: next_state = StIdle; |
| endcase |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| unique case (state) |
| StIdle: // These lines are incorrect because we should not wrap |
| next_state = StA; // case items at a block boundary without using begin |
| StA: // and end. Case items should fit on a single line, or |
| next_state = StB; // else the procedural block must have begin and end. |
| StB: begin |
| foo = bar; |
| next_state = StIdle; |
| end |
| default: begin |
| next_state = StIdle; |
| end |
| endcase |
| ``` |
| |
| ### Indentation |
| |
| ***Indentation is two spaces per level.*** |
| |
| Use spaces for indentation. |
| Do not use tabs. |
| You should set your editor to emit spaces when you hit the tab key. |
| |
| #### Indented Sections |
| |
| Always add an additional level of indentation to the enclosed sections of all paired keywords. |
| Examples of SystemVerilog keyword pairs: `begin / end`, `module / endmodule`, `package / endpackage`, `class / endclass`, `function / endfunction`. |
| |
| #### Line Wrapping |
| |
| When wrapping a long expression, indent the continued part of the expression by four spaces, like this: |
| |
| 👍 |
| ```systemverilog {.good} |
| assign zulu = enabled && ( |
| alpha < bravo && |
| charlie < delta); |
| |
| assign addr = addr_gen_function_with_many_params( |
| thing, other_thing, long_parameter_name, x, y, |
| extra_param1, extra_param2); |
| |
| assign structure = '{ |
| src: src, |
| dest: dest, |
| default: '0}; |
| ``` |
| |
| Or, if it improves readability, align the continued part of the expression with a grouping open parenthesis or brace, like this: |
| |
| ```systemverilog |
| assign zulu = enabled && (alpha < bravo && |
| charlie < delta); |
| |
| assign addr = addr_gen_function(thing, other_thing, |
| long_parameter_name, |
| x, y); |
| |
| assign structure = '{src: src, |
| dest: dest, |
| default: '0}; |
| ``` |
| |
| Operators in a wrapped expression can be placed at either the end or the beginning of each line, but this must be done consistently within a file. |
| |
| #### Preprocessor Directives |
| |
| ***Keep branching preprocessor directives left-aligned and un-indented.*** |
| |
| Keep branching preprocessor directives (`` `ifdef``, `` `ifndef``, `` `else``, `` `elsif``, `` `endif``) aligned to the left, even if they are nested. |
| Indent the conditional branches of text as if the preprocessor directives were absent. |
| Non-branching preprocessor directives must follow the same indentation rules as the regular code. |
| |
| 👍 |
| ```systemverilog {.good} |
| package foo; |
| `ifdef FOO // good: branching directive left-aligned |
| `include "foo.sv"; // normal indentation for non-branching directives |
| parameter bit A = 1; // normal indentation for the regular code |
| `ifdef BAR // good: branching directive left-aligned |
| parameter bit A = 2; |
| `else |
| parameter bit A = 3; |
| `endif |
| `endif |
| endpackage : foo |
| ``` |
| |
| Un-indented branching preprocessor directives disrupt the flow of reading to emphasize that there is conditional text. |
| Leaving conditional branch text un-indented will result in post-preprocessed text looking properly indented. |
| |
| ### Spacing |
| |
| #### Comma-delimited Lists |
| |
| ***For multiple items on a line, one space must separate the comma and the next character.*** |
| |
| Additional whitespace is allowed for readability. |
| |
| 👍 |
| ```systemverilog {.good} |
| bus = {addr, parity, data}; |
| a = myfunc(lorem, ipsum, dolor, sit, amet, consectetur, adipiscing, elit, |
| rhoncus); |
| mymodule mymodule(.a(a), .b(b)); |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| {parity,data} = bus; |
| a = myfunc(a,b,c); |
| mymodule mymodule(.a(a),.b(b)); |
| ``` |
| |
| #### Tabular Alignment |
| |
| ***Adding whitespace to cause related things to align is encouraged.*** |
| |
| Where it is reasonable to do so, align a group of two or more similar lines so that the identical parts are directly above one another. |
| This alignment makes it easy to see which characters are the same and which characters are different between lines. |
| |
| Use spaces, not tabs. |
| |
| For example: |
| |
| ```systemverilog |
| logic [7:0] my_interface_data; |
| logic [15:0] my_interface_address; |
| logic my_interface_enable; |
| ``` |
| |
| #### Expressions |
| |
| ***Include whitespace on both sides of all binary operators.*** |
| |
| Use spaces around binary operators. |
| Add sufficient whitespace to aid readability. |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| assign a = ((addr & mask) == My_addr) ? b[1] : ~b[0]; // good |
| ``` |
| |
| is better than |
| |
| 👎 |
| ```systemverilog {.bad} |
| assign a=((addr&mask)==My_addr)?b[1]:~b[0]; // bad |
| ``` |
| |
| **Exception:** when declaring a bit vector, it is acceptable to use the compact notation. |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| wire [WIDTH-1:0] foo; // this is acceptable |
| wire [WIDTH - 1 : 0] foo; // fine also, but not necessary |
| ``` |
| |
| When splitting alternation expressions into multiple lines, use a format that is similar to an equivalent if-then-else line. |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| assign a = ((addr & mask) == `MY_ADDRESS) ? |
| matches_value : |
| doesnt_match_value; |
| ``` |
| |
| #### Array Dimensions in Declarations |
| |
| Add a space around packed dimensions. |
| |
| Do not add a space: |
| |
| - between identifier and unpacked dimensions. |
| - between multiple dimensions. |
| |
| Applies to packed and unpacked arrays as well as dynamic arrays, associative arrays, and queues. |
| |
| 👍 |
| ```systemverilog {.good} |
| logic [7:0][3:0] data[128][2]; |
| typedef logic [31:0] word_t; |
| bit bit_array[512]; |
| data_t some_array[]; |
| data_t some_map[addr_t]; |
| data_t some_q[$]; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| // There must not be a space between dimensions. |
| logic [7:0] [3:0] data[128] [2]; |
| // There must be a space around packed dimensions. |
| typedef logic[31:0]word_t; |
| // There must not be a space between identifier and unpacked dimension. |
| bit bit_array [512]; |
| // Dynamic, associative, and queue "dimensions" are treated the same as unpacked |
| // dimensions. There must not be a space. |
| data_t some_array []; |
| data_t some_map [addr_t]; |
| data_t some_q [$]; |
| ``` |
| |
| #### Parameterized Types |
| |
| ***Add one space before type parameters, except when the type is part of a qualified name.*** |
| |
| A qualified name contains at least one scope `::` operator connecting its segments. |
| A space in a qualified name would break the continuity of a reference to one symbol, so it must not be added. |
| Parameter lists must follow the [space-after-comma](#comma-delimited-lists) rule. |
| |
| 👍 |
| ```systemverilog {.good} |
| my_fifo #(.WIDTH(4), .DEPTH(2)) my_fifo_nibble ... |
| |
| class foo extends bar #(32, 8); // unqualified base class |
| ... |
| endclass |
| |
| foo_h = my_class#(.X(1), .Y(0))::type_id::create("foo_h"); // static method call |
| |
| my_pkg::x_class#(8, 1) bar; // package-qualified name |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| my_fifo#(.WIDTH(4), .DEPTH(2)) my_fifo_2by4 ... |
| |
| class foo extends bar#(32, 8); // unqualified base class |
| ... |
| endclass |
| |
| foo_h = my_class #(.X(1), .Y(0))::type_id::create("foo_h"); // static method call |
| |
| my_pkg::x_class #(8, 1) bar; // package-qualified name |
| ``` |
| |
| #### Labels |
| |
| ***When labeling code blocks, add one space before and after the colon.*** |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| begin : foo |
| end : foo |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| end:bar // There must be a space before and after the colon. |
| endmodule: foobar // There must be a space before the colon. |
| ``` |
| |
| #### Case items |
| |
| There must be no whitespace before a case item's colon; there must be at least one space after the case item's colon. |
| |
| The `default` case item must include a colon. |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| unique case (my_state) |
| StInit: $display("Shall we begin"); |
| StError: $display("Oh boy this is Bad"); |
| default: begin |
| my_state = StInit; |
| interrupt = 1; |
| end |
| endcase |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| unique case (1'b1) |
| (my_state == StError) : interrupt = 1; // Excess whitespace before colon |
| default:begin end // Missing space after colon |
| endcase |
| ``` |
| |
| #### Function And Task Calls |
| |
| ***Function and task calls must not have any spaces between the function name or task name and the open parenthesis.*** |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| process_packet(pkt); |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| process_packet (pkt); // There must not be a space before "(" |
| ``` |
| |
| #### Macro Calls |
| |
| ***Macro calls must not have any spaces between the macro name and the open parenthesis.*** |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| `uvm_error(ID, "you fail") |
| `ASSERT(name, a & b, clk, rst) |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| `uvm_error (ID, "you fail") // There must not be a space before "(" |
| `ASSERT (name, a & b, clk, rst) |
| ``` |
| |
| #### Line Continuation |
| |
| ***It is mandatory to right-align line continuations.*** |
| |
| Aligning line continuations ('`\ `' character) helps visually mark the end of a multi-line macro. |
| The position of alignment only needs to be beyond the rightmost extent of a multi-line macro by at least one space, when a space does not split a token, but should not exceed the maximum line length. |
| |
| ```systemverilog |
| `define REALLY_LONG_MACRO(arg1, arg2, arg3) \ |
| do_something(arg1); \ |
| do_something_else(arg2); \ |
| final_action(arg3); |
| ``` |
| |
| #### Space Around Keywords |
| |
| ***Include whitespace before and after SystemVerilog keywords.*** |
| |
| Do not include a whitespace: |
| |
| - before keywords that immediately follow a group opening, such as an open parenthesis. |
| - before a keyword at the beginning of a line. |
| - after a keyword at the end of a line. |
| |
| For example: |
| |
| ```systemverilog |
| // Normal indentation before if. Include a space after if. |
| if (foo) begin |
| end |
| // Include a space after always, but not before posedge. |
| always_ff @(posedge clk) begin |
| end |
| ``` |
| |
| ### Parentheses |
| |
| ***Use parentheses to make operations unambiguous.*** |
| |
| In any instance where a reasonable human would need to expend thought or refer to an operator precedence chart, use parentheses instead to make the order of operations unambiguous. |
| |
| #### Ternary Expressions |
| |
| ***Nested ternary expressions must be enclosed in parentheses.*** |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| assign state_next = condition_b ? |
| (condition_a ? |
| a_and_b : |
| b_and_not_a) : |
| state; |
| ``` |
| |
| While the following nested ternary has only one meaning to the compiler, the meaning can be unclear and error-prone to humans: |
| |
| 👎 |
| ```systemverilog {.bad} |
| assign state_next = condition_b ? |
| condition_a ? |
| a_and_b : |
| b_and_not_a : |
| state; |
| ``` |
| |
| ### Comments |
| |
| ***C++ style comments (`// foo`) are preferred. |
| C style comments (`/* bar */`) can also be used.*** |
| |
| A comment on its own line describes the code that follows. |
| A comment on a line with code describes that line of code. |
| |
| For example: |
| |
| ```systemverilog |
| // This comment describes the following module. |
| module foo; |
| ... |
| endmodule : foo |
| |
| localparam bit ValBaz = 1; // This comment describes the item to the left. |
| ``` |
| |
| ### Declarations |
| |
| ***Signals must be declared before they are used. |
| This means that implicit net declarations must not be used.*** |
| |
| Within modules, it is **recommended** that signals, types, enums, and localparams be declared close to their first use. |
| This makes it easier for the reader to find the declaration and see the signal type. |
| |
| ### Basic Template |
| |
| ***A template that demonstrates many of the items is given below.*** |
| |
| Template: |
| |
| ```systemverilog |
| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // One line description of the module |
| |
| module my_module #( |
| parameter Width = 80, |
| parameter Height = 24 |
| ) ( |
| input clk_i, |
| input rst_ni, |
| input req_valid_i, |
| input [Width-1:0] req_data_i, |
| output req_ready_o, |
| ... |
| ); |
| |
| logic [Width-1:0] req_data_masked; |
| |
| submodule u_submodule ( |
| .clk_i, |
| .rst_ni, |
| .req_valid_i, |
| .req_data_i (req_data_masked), |
| .req_ready_o, |
| ... |
| ); |
| |
| always_comb begin |
| req_data_masked = req_data_i; |
| case (fsm_state_q) |
| ST_IDLE: begin |
| req_data_masked = req_data_i & MASK_IDLE; |
| ... |
| end |
| |
| ... |
| |
| endmodule |
| ``` |
| |
| ## Naming |
| |
| ### Summary |
| |
| | Construct | Style | |
| | ------------------------------------ | ----------------------- | |
| | Declarations (module, class, package, interface) | `lower_snake_case` | |
| | Instance names | `lower_snake_case` | |
| | Signals (nets and ports) | `lower_snake_case` | |
| | Variables, functions, tasks | `lower_snake_case` | |
| | Named code blocks | `lower_snake_case` | |
| | \`define macros | `ALL_CAPS` | |
| | Tunable parameters for parameterized modules, classes, and interfaces | `UpperCamelCase` | |
| | Constants | `ALL_CAPS` or `UpperCamelCase` | |
| | Enumeration types | `lower_snake_case_e` | |
| | Other typedef types | `lower_snake_case_t` | |
| | Enumerated value names | `UpperCamelCase` | |
| |
| ### Constants |
| |
| ***Declare global constants using parameters in the project package file.*** |
| |
| In this context, **constants** are distinct from tuneable parameters for objects such as parameterized modules, classes, etc. |
| |
| Explicitly declare the type for constants. |
| |
| When declaring a constant: |
| |
| * within a package use `parameter`. |
| * within a module or class use `localparam`. |
| |
| The preferred method of defining constants is to declare a `package` and declare all constants as a `parameter` within that package. |
| If the constants are to be used in only one file, it is acceptable to keep them defined within that file rather than a separate package. |
| |
| Define project-wide constants in the project's main package. |
| |
| Other packages may also be declared with their own `parameter` constants to facilitate the creation of IP that may be re-used across many projects. |
| |
| The preferred naming convention for all immutable constants is to use `ALL_CAPS`, but there are times when the use of `UpperCamelCase` might be considered more natural. |
| |
| | Constant Type | Style Preference | Conversation | |
| | ---- | ---- | ---- | |
| | \`define | `ALL_CAPS` | Truly constant | |
| | module parameter | `UpperCamelCase` | truly modifiable by instantiation, not constant | |
| | derived localparam | `UpperCamelCase` | while not modified directly, still tracks module parameter | |
| | tuneable localparam | `UpperCamelCase` | while not expected to change upon final RTL version, is used by designer to explore the design space conveniently | |
| | true localparam constant | `ALL_CAPS` | Example `localparam OP_JALR = 8'hA0;` | |
| | enum member true constant | `ALL_CAPS` | Example `typedef enum ... { OP_JALR = 8'hA0;` | |
| | enum set member | `ALL_CAPS` or `UpperCamelCase` | Example `typedef enum ... { ST_IDLE, ST_FRAME_START, ST_DYN_INSTR_READ ...`, `typedef enum ... { StIdle, StFrameStart, StDynInstrRead...`. A collection of arbitrary values, could be either convention. | |
| |
| The units for a constant should be described in the symbol name, unless the constant is unitless or the units are "bits." For example, `FooLengthBytes`. |
| |
| Example: |
| |
| 👍 |
| ```systemverilog {.good} |
| // package-scope |
| package my_pkg; |
| |
| parameter int unsigned NUM_CPU_CORES = 64; |
| // reference elsewhere as my_pkg::NUM_CPU_CORES |
| |
| endpackage |
| ``` |
| |
| #### Parameterized Objects (modules, etc.) |
| |
| ***Use `parameter` to parameterize, and `localparam` to declare module-scoped constants.*** |
| |
| You can create parameterized modules, classes, and interfaces to facilitate design re-use. |
| |
| Use the keyword `parameter` within the `module` declaration of a parameterized module to indicate what parameters the user is expected to tune at instantiation. |
| The preferred naming convention for all parameters is `UpperCamelCase`. |
| Some projects may choose to use `ALL_CAPS` to differentiate tuneable parameters from constants. |
| |
| The preference for derived parameters within the `module` declaration is to use `localparam`, **however** currently several tools do not accept this legal (since SystemVerilog 2009) construct. |
| **For now** all derived parameters should use `parameter` with a comment `// derived parameter` and create a static assertion with the name prefix `paramCheck` somewhere within the module. |
| An example is shown below. |
| |
| ```systemverilog |
| // ideal, but currently untenable declaration |
| module modname #( |
| parameter int Depth = 2048, // 8kB default |
| localparam int Aw = $clog2(Depth) // derived parameter |
| ) ( |
| ... |
| ); |
| |
| // current declaration method with assertion |
| module modname #( |
| parameter int Depth = 2048, // 8kB default |
| parameter int Aw = $clog2(Depth) // derived parameter |
| ) ( |
| ... |
| ); |
| |
| `ASSERT_INIT(paramCheckAw, Aw == $clog2(Depth)) |
| |
| // alternate, expanded assertion macro |
| |
| initial begin |
| paramCheckAw: assert (Aw == $clog2(Depth)) \ |
| else $error("Assert failed: [%m] paramCheckAw, (Aw == $clog2(Depth))") |
| end |
| |
| ... |
| |
| endmodule |
| ``` |
| |
| `` `define`` and `defparam` should never be used to parameterize a module. |
| |
| Use [package parameters](#constants) to transmit global constants through a hierarchy instead of parameters. |
| To declare a constant whose scope is internal to the module, [use `localparam` instead](#constants). |
| |
| Examples of when to use parameterized modules: |
| |
| - When multiple instances of a module will be instantiated, and need to be differentiated by a parameter. |
| - As a means of specializing a module for a specific bus width. |
| - As a means of documenting which global parameters are permitted to change within the module. |
| |
| Explicitly declare the type for parameters. |
| |
| Use the type of the parameter to help constrain the legal range. |
| E.g. `int unsigned` for general non-negative integer valuess, `bit` for boolean values. |
| Any further restrictions on tuneable parameter values must be documented with assertions. |
| |
| Tuneable parameter values should always have reasonable defaults. |
| |
| For additional reading, see [New Verilog-2001 Techniques for Creating Parameterized Models](https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-884-complex-digital-systems-spring-2005/related-resources/parameter_models.pdf). |
| |
| ### Macro Definitions |
| |
| ***Macros should be ALL\_CAPITALS with underscores.*** |
| |
| Macros should be all capitals with underscores. |
| |
| A **global define** is a tick-defined macro in a header file that is shared by all source files in a project. |
| To reduce namespace collisions, global defines should be prefixed by the name of a group of related macros, followed by a pair of underscores: |
| |
| ```systemverilog |
| // The following two constants are in the FOO namespace of the |
| // SN chip. |
| `define SN_FOO__ALPHA_BETA 5 |
| `define SN_FOO__GAMMA_OMEGA 6 |
| ``` |
| |
| A **local define** is a tick-defined macro that should only be used within the scope of a single local file. |
| It must be explicitly undefined after use, to avoid polluting the global macro namespace. |
| To indicate that a macro is only meant to be used in the local scope, the macro name should be prefixed with a single underscore. |
| |
| To ensure that local defines stay local, be careful not to `` `include`` other files between the macro definition and `` `undef``. |
| |
| Example: |
| |
| ```systemverilog |
| `define _MAKE_THING(_x) \ |
| thing i_thing_##_x (.clk(clk), .i(i##_x) .o(o##_x)); |
| `_MAKE_THING(a) |
| `_MAKE_THING(b) |
| `_MAKE_THING(c) |
| `undef _MAKE_THING |
| ``` |
| |
| ### Suffixes |
| |
| Suffixes are used in several places to give guidance to intent. |
| The following table lists the suffixes that have special meaning. |
| |
| | Suffix(es) | Arena | Intent | |
| | --- | :---: | --- | |
| | `_e` | typedef | Enumerated types | |
| | `_t` | typedef | Other typedefs, including signal clusters | |
| | `_n` | signal name | Active low signal | |
| | `_n`, `_p` | signal name | Differential pair, active low and active high | |
| | `_d`, `_q` | signal name | Input and output of register | |
| | `_q2`,`_q3`, etc | signal name | Pipelined versions of signals; `_q` is one cycle of latency, `_q2` is two cycles, `_q3` is three, etc | |
| | `_i`, `_o`, `_io` | signal name | Module inputs, outputs, and bidirectionals | |
| |
| When multiple suffixes are necessary use the following guidelines: |
| |
| * Guidance suffixes are added together and not separated by additional `_` characters (`_ni` not `_n_i`) |
| * If the signal is active low `_n` will be the first suffix |
| * If the signal is a module input/output the letters will come last. |
| * It is not mandatory to propagate `_d` and `_q` to module boundaries. |
| |
| Example: |
| |
| 👍 |
| ```systemverilog {.good} |
| module simple ( |
| input clk_i, |
| input rst_ni, // Active low reset |
| |
| // writer interface |
| input [15:0] data_i, |
| input valid_i, |
| output ready_o, |
| |
| // bi-directional bus |
| inout [7:0] driver_io, // Bi directional signal |
| |
| // Differential pair output |
| output lvds_po, // Positive part of the differential signal |
| output lvds_no // Negative part of the differential signal |
| ); |
| |
| logic valid_d, valid_q, valid_q2, valid_q3; |
| assign valid_d = valid_i; // next state assignment |
| |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| valid_q <= '0; |
| valid_q2 <= '0; |
| valid_q3 <= '0; |
| end else begin |
| valid_q <= valid_d; |
| valid_q2 <= valid_q; |
| valid_q3 <= valid_q2; |
| end |
| end |
| |
| assign ready_o = valid_q3; // three clock cycles delay |
| |
| endmodule // simple |
| ``` |
| |
| ### Enumerations |
| |
| ***Name enumeration types `snake_case_e`. |
| Name enumeration values `ALL_CAPS` or `UpperCamelCase`.*** |
| |
| Always name `enum` types using `typedef`. |
| The storage type of any enumerated type must be specified. |
| For synthesizable enums, the storage type must be a 4-state data type (`logic` rather than `bit`). |
| |
| Anonymous `enum` types are not allowed as they make it harder to use the type in other places throughout the project and across projects. |
| |
| Enumeration type names should contain only lower-case alphanumeric characters and underscores. |
| You must suffix enumeration type names with `_e`. |
| |
| Enumeration value names (constants) should typically be `ALL_CAPS`, for example, `READY_TO_SEND`, to reflect their constant nature, especially for truly unchangeable values like defined opcode assignments. |
| There are times when `UpperCamelCase` might be preferred, when the enumerated type's assigned value is effectively a don't care to the designer, like state machine values. |
| See the conversation on [constants](#constants) for a discussion on how to think of this recommendation. |
| |
| 👍 |
| ```systemverilog {.good} |
| typedef enum logic [7:0] { // 8-bit opcodes |
| OP_JALR = 8'hA0, |
| OP_ADDI = 8'h47, |
| OP_LDW = 8'h0B |
| } opcode_e; |
| opcode_e op_val; |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| typedef enum logic [1:0] { // A 2-bit enumerated type |
| ACC_WRITE, |
| ACC_READ, |
| ACC_PAUSE |
| } access_e; // new named type is created |
| access_e req_access, resp_access; |
| ``` |
| |
| 👍 |
| ```systemverilog {.good} |
| typedef enum logic [1:0] { // A 2-bit enumerated type |
| AccWrite, |
| AccRead, |
| AccPause |
| } access_e; // new named type is created |
| access_e req_access, resp_access; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| enum { // Typedef is missing, storage type is missing. |
| Write, |
| Read |
| } req_access, resp_access; // anonymous enum type |
| ``` |
| |
| ### Signal Naming |
| |
| ***Use `lower_snake_case` when naming signals.*** |
| |
| In this context, a **signal** is meant to mean a net, variable, or port within a SystemVerilog design. |
| |
| Signal names may contain lowercase alphanumeric characters and underscores. |
| |
| Signal names should never end with an underscore followed by a number (for example, `foo_1`, `foo_2`, etc.). |
| Many synthesis tools map buses into nets using that naming convention, so similarly named nets can lead to confusion when examining a synthesized netlist. |
| |
| Reserved [Verilog](http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_1/ite_r_verilog_reserved_words.htm) or [SystemVerilog-2012 standard] keywords may never be used as names. |
| |
| When interoperating with different languages, be mindful not to use keywords from other languages. |
| |
| #### Use descriptive names |
| |
| ***Names should describe what a signal's purpose is.*** |
| |
| Use whole words. |
| Avoid abbreviations and contractions except in the most common places. |
| Favor descriptive signal names over brevity. |
| |
| #### Prefixes |
| |
| Use common prefixes to identify groups of signals that operate together. |
| For example, all elements of an AXI-S interface would share a prefix: `foo_valid`, `foo_ready`, and `foo_data`. |
| |
| Additionally, prefixes should be used to clearly label which signal is in which clock group for any module with multiple clocks. |
| See the section on [clock domains](#clocks) for more details. |
| |
| Examples: |
| |
| - Signals associated with controlling a blockram might share a `bram_` prefix. |
| - Signals that are synchronous with `clk_dram` rather than `clk` should share a `dram_` prefix. |
| |
| Code example: |
| |
| 👍 |
| ```systemverilog {.good} |
| module fifo_controller ( |
| input clk_i, |
| input rst_ni, |
| |
| // writer interface |
| input [15:0] wr_data_i, |
| input wr_valid_i, |
| output wr_ready_o, |
| |
| // reader interface |
| output [15:0] rd_data_o, |
| output rd_valid_o, |
| output [7:0] rd_fullness_o, |
| input rd_ack_i, |
| |
| // memory interface: |
| output [7:0] mem_addr_o, |
| output [15:0] mem_wdata_o, |
| output mem_we_o, |
| input [15:0] mem_rdata_i |
| ); |
| ``` |
| |
| This naming convention makes it easier to map port names onto similar signal names using simple and consistent rules. |
| See the section on [Hierarchical Consistency](#hierarchical-consistency) for more information. |
| |
| #### Hierarchical consistency |
| |
| ***The same signal should have the same name at any level of the hierarchy.*** |
| |
| A signal that connects to a port of an instance should have the same name as that port. |
| By proceeding in this manner, signals that are directly connected should maintain the same name at any level of hierarchy. |
| |
| Exceptions to this convention are expected, such as: |
| |
| * When connecting a port to an element of an array of signals. |
| |
| * When mapping a generic port name to something more specific to the design. |
| For example, two generic blocks, one with a `master_bus` port and one with a `slave_bus` port might be connected by a `foo_bar_bus` signal. |
| |
| In each exceptional case, care should be taken to make the mapping of port names to signal names as unambiguous and consistent as possible. |
| |
| ### Clocks |
| |
| ***All clock signals must begin with `clk`.*** |
| |
| The main system clock for a design must be named `clk`. |
| It is acceptable to use `clk` to refer to the default clock that the majority of the logic in a module is synchronous with. |
| |
| If a module contains multiple clocks, the clocks that are not the system clock should be named with a unique identifier, preceded by the `clk_` prefix. |
| For example: `clk_dram`, `clk_axi`, etc. |
| Note that this prefix will be used to identify other signals in that clock domain. |
| |
| ### Resets |
| |
| ***Resets are active-low and asynchronous. |
| The default name is `rst_n`.*** |
| |
| Chip wide all resets are defined as active low and asynchronous. |
| Thus they are defined as tied to the asynchronous reset input of the associated standard cell registers. |
| |
| The default name is `rst_n`. |
| If they must be distinguished by their clock, the clock name should be included in the reset name like `rst_domain_n`. |
| |
| SystemVerilog allows either of the following syntax styles, but the style guide prefers the former. |
| |
| ```systemverilog |
| // preferred |
| always_ff @(posedge clk or negedge rst_n) begin |
| if (!rst_n) begin |
| q <= 1'b0; |
| end else begin |
| q <= d; |
| end |
| end |
| |
| // legal but not preferred |
| always_ff @(posedge clk, negedge rst_n) begin |
| if (!rst_n) begin |
| q <= 1'b0; |
| end else begin |
| q <= d; |
| end |
| end |
| ``` |
| |
| ## Language Features |
| |
| ### Preferred SystemVerilog Constructs |
| |
| Use these SystemVerilog constructs instead of their Verilog-2001 equivalents: |
| |
| - `always_comb` is required over `always @*`. |
| - `logic` is preferred over `reg` and `wire`. |
| - Top-level `parameter` declarations are preferred over `` `define`` globals. |
| |
| |
| ### Package Dependencies |
| |
| ***Packages must not have cyclic dependencies.*** |
| |
| Package files may depend on constants and types in other package files, but there must not be any cyclic dependencies. |
| That is: if package A depends on a constant from package B, package B must not depend on anything from package A. |
| While cyclic dependencies are permitted by the SystemVerilog language specification, their use can break some tools. |
| |
| For example: |
| |
| ```systemverilog |
| package foo; |
| |
| // Package "bar" must not depend on anything in "foo": |
| parameter int unsigned PageSizeBytes = 16 * bar::Kibi; |
| |
| endpackage |
| ``` |
| |
| ### Module Declaration |
| |
| ***Use the Verilog-2001 full port declaration style, and use the format below.*** |
| |
| Use the Verilog-2001 combined port and I/O declaration style. |
| Do not use the Verilog-95 list style. |
| The port declaration in the module statement should fully declare the port name, type, and direction. |
| |
| The opening parenthesis should be on the same line as the module declaration, and the first port should be declared on the following line. |
| |
| The closing parenthesis should be on its own line, in column zero. |
| |
| Indentation for module declaration follows the standard indentation rule of two space indentation. |
| |
| The clock port(s) must be declared first in the port list, followed by any and all reset inputs. |
| |
| Example without parameters: |
| |
| 👍 |
| ```systemverilog {.good} |
| module foo ( |
| input clk_i, |
| input rst_ni, |
| input [7:0] d_i, |
| output logic [7:0] q_o |
| ); |
| ``` |
| |
| Example with parameters: |
| |
| 👍 |
| ```systemverilog {.good} |
| module foo #( |
| parameter int unsigned Width = 8, |
| ) ( |
| input clk_i, |
| input rst_ni, |
| input [Width-1:0] d_i, |
| output logic [Width-1:0] q_o |
| ); |
| ``` |
| |
| Do not use Verilog-95 style: |
| |
| 👎 |
| ```systemverilog {.bad} |
| // WRONG: |
| module foo(a, b, c d); |
| input wire [2:0] a; |
| output logic b; |
| ... |
| ``` |
| |
| ### Parameterized Module Instantiation |
| |
| ***Use named parameters for all instantiations.*** |
| |
| When parameterizing an instance, specify the parameter using the named parameter style. |
| An exception is if there is only one parameter that is obvious such as register width, then the instantiation can be implicit. |
| |
| Indentation for module instantiation follows the standard indentation rule of two space indentation. |
| |
| ```systemverilog |
| my_module #( |
| .Height(5), |
| .Width(10) |
| ) my_module ( |
| ...etc... |
| |
| my_reg #(16) my_reg0 (.clk_i, .rst_ni, .d_i(data_in), .q_o(data_out)); |
| |
| ``` |
| Do not specify parameters positionally, unless there is only one parameter and the intent of that parameter is obvious, such as the width for a register instance. |
| |
| Do not use `defparam`. |
| |
| ***Use named ports to fully specify all instantiations.*** |
| |
| When connecting signals to ports for an instantiation, use the named port style, like this: |
| |
| ```systemverilog |
| my_module i_my_instance ( |
| .clk_i (clk_i), |
| .rst_ni(rst_ni), |
| .d_i (from_here), |
| .q_o (to_there) |
| ); |
| ``` |
| |
| If the port and the connecting signal have the same name, you can use the `.port` syntax (without parentheses) to indicate connectivity. |
| For example: |
| |
| ```systemverilog |
| my_module i_my_instance ( |
| .clk_i, |
| .rst_ni, |
| .d_i (from_here), |
| .q_o (to_there) |
| ); |
| ``` |
| |
| All declared ports must be present in the instantiation blocks. |
| Unconnected outputs must be explicitly written as no-connects (for example: `.output_port()`), and unused inputs must be explicitly tied to ground (for example: `.unused_input_port(8'd0)`) |
| |
| `.*` is not permitted. |
| |
| Do not use positional arguments to connect signals to ports. |
| |
| Instantiate ports in the same order as they are defined in the module. |
| |
| ***Do not instantiate recursively.*** |
| |
| Modules may not instantiate themselves recursively. |
| |
| ### Constants |
| |
| ***It is recommended to use symbolicly named constants instead of raw numbers.*** |
| |
| Try to give commonly used constants symbolic names rather than repeatedly typing raw numbers. |
| |
| Local constants should always be declared using `localparam`. |
| |
| Global constants should always be declared in a separate `.vh` or `.svh` include file. |
| |
| For SystemVerilog code, global constants should always be declared as package parameters. |
| For Verilog-2001 compatible code, top-level parameters are not supported and `` `define`` macros must be used instead. |
| |
| Include the units for a constant as a suffix in the constant's symbolic name. |
| The exceptions to this rule are for constants that are inherently unitless, or if the constant is describing the default unit type, "bits." |
| |
| Example: |
| |
| ```systemverilog |
| localparam int unsigned INTERFACE_WIDTH = 64; // Bits |
| localparam int unsigned INTERFACE_WIDTH_BYTES = (INTERFACE_WIDTH + 7) / 8; |
| localparam int unsigned INTERFACE_WIDTH_64B_WORDS = (INTERFACE_WIDTH + 63) / 64; |
| localparam int unsigned IMAGE_WIDTH_PIXELS = 640; |
| localparam int unsigned MEGA = 1000 * 1000; // Unitless |
| localparam int unsigned MEBI = 1024 * 1024; // Unitless |
| localparam int unsigned SYSTEM_CLOCK_HZ = 200 * MEGA; |
| ``` |
| |
| ### Signal Widths |
| |
| ***Be careful about signal widths.*** |
| |
| #### Always be explicit about the widths of number literals. |
| |
| Examples: |
| |
| 👍 |
| ```systemverilog {.good} |
| localparam logic [3:0] bar = 4'd4; |
| |
| assign foo = 8'd2; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| localparam logic [3:0] bar = 4; |
| |
| assign foo = 2; |
| ``` |
| |
| Exceptions: |
| |
| * When using parameterized widths, it is acceptable to simply use `1'b1` (e.g. when incrementing) rather than contrivances such as `{{(Bus_width-1){1'b0}},1'b1}` |
| * It is acceptable to use the '0 construct to create an automatic correctly sized zero. |
| * Literals assigned to integer variants (e.g. byte, shortint, int, integer, and longint) do not need an explicit width. |
| |
| #### Port connections on module instances must always match widths correctly. |
| |
| It is recommended to use explicit widths, rather than relying on Verilog's implicit zero-extension and truncation operations, whenever practical. |
| |
| Examples: |
| |
| 👍 |
| ```systemverilog {.good} |
| my_module i_module ( |
| .thirty_two_bit_input({16'd0, sixteen_bit_word}) |
| ); |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| my_module i_module ( |
| // Incorrectly implicitly extends from 16 bit to 32 bit |
| .thirty_two_bit_input(sixteen_bit_word) |
| ); |
| ``` |
| |
| #### Do not use multi-bit signals in a boolean context. |
| |
| Rather than letting boolean operations and if expressions reduce a multi-bit signal to a single bit, explictly compare the multi-bit signal to 0. |
| The implicit conversion can hide subtle logic bugs. |
| |
| Examples; |
| |
| 👍 |
| ```systemverilog {.good} |
| logic [3:0] a, b; |
| logic out; |
| |
| assign out = (a != '0) && (b == '0); |
| |
| always_comb begin |
| if (a != '0) |
| ... |
| else |
| ... |
| end |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| logic [3:0] a, b; |
| logic out; |
| |
| // Incorrect because it implicitly converts 4-bit signals to 1-bit before AND. |
| // Also, !b is different from ~b and can be hard to catch. |
| assign out = a && !b; |
| |
| // Incorrect use of a multi-bit signal in an if expression |
| always_comb begin |
| if (a) |
| ... |
| else |
| ... |
| end |
| ``` |
| |
| #### Bit Slicing |
| |
| Only use the bit slicing operator when the intent is to refer to a portion of a bit vector. |
| |
| Examples: |
| |
| 👍 |
| ```systemverilog {.good} |
| logic [7:0] a, b; |
| logic [6:0] c; |
| |
| assign a = 8'd7; // good |
| |
| assign a[7:1] = 7'd5; // good - it's partial assignment. |
| assign a = b; // good - the parser would warn on width mismatch. |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| logic [7:0] a, b; |
| |
| assign a[7:0] = 8'd7; // BAD - redundant and can mask linter warnings. |
| assign a = b[7:0]; // BAD - redundant and masks linter warnings. |
| ``` |
| |
| #### Handling Width Overflow |
| |
| Beware of shift operations, which can produce a result wider than the operand. |
| Bit-selection and concatenation may be clearer than shifting by a constant amount. |
| |
| Addition and negation operations produce a result one bit wider than the operands, due to carry. |
| An allowable exception to the rule about matching widths is to silently drop the carry on assignment. |
| |
| Example: |
| |
| ```systemverilog |
| assign abc = abc + 4'h1; |
| ``` |
| |
| ### Blocking and Non-blocking Assignments |
| |
| ***Sequential logic must use non-blocking assignments. |
| Combinational blocks must use blocking assignments.*** |
| |
| Never mix assignment types within a block declaration. |
| |
| A sequential block (a block that latches state on a clock edge) must exclusively use non-block assignments, as defined in the Sequential Logic section below. |
| |
| Purely combinational blocks must exclusively use blocking assigments. |
| |
| This is one of Cliff Cumming's [Golden Rules of Verilog](http://www.ece.cmu.edu/~ece447/s13/lib/exe/fetch.php?media=synth-verilog-cummins.pdf). |
| |
| ### Delay Modeling |
| |
| ***Do not use `#delay` in synthesizable design modules.*** |
| |
| Synthesizable design modules must be designed around a zero-delay simulation methodology. |
| All forms of `#delay`, including `#0`, are not permitted. |
| |
| ### Sequential Logic (Latches) |
| |
| ***The use of latches is discouraged - use flip-flops when possible.*** |
| |
| Unless absolutely necessary, use flops/registers instead of latches. |
| |
| If you must use a latch, use `always_latch` over `always`, and use non-blocking assignments (`<=`). |
| Never use blocking assignments (`=`). |
| |
| ### Sequential Logic (Registers) |
| |
| ***Use the standard format for declaring sequential blocks.*** |
| |
| In a sequential always block, only use non-blocking assignments (`<=`). |
| Never use blocking assignments (`=`). |
| |
| Designs that mix blocking and non-blocking assignments for registers simulate incorrectly because some simulators process some of the blocking assignments in an always block as occurring in a separate simulation event as the non-blocking assignment. |
| This process makes some signals jump registers, potentially leading to total protonic reversal. |
| That's bad. |
| |
| Sequential statements for state assignments should only contain reset values and a next-state to state assignment, use a separate combinational-only block to generate that next-state value. |
| |
| A correctly implemented 8-bit register with an initial value of "0xAB" would be implemented: |
| |
| 👍 |
| ```systemverilog {.good} |
| logic foo_en; |
| logic [7:0] foo_q, foo_d; |
| |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| foo_q <= 8'hab; |
| end else if (foo_en) begin |
| foo_q <= foo_d; |
| end |
| end |
| ``` |
| |
| Do not allow multiple non-blocking assignments to the same bit. |
| |
| Example: |
| |
| 👎 |
| ```systemverilog {.bad} |
| if (cond1) begin |
| abc <= 4'h1; |
| end |
| |
| if (cond2) begin |
| abc <= 4'h2; |
| end |
| ``` |
| |
| If both cond1 and cond2 are true, the Verilog standard says that the second assignment will take effect, but this is a style violation. |
| |
| Even if `cond1` and `cond2` are mutually exclusive, make the second `if` into an `else if`. |
| |
| Exception: It is fine to set default values first, then specific values. |
| However, it is preferred to do this work in a separate combinational block with explicit blocking assignments. |
| |
| Example: |
| |
| ```systemverilog |
| always_ff @(posedge clk or negedge rst_ni) begin |
| if (!rst_ni) begin |
| state_q <= StIdle; |
| end else begin |
| state_q <= state_d; |
| end |
| end |
| |
| always_comb begin |
| state_d = state_q; // default assignment next state is present state |
| unique case (state_q) |
| StIdle: state_d = StInit; // Idle State move to Init |
| StInit: begin // Initialize calculation |
| if (conditional) begin |
| state_d = StIdle; |
| end else begin |
| state_d = StCalc; |
| end |
| end |
| StCalc: begin // Perform calculation |
| if (conditional) begin |
| state_d = StResult; |
| end |
| end |
| StResult: state_d = Idle; |
| default: state_d = 'X; |
| endcase |
| end |
| ``` |
| |
| Keep work in sequential blocks simple. |
| If a sequential block becomes sufficiently complicated, consider splitting the combinational logic into a separate combinational (`always_comb`) block. |
| Ideally, sequential blocks should contain only a register instantiation, with perhaps a load enable or an increment. |
| |
| ### Don't Cares (`X`'s) |
| |
| ***Explicitly specify don't cares when safe to do so. |
| Don't silently squash `X` in logic.*** |
| |
| Don't Care values can significantly help the quality of logic optimization and should be used wherever it is safe to do so. |
| Explicitly declaring unused decodes as `X` has the secondary effect of propagating `X`'s through the design if the **input unused** design assumption is violated, making those bugs easier to diagnose and fix. |
| |
| Example: |
| |
| ```systemverilog |
| always_comb begin |
| unique case (state) |
| ALPHA: decode = 16'd1; |
| BETA: decode = 16'd127; |
| GAMMA: decode = 16'd43; |
| // all other states are unused: |
| default: decode = 'X; // or {16{1'bx}} in Verilog-2001 |
| endcase |
| end |
| ``` |
| |
| Write logic that will either propagate `X` or assert when your inputs are `X`. |
| Avoid silently squashing `X` by writing logic that resolves an `X` input to a non-`X` output. |
| Instead, write logic that either explicitly propagates the `X` or uses an assert to raise an exception when an input is `X`. |
| |
| Be aware: Any logical operation involving `X` always propagates the `X`. |
| |
| Example: |
| |
| ```systemverilog |
| $display("%b", 1'bx == 1'b1); // produces 1'bx |
| $display("%b", 1'bx != 1'b1); // produces 1'bx |
| $display("%b", !(1'bx)); // produces 1'bx. |
| // etc. |
| ``` |
| |
| However, when evaluated in a boolean context, `X` always evaluates to false. |
| |
| Example: |
| |
| ```systemverilog |
| always_comb begin |
| if (value) result = 1'b0; // value is 1'b1 |
| else result = 1'b1; // value is 1'b0 or 1'bx |
| end |
| ``` |
| |
| This can mask subtle problems in code and produce a mismatch between simulation and synthesis. |
| |
| Instead, consider these options: |
| |
| ```systemverilog |
| always_comb begin |
| result = value ? 1'b1 : 1'b0; // 1'bx produces 1'bx |
| end |
| ``` |
| |
| or |
| |
| ```systemverilog |
| always_comb begin |
| if (value) result = 1'b0; // value is 1'b1 |
| else if (!value) result = 1'b1; // value is 1'b0 |
| else result = 1'bx; // value is 1'bx |
| end |
| ``` |
| |
| or |
| |
| ```systemverilog |
| always_comb begin |
| assert (!$isunknown(value)); // throws exception if 1'bx |
| if (value) result = 1'b0; // value is 1'b1 |
| else result = 1'b1; // value is 1'b0 or 1'bx |
| end |
| ``` |
| |
| Further discussion: |
| |
| - ["I'm Still In Love With My X!"](http://www.sutherland-hdl.com/papers/2013-DVCon_In-love-with-my-X_paper.pdf) by Stuart Sutherland |
| - ["Being Assertive With Your X"](http://www.lcdm-eng.com/papers/snug04_assertiveX.pdf) by Don Mills |
| |
| ### Combinational Logic |
| |
| ***Avoid sensitivity lists, and use a consistent assignment type.*** |
| |
| Use `always_comb` for SystemVerilog combinational blocks. |
| Use `always @*` if only Verilog-2001 is supported. |
| Never explicitly declare sensitivity lists for combinational logic. |
| |
| Prefer assign statements wherever practical. |
| |
| Example: |
| |
| ```systemverilog |
| assign final_value = xyz ? value_a : value_b; |
| ``` |
| |
| Where a case statement is needed, enclose it in its own `always_comb` block. |
| |
| Synthesizable combinational logic blocks should only use blocking assignments. |
| |
| Do not use three-state logic (`Z` state) to accomplish on-chip logic such as muxing. |
| |
| Do not infer a latch inside a function, as this may cause a simulation / synthesis mismatch. |
| |
| ### Case Statements |
| |
| ***Avoid case-modifying pragmas. |
| `unique case` is the best practice. |
| Always define a default case.*** |
| |
| Never use either the `full_case` or `parallel_case` pragmas. |
| These pragmas can easily cause synthesis-simulation mismatches. |
| |
| Here is an example of a style-compliant case statement: |
| |
| ```systemverilog |
| always_comb begin |
| unique casez (select) |
| 3'b000: operand = accum0 >> 0; |
| 3'b001: operand = accum0 >> 1; |
| 3'b010: operand = accum1 >> 0; |
| 3'b011: operand = accum1 >> 1; |
| 3'b1??: operand = regfile[select[1:0]]; |
| default: operand = 'X; // propagate X |
| endcase |
| end |
| ``` |
| |
| The `unique` prefix is recommended before all case statements, as it creates simulation assertions that can catch certain mistakes. |
| In some cases, `priority` may be used instead of `unique`, though `if-else-if` structures are a more readable representation for priority encoders. |
| |
| Be sure to use `unique case` correctly. |
| In particular, any variables assigned in one case item must be assigned in all case items, including the default. |
| Failing to do this can lead to a simulation-synthesis mismatch as described in [Don Mills' paper][yalagp]. |
| |
| The `default` case is required to avoid accidental inference of latches, even if all cases are covered. |
| In simulation, a case expression that evaluates to `X` will not match any case and will behave as a latch, leading to different behavior than synthesis. |
| Instead, in most scenarios, the best choice is to propagate the `X` by assigning all output variables to `X` by default. |
| |
| ##### Wildcards in case items |
| |
| Use `case` instead of `casez` whenever wildcard operator behavior is not required. |
| When wildcard behavior is needed, use `casez`. |
| |
| When expressing a wildcard in a case item, use the '?' character since it more clearly expresses the intent. |
| |
| `casex` should not be used. |
| `casex` implements a symmetric wildcard operator such that an `X` in the case expression may match one or more case items. |
| `casez` only treats high-impedance states (`Z` or `?`) as a wildcard, and performs exact matches for undriven `X` inputs. |
| While this does not completely fix the problems with symmetric wildcard matching, it is harder to accidentally produce a `Z` input than an `X` input, so this form is preferred. |
| |
| The SystemVerilog-2012 `case-inside` construct should not be use used yet. |
| It implements asymmetric wildcard matching, so that only `X`s in the case-items will behave as wildcards. |
| Unfortunately, tool support for `case-inside` is not universal yet. |
| |
| References: |
| |
| * Don Mills, [Yet Another Latch and Gotchas Paper][yalagp] |
| * Clifford Cummings, [full\_case parallel\_case, the Evil Twins of Verilog Synthesis][twinevils] |
| * Clifford Cummings, [SystemVerilog's priority & unique][priuniq] |
| * Sutherland, Mills, and Spear, [Gotcha Again: More Subtleties in the Verilog and SystemVerilog Standards That Every Engineer Should Know][gotagain] |
| |
| [yalagp]: http://www.lcdm-eng.com/papers/snug12_Paper_final.pdf |
| [twinevils]: http://www.sunburst-design.com/papers/CummingsSNUG1999Boston_FullParallelCase_rev1_1.pdf |
| [priuniq]: http://www.sunburst-design.com/papers/CummingsSNUG2005Israel_SystemVerilog_UniquePriority.pdf |
| [gotagain]: http://www.lcdm-eng.com/papers/snug07_Verilog%20Gotchas%20Part2.pdf |
| |
| ### Generate Constructs |
| |
| ***Always name your generated blocks.*** |
| |
| When using a generate construct, always explicitly name each block of generated code. |
| Name each possible outcome of the generating if statement, and name the iterated block of a generating for statement. |
| |
| This ensures that generated hierarchical signal names are consistent across different tools. |
| |
| Generate and all named code blocks should use `lower_snake_case`. |
| A space should be placed between `begin` and the code block name. |
| |
| Example of a conditional generate construct: |
| |
| 👍 |
| ```systemverilog {.good} |
| if (TypeIsPosedge) begin : posedge_type |
| always_ff @(posedge clk) foo <= bar; |
| end else begin : negedge_type |
| always_ff @(negedge clk) foo <= bar; |
| end |
| ``` |
| |
| Example of a loop generate construct: |
| |
| 👍 |
| ```systemverilog {.good} |
| for (genvar ii = 0; ii < NumberOfBuses; ii++) begin : my_buses |
| my_bus #(.index(ii)) i_my_bus (.foo(foo), .bar(bar[ii])); |
| end |
| ``` |
| |
| Do not wrap a generate construct with an additional `begin` block. |
| |
| Do not use generate regions {`generate`, `endgenerate`}. |
| |
| ### Signed Arithmetic |
| |
| ***Use the available signed arithmetic constructs wherever signed arithmetic is used.*** |
| |
| When it's necessary to convert from unsigned to signed, use the `signed'` cast operator (`$signed` in Verilog-2001). |
| |
| If any operand in a calculation is unsigned, Verilog implicitly casts all operands to unsigned and generates a warning. |
| There should not be any signed-to-unsigned warnings from either the simulation or synthesis tools if all unsigned variables are properly casted. |
| |
| Example of implicit signed-to-unsigned casting: |
| |
| ```systemverilog |
| logic signed [7:0] a; |
| logic incr; |
| logic signed [15:0] sum1, sum2; |
| initial begin |
| a = 8'sh80; |
| incr = 1'b1; |
| sum1 = a + incr; // sum1 = 16'h0081 |
| sum2 = a + signed'({1'b0, incr}); // sum2 = 16'hFF81 |
| end |
| ``` |
| |
| In the above example, the fact that `incr` is unsigned causes `a` to be evaluated as unsigned as well. |
| The `sum1` evaluation is surprising and is flagged by a warning that should not be ignored. |
| |
| ### Number Formatting |
| |
| ***Prefix printed binary numbers with `0b`. |
| Prefix printed hexadecimal numbers with `0x`. |
| Do not use prefixes for decimal numbers.*** |
| |
| When formatting text representations of numbers for log files, make it clear what data you are including. |
| |
| Make the base of a printed number clear. |
| Only print decimal numbers without modifiers. |
| Use a `0x` prefix for hexadecimal and `0b` prefix for binary. |
| |
| Decode individual fields of large structures individually, instead of expecting the user to manually decode raw values. |
| |
| 👍 |
| ```systemverilog {.good} |
| $display("0x%0x", some_hex_value); |
| $display("0b%0b", some_binary_value); |
| $display("%0d", some_decimal_value); |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| $display("%0x", some_hex_value); |
| $display("%0b", some_binary_value); |
| $display("0d%0d", some_decimal_value); |
| ``` |
| |
| When assigning constant values, it is preferred to use underscore notation for hex or binary bit strengths of length beyond 8 for better readability. |
| Zero prepending is not required unless it improves readability. |
| Declare constants in the format (binary, hex, decimal) they are typically displayed in. |
| |
| |
| 👍 |
| ```systemverilog {.good} |
| logic [15:0] val0, val1, val2; |
| logic [39:0] addr0, addr1; |
| |
| always_comb begin |
| val0 = 16'h0; |
| if (condition1) begin |
| val1 = 16'b0010_0011_0000_1101; |
| val2 = 16'b0010_1100_0000_0000; |
| addr1 = 40'h00_1fc0_0000; |
| addr2 = 40'h00_efc0_0000; |
| end else begin |
| val0 = 16'hffff; |
| val1 = 16'b1010_0011_0110_1001; |
| val2 = 16'b1110_1100_1111_0110; |
| addr1 = 40'h40_8000_0000; |
| addr2 = 40'h41_c000_0000; |
| end |
| end |
| ``` |
| |
| ### Problematic Language Features and Constructs |
| |
| These language features are considered problematic and their use is discouraged unless otherwise noted: |
| |
| - Interfaces. |
| - Wildcard import (of packages), eg. `import my_pkg::*;`. |
| - The `alias` statement. |
| - `case inside` is broken inside some FPGA compile tools. |
| |
| #### Floating begin-end blocks |
| |
| The use of generate blocks other than `for` loop, `if`, or `case` generate constructs is not LRM compliant. |
| While such usage might be accepted by some tools, this guide prohibits such "bare" generate blocks. |
| Note that the similar "sequential block" construct is LRM compliant and allowed. |
| |
| 👎 |
| ```systemverilog {.bad} |
| module foo ( |
| input bar, |
| output foo |
| ); |
| begin // illegal generate block |
| assign foo = bar; |
| end |
| endmodule |
| ``` |
| |
| ## Design Conventions |
| |
| ### Summary |
| |
| The key ideas in this section include: |
| |
| * Declare all signals and use `logic`: `logic foo;` |
| * Packed arrays are little-endian: `logic [7:0] byte;` |
| * Unpacked arrays are big-endian: `byte_t arr[0:N-1];` |
| * Prefer to register module outputs. |
| * Declare FSMs consistently. |
| |
| ### Declare all signals |
| |
| ***Do not rely on inferred nets.*** |
| |
| All signals **must** be explicitly declared before use. |
| All declared signals must specify a data type. |
| A correct design contains no inferred nets. |
| |
| ### Use `logic` for synthesis |
| |
| ***Use `logic` for synthesis. |
| `wire` is allowed when necessary.*** |
| |
| All signals in synthesizable RTL must be implemented in terms of 4-state data types. |
| This means that all signals must ultimately be constructed of nets with the storage type of `logic`. |
| While SystemVerilog does provide other data primitives with 4-state storage (ie. `integer`), those primitives are prone to misunderstandings and misuse. |
| |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| logic signed [31:0] x_velocity; // say what you mean: a signed 32-bit integer. |
| typedef logic [7:0] byte_t; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| bit signed [63:0] stars_in_the_sky; // 2-state logic doesn't belong in RTL |
| int grains_of_sand; // Or wait, did I mean integer? Easy to confuse! |
| ``` |
| |
| It is permissible to use wire as a short-hand to both declare a net and perform continuous assignment. |
| Take care not to confuse continuous assignment with initialization. |
| For example: |
| |
| 👍 |
| ```systemverilog {.good} |
| wire [7:0] sum = a + b; // Continuous assignment |
| |
| logic [7:0] acc = '0; // Initialization |
| ``` |
| |
| There are exceptions for places where `logic` is inappropriate. |
| For example, nets that connect to bidirectional (`inout`) ports must be declared with `wire`. |
| These exceptions should be justified with a short comment. |
| |
| It is permissible for DV (Design Verification) to make use of 2-state logic, but all interfaces between 4-state and 2-state signals must assert a check for `X` on the 4-state net before resolving to a 2-state variable. |
| |
| ### Logical vs. Bitwise |
| |
| ***Use logical constructs for logical comparisons, bit-wise for data.*** |
| |
| Logical constructs (`!`, `||`, `&&`, `==`, `!=`) should be used for all constructs that are evaluating logic (true or false) values, such as if clauses and ternary assignments. |
| Use bit-wise constructs (`~`, `|`, `&`, `^`) for all data constructs, even if scalar. |
| |
| 👍 |
| ```systemverilog {.good} |
| always_comb begin |
| if (bool_a || (bool_b && !bool_c) begin |
| x = 1'b1; |
| end else begin |
| x = 1'b0; |
| end |
| |
| assign z = ((bool_a != bool_b) || bool_c) ? a : b; |
| assign y = (a & ~b) | c; |
| ``` |
| |
| 👎 |
| ```systemverilog {.bad} |
| always_comb begin |
| if (bool_a | (bool_b & ~bool_c) begin |
| x = 1'b1; |
| end else begin |
| x = 1'b0; |
| end |
| |
| assign z = ((bool_a ^ bool_b) | bool_c) ? a : b; |
| assign y = (a && !b) || c; |
| ``` |
| |
| ### Packed Ordering |
| |
| ***Bit vectors and packed arrays must be little-endian.*** |
| |
| When declaring bit vectors and packed arrays, the index of the most-significant bound (left of the colon) must be greater than or equal to the least-significant bound (right of the colon). |
| |
| This style of bit vector declaration keeps packed variables little-endian. |
| |
| For example: |
| |
| ```systemverilog |
| typedef logic [7:0] u8_t; |
| logic [31:0] u32_word; |
| u8_t [1:0] u16_word; |
| u8_t byte3, byte2, byte1, byte0; |
| assign u16_word = {byte1, byte0}; |
| assign u32_word = {byte3, byte2, u16_word}; |
| ``` |
| |
| ### Unpacked Ordering |
| |
| ***Unpacked arrays must be big-endian.*** |
| |
| Declare unpacked arrays in big-endian fashion (for instance, `[n:m]` where `n <= m`). |
| Never declare an unpacked array in little-endian order, such as `[size-1:0]`. |
| |
| Declare zero-based unpacked arrays using the shorter notation `[size]`. |
| It is understood that `[size]` is equivalent to the big-endian declaration `[0:size-1]`. |
| |
| ```systemverilog |
| logic [15:0] word_array[3] = '{word0, word1, word2}; |
| ``` |
| |
| ### Finite State Machines |
| |
| ***State machines use an enum to define states, and be implemented with two process blocks: a combinational block and a clocked block.*** |
| |
| Every state machine description has three parts: |
| |
| 1. An enum that declares and describes the states. |
| 1. A combinational process block that decodes state to produce next state and other combinational outputs. |
| 1. A clocked process block that updates state from next state. |
| |
| *Enumerating States* |
| |
| The enum statement for the state machine should list each state in the state machine. |
| Comments describing the states should be deferred to case statement in the combinational process block, below. |
| |
| States should be named in `UpperCamelCase`, like other [enumeration constants](#enumerations). |
| |
| Barring special circumstances, the initial idle state of the state machines will be named `Idle` or `StIdle`. |
| (Alternate names are acceptable if they improve clarity.) |
| |
| Ideally, each module should only contain one state machine. |
| If your module needs more than one state machine, you will need to add a unique prefix (or suffix) to the states of each state machine, to distinguish which state is associated with which state machine. |
| For example, a module with a "reader" machine and a "writer" machine might have a `StRdIdle` state and a `StWrIdle` state. |
| |
| *Combinational Decode of State* |
| |
| The combinational process block should contain: |
| |
| - A case statement that decodes state to produce next state and combinational outputs. |
| For clarity, only cases where the output value deviates from the default should be coded. |
| - Before the case statement should be a block of code that defines default values for every combinational output, including "next state." |
| - The default value for the "next state" variable should be the current state. |
| The case statement that decodes state will then only assign to "next state" when transitioning between states. |
| - Within the case statement, each state alternative should be preceded with a comment that describes the function of that state within the state machine. |
| |
| *The State Register* |
| |
| No logic except for reset should be performed in this process. |
| The state variable should latch the value of the "next state" variable. |
| |
| *Other Guidelines* |
| |
| When possible, try to choose state names that differ near the beginning of their name, to make them more readable when viewing waveform traces. |
| |
| *Example* |
| |
| 👍 |
| ```systemverilog {.good} |
| // Define the states |
| typedef enum { |
| StIdle, StFrameStart, StDynInstrRead, StBandCorr, StAccStoreWrite, StBandEnd |
| } alcor_state_e; |
| |
| alcor_state_e alcor_state_d, alcor_state_q; |
| |
| // Combinational decode of the state |
| always_comb begin |
| alcor_state_d = alcor_state_q; |
| foo = 1'b0; |
| bar = 1'b0; |
| bum = 1'b0; |
| unique case (alcor_state_q) |
| // StIdle: waiting for frame_start |
| StIdle: |
| if (frame_start) begin |
| foo = 1'b1; |
| alcor_state_d = StFrameStart; |
| end |
| // StFrameStart: Reset accumulators |
| StFrameStart: begin |
| // ... etc ... |
| end |
| default: begin |
| // X's in the inputs propagate to X's in the outputs |
| alcor_state_d = 'X; |
| foo = 'X; |
| bar = 'X; |
| bum = 'X; |
| end |
| endcase |
| end |
| |
| // Register the state |
| always_ff @(posedge clk or negedge rst_n) begin |
| if (!rst_n) begin |
| alcor_state_q <= StIdle; |
| end else begin |
| alcor_state_q <= alcor_state_d; |
| end |
| end |
| ``` |
| |
| ### Active-Low Signals |
| |
| ***The `_n` suffix indicates an active-low signal.*** |
| |
| If active-low signals are used, they must have the `_n` suffix in their name. |
| Otherwise, all signals are assumed to be active-high. |
| |
| ### Differential Pairs |
| |
| ***Use the `_p` and `_n` suffixes to indicate a differential pair.*** |
| |
| For example, `in_p` and `in_n` comprise a differential pair set. |
| |
| ### Delays |
| |
| ***Signals delayed by a single clock cycle should end in a `_q` suffix.*** |
| |
| If one signal is only a delayed version of another signal, the `_q` suffix should be used to indicate this relationship. |
| |
| If another signal is then delayed by another clock cycle, the next signal should be identifed with the `_q2` suffix, and then `_q3` and so on. |
| |
| Example: |
| |
| ```systemverilog |
| always_ff @(posedge clk) begin |
| data_valid_q <= data_valid_d; |
| data_valid_q2 <= data_valid_q; |
| data_valid_q3 <= data_valid_q2; |
| end |
| ``` |
| |
| ## Appendix - Condensed Style Guide |
| |
| This is a short summary of the Comportable style guide. |
| Refer to the main text body for explanations examples, and exceptions. |
| |
| ### Basic Style Elements |
| |
| * Use SystemVerilog-2012 conventions, files named as module.sv, one file per module |
| * Only ASCII, **100** chars per line, **no** tabs, **two** spaces per indent for all paired keywords. |
| * C++ style comments `//` |
| * For multiple items on a line, **one** space must separate the comma and the next character |
| * Include **whitespace** around keywords and binary operators |
| * **No** space between case item and colon, function/task/macro call and open parenthesis |
| * Line wraps should indent by **four** spaces |
| * `begin` must be on the same line as the preceding keyword and end the line |
| * `end` must start a new line |
| |
| ### Construct Naming |
| |
| * Use **lower\_snake\_case** for instance names, signals, declarations, variables, types |
| * Use **UpperCamelCase** for tunable parameters, enumerated value names |
| * Use **ALL\_CAPS** for constants and define macros |
| * Main clock signal is named `clk`. |
| All clock signals must start with `clk_` |
| * Reset signals are **active-low** and **asynchronous**, default name is `rst_n` |
| * Signal names should be descriptive and be consistent throughout the hierarchy |
| |
| ### Suffixes for signals and types |
| |
| * Add `_i` to module inputs, `_o` to module outputs or `_io` for bi-directional module signals |
| * The input (next state) of a registered signal should have `_d` and the output `_q` as suffix |
| * Pipelined versions of signals should be named `_q2`, `_q3`, etc. |
| to reflect their latency |
| * Active low signals should use `_n`. |
| When using differential signals use `_p` for active high |
| * Enumerated types should be suffixed with `_e` |
| * Multiple suffixes will not be separated with `_`. |
| `n` should come first `i`, `o`, or `io` last |
| |
| ### Language features |
| |
| * Use **full port declaration style** for modules, any clock and reset declared first |
| * Use **named parameters** for instantiation, all declared ports must be present, no `.*` |
| * Top-level parameters is preferred over `` `define`` globals |
| * Use **symbolically named constants** instead of raw numbers |
| * Local constants should be declared `localparam`, globals in a separate **.svh** file. |
| * `logic` is preferred over `reg` and `wire`, declare all signals explicitly |
| * `always_comb`, `always_ff` and `always_latch` are preferred over `always` |
| * Interfaces are discouraged |
| * Sequential logic must use **non-blocking** assignments |
| * Combinational blocks must use **blocking** assignments |
| * Use of latches is discouraged, use flip-flops when possible |
| * Explicitly specify don't cares (`X`) when safe to do so. |
| * Prefer `assign` statements wherever practical. |
| * Use `unique case` and always define a `default` case |
| * Use available signed arithmetic constructs wherever signed arithmetic is used |
| * When printing use `0b` and `0x` as a prefix for binary and hex. |
| Use `_` for clarity |
| * Use logical constructs (i.e `||`) for logical comparison, bit-wise (i.e `|`) for data comparison |
| * Bit vectors and packed arrays must be little-endian, unpacked arrays must be big-endian |
| * FSMs: **no logic** except for reset should be performed in the process for the state register |
| * A combinational process should first define **default value** of all outputs in the process |
| * Default value for next state variable should be the current state |