Coding Conventions

Virdant is a language we created so that hardware can be designed in a way that is lush and beautiful.

To help with this, we insist on adhering to certain coding conventions when writing Virdant.

Filenames

Virdant files have the .vir extension and should begin with a lowercase letter. For files with multiple words, we use snake case.

Spaces not Tabs

Please use only spaces in Virdant designs. When indenting, always use 4 spaces.

Naming Things

Names are incredibly important. They should be descriptive and accurate.

Do not abbreviate things needlessly. Be considerate of others who might want to read and understand your code. Make good use of your IDE, including autocomplete, to save effort on typing.

The names of module definitions, types, and sockets should begin with an uppercase letter. Everything else, including the names of function definitions, should begin with a lowercase letter.

For names that begin with an uppercase letter, use camel case. For abbreviations that appear in names, such as SPI, UART, or DDR, only the first letter is capitalized. So we write SpiController instead of SPIController.

For names that begin with a lowercase letter, we use snake case. A good name for a UART receiver is uart_receiver.

Types

Whenever you give the type of a component, you should put a space both before and after the colon. That is, we write wire w : Bit instead of wire w: Bit.

When declaring many components on consecutive lines, if adding a few extra spaces would cause the colons to line up, you may insert them to make it easier to read off the types.

Curly Braces

Virdant should be written with the opening curly brace at the end of the line which needed to open it. So we write the following:

mod Top {
    // ...
}

And similarly, the correct ways to write if and match expressions are:

if condition {
    0
} else {
    1
}

and

match maybe_data {
    @Invalid() => 0;
    @Valid(payload) => payload;
}

Expressions

When writing driver statements, if the expression on the right hand side is short, you can write it on the same line:

out := is_valid->and(counter[3]);

If an expression is longer, especially if it contains an if or match expression, it may be written in one of two ways.

The first is to write it inline, as if the driver is part of the expression:

counter <= if reset {
    0
} else {
    counter->inc()
};

Or if it makes it clearer, with a newline and an extra layer of indentation:

counter <=
    if reset {
        0
    } else {
        counter->inc()
    };

The expressions for the arm of each match expression follows a similar rule:

Inline:

match maybe_data {
    @Invalid() => 0;
    @Valid(payload) => payload;
}

Newline and extra indentation:

match maybe_data {
    @Invalid() =>
        if default_payload {
            default_payload
        } else {
            0
        };
    @Valid(payload) => payload;
}