Functions
Virdant allows you to define functions.
Functions are reusable snippets of combination logic. They may be used anywhere in a design.
Functions are declared with the fn
keyword:
fn max(x : Word[8], y : Word[8]) -> Word[8] {
if x->lt(y) {
x
} else {
y
}
}
The name and type of each parameter is given in a comma-separated list, and the return type is given after the arrow.
The body of the function definition is a single expression which may make use of the parameters.
To call a function, we do so as you would in math class: max(a, b)
,
where a
and b
can be any two expressions of the proper type.
Even when a function is only used in one place, they still provide two key benefits. First, they allow you to name a piece of logic in a way that is meaningful to anyone who reads your code. And second, they can be used to guarantee that a given result only depends on the arguments you pass to it. (This is very useful when both the module definition gets large and the function body gets complicated).
Here is a a complete example that shows a module which will always output the larger byte that it has seen as an input:
1fn max(x : Word[8], y : Word[8]) -> Word[8] {
2 if x->lt(y) {
3 x
4 } else {
5 y
6 }
7}
8
9mod Top {
10 incoming clock : Clock;
11 incoming reset : Bit;
12 incoming inp : Word[8];
13 outgoing max_seen : Word[8];
14
15 reg max_seen_reg : Word[8] on clock;
16
17 max_seen_reg <= if reset {
18 0
19 } else {
20 max(max_seen_reg, inp)
21 };
22
23 max_seen := max_seen_reg;
24}