The single-source-of-truth reference material for writing the cleanest code. The rules written in this document override any adopted external style guides and hold the highest precedence.
Sections are ordered alphabetically, except Overview, which opens the document, Global, whose subsections follow the order a contributor encounters them, and License, which closes the document.
Important
This document is a draft. Rules may change without a version bump until v1.0.0 is tagged.
This document is versioned with Semantic Versioning 2.0.0.
Each release is tagged v<major>.<minor>.<patch> and recorded in changelog.md
(lowercase, see Markdown file name), which follows
Keep a Changelog 1.1.0.
Version numbers are incremented as follows:
- Major: a change that can make conforming code non-conforming, i.e., a rule is added, tightened, or an exemption is removed.
- Minor: a change that cannot make conforming code non-conforming, i.e., a rule is relaxed, optional guidance is added, or a previously ungoverned language is given a section.
- Patch: an editorial change with no normative effect, i.e., typographical fixes, link repairs, rewording, or corrected examples.
A repository adopts these guidelines by declaring the adopted version in its readme.md or
contributing.md.
Example:
This repository conforms to the coding guidelines by Mondal & Mondal, v0.1.0.
Link to the tag, not to the default branch, so that the declaration remains reproducible.
Example:
https://github.com/mondal-mondal/coding-guidelines/blob/v0.1.0/readme.md
An adopting repository copies .editorconfig into its root. It may add rules that
these guidelines do not cover, but it must not relax a rule that these guidelines set. Any deviation
is documented in the adopting repository's docs/style.md, along with its justification.
Use American English (IETF language tag: en-US) over other variations of the English language,
except for two conventions: The Oxford comma is used in a series, and punctuation is placed outside
a closing quotation mark unless it is part of the quoted text (logical quotation), rather than the
American convention of placing it inside.
Most of the formatting rules laid out in this document are enforced by .editorconfig. For VS Code users, settings.json additionally configures behavior that .editorconfig cannot express, i.e., the vertical ruler, formatter selection, and formatting on save.
Two rules are not mechanically enforced and are checked during review: A file ends with exactly one newline, and a file contains no consecutive blank lines.
test_: verification file
Suffixes are defined per language.
Declare the license with the SPDX identifier of the license used by the adopting repository. Use REUSE's header convention to construct the file headers of the adopting repository's source files. A slightly modified version of this convention is given below for the adopting repository's use.
Example:
# SPDX-FileCopyrightText: © [year] [copyright holder] <[email address]>
#
# SPDX-License-Identifier: [identifier]
#
# [File description (if any)]
Indent with spaces, never tabs. The only exception is a recipe line in a Makefile, where the tab
is required by the format itself.
The indent width per language is:
| Language | Indent width |
|---|---|
| C++ | 2 |
| Markdown | 2 |
| PlantUML | 2 |
| Python | 4 |
| SystemVerilog | 2 |
| YAML | 2 |
Every source file:
- Carries no trailing whitespace on any line.
- Contains no consecutive blank lines.
- Ends with exactly one newline.
- Uses LF (
\n) line endings, never CRLF. - Uses UTF-8 without a byte order mark.
The maximum allowed column count or character width is 100. Unbreakable tokens, for example, long URLs or paths, are exempt.
Use canonical links only. Do not use www. as a subdomain and/or a trailing slash unless the
canonical link consists them/it.
Use Microsoft Visual Basic Coding Conventions — Commenting Conventions, except end with a period only when it is a complete sentence.
Conventional Commits 1.0.0 normatively defines
only feat and fix. The complete set permitted by this project is:
| Type | Use |
|---|---|
build |
Build system, toolchain, or dependency changes |
chore |
Maintenance with no effect on source or tests |
ci |
CI/CD configuration and pipeline changes |
docs |
Documentation only |
feat |
A new feature |
fix |
A bug fix |
perf |
A change that improves performance |
refactor |
A change that neither fixes a bug nor adds a feature |
revert |
A revert of a previous commit |
style |
Formatting only, with no change in behavior |
test |
Adding or correcting tests |
The default branch name is main. Do not use any other variations like master, trunk, etc.
Branches are named <type>/<description>, where <type> is drawn from the same set as a commit
type (see Commit type) and <description> is a lowercase, kebab-case
summary of the work.
This structure follows Conventional Branch v1.1.0, except that
the type set is the Conventional Commits set rather than the smaller set the specification
recommends, and develop and master are not permitted as trunk branches.
The description does not exceed 50 characters and contains only [a-z0-9-], with no consecutive,
leading, or trailing hyphens. The default branch is exempt from this rule.
Example:
fix/control-latch-and-alu-default
feat/tmr-register-file
docs/whitespace-indent-width
Use Conventional Commits 1.0.0.
Conventional Commits' example:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
A breaking change is marked with ! before the colon, a BREAKING CHANGE: footer, or both.
The subject line does not exceed 50 characters. The body and the trailers wrap at 72 characters. Commit messages are exempt from the column count.
Trailers follow git-interpret-trailers. They
occupy the last paragraph of the commit message, are separated from the body by exactly one blank
line, and contain nothing but trailers.
The permitted tokens are:
| Token | Value |
|---|---|
Closes |
An issue or merge request reference that this commit resolves |
Co-authored-by |
<name> <<email>> of an additional author |
Refs |
A related issue, merge request, commit, or URI |
Reviewed-by |
<name> <<email>> of a reviewer |
A trailer that applies more than once is repeated, once per line. Values are never combined into a comma-separated list on a single line.
Example:
fix(control): remove latch inference in the decoder
The default assignments were missing from the always_comb block, so the
unassigned branches inferred latches.
Refs: #12
Refs: https://github.com/example_user/example-repo/pull/25
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Incorrect:
Refs: #12, https://github.com/example_user/example-repo/pull/25
Use the Google C++ Style Guide.
Use snake_case.
No inline HTML except where Markdown has no equivalent.
| Target | Case | Example |
|---|---|---|
| Component name | PascalCase |
component ExampleComponent |
| Diagram name | snake_case |
@startuml example_diagram |
| Port name | Component name: PascalCase Port name: snake_case |
portin "example_port_i" as ExampleComponent_example_port_i portout "example_port_o" as ExampleComponent_example_port_o |
Use port aliasing to address the ports uniquely, for example, during connections. If multiple components use the same name for a port, each port can still be referenced uniquely.
Example:
<portin/portout> "<port_name>_<i/o>" as <ComponentName>_<port_name>_<i/o>
Same as SystemVerilog port order.
Applies to:
- Port connection
- Port list
Use spaces, not tabs.
Example:
@startuml
portin "operand_a_i" as Alu_operand_a_i
portin "operand_b_i" as Alu_operand_b_i
portout "result_o" as Alu_result_o
portin "result_i" as RegisterFile_result_i
portout "rs1_o" as RegisterFile_rs1_o
portout "rs2_o" as RegisterFile_rs2_o
RegisterFile_rs1_o --> Alu_operand_a_i
RegisterFile_rs2_o --> Alu_operand_b_i
Alu_result_o --> RegisterFile_result_i
@enduml
Use PEP 8 wherever applicable, except where a rule below overrides it.
The maximum allowed column count is 100 (see Column count), not PEP 8's 79. Configure Black accordingly, as its default is 88.
Example:
[tool.black]
line-length = 100
target-version = ["py313"]Black does not split a long string, comment, or docstring. Wrap these by hand, and do not rely on the formatter to enforce the column limit.
Use the Google docstring style. Every module, public class, and public function carries a docstring. A private function carries one where its purpose is not evident from its name and signature.
Example:
def compare_commit_log(trace_path: Path, golden_path: Path) -> bool:
"""Compares a captured commit log against a golden reference trace.
Args:
trace_path: Path to the commit log captured from the design under test.
golden_path: Path to the golden reference trace.
Returns:
True if every commit matches, False otherwise.
Raises:
FileNotFoundError: If either path does not exist.
"""Format with Black. Black is the sole authority on
formatting, i.e., its output is correct by definition and is never overridden by hand. Do not use
# fmt: off or # fmt: skip except where a hand-aligned block carries meaning that reformatting
would destroy, for example, a table of test vectors.
Black is configured in pyproject.toml, never through command line arguments, so that the editor
and CI read the same configuration.
Black formats but does not lint. A linter is not yet adopted, so PEP 8 rules that Black cannot enforce, i.e., naming, unused imports, and import order, are currently the author's responsibility and are checked during review.
Annotate every public function signature. Use the built-in generics of
PEP 585 and the union syntax of
PEP 604, not their typing equivalents.
Example:
def parse(paths: list[Path], limit: int | None = None) -> dict[str, int]:Incorrect:
def parse(paths: List[Path], limit: Optional[int] = None) -> Dict[str, int]:Use the lowRISC Verilog Coding Style Guide.
- Pipeline:
- Single-cycle core:
_sc.sv n-stage pipelined core:_pn.sv
- Single-cycle core:
- Package file:
_pkg.sv
Applies to:
- Module declaration
- Module instantiation
Ports are declared in three sections, in this order:
- System:
clk_i,rst_ni - Inputs: alphabetical
- Outputs: alphabetical
Example:
module example_module (
input logic clk_i,
input logic rst_ni,
input logic a_i,
input logic b_i,
input logic c_i,
input logic x_i,
input logic y_i,
input logic z_i,
output logic i_o,
output logic j_o,
output logic k_o,
output logic p_o,
output logic q_o,
output logic r_o
);
// Module content
endmodule : example_moduleThe MIT License is used for this project. See LICENSES/MIT.txt for more information.