Statements

The body of any unit, or block is a list of statements followed by a resulting expression. Statements can declare things local to the block and contain expressions to be evaluated

Let bindings

Let bindings bind a pattern to a value.

Those not used to bindings and patterns can view a let binding as assigning a value to a variable.

The pattern has to be an irrefutable pattern

If the type specification is omitted, the type is inferred.

Syntax

let pattern [: type specification] = expression ;

Examples

Binding a value to a variable

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
a = some_value;

Binding a value to the result of an if expression

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
a = Returns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
x {0} else {2};

Unpacking a tuple

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
(a, b) = some_value;

Unpacking a struct with an explicit type signature

let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
Struct$(a, b): Struct<Type used to represent signed integers. The generic parameter (<N>) specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
ies the number of bits
> = some_value;

Registers

Free-standing (i.e. non-pipelining registers) are defined using reg(clk) ... The register definition is quite complex and includes

On the rising edge of the clock signal, the value of the register is updated to the value of the new value. The new value expression can include variables from the register itself.

Syntax

reg( clock: expression ) pattern [: type specification ] [reset( reset trigger: expression : reset value expression )] = new value: expression ;

Examples

A register which counts from −128 to 127 (Note that because no initial value is specified, this will be undefined in simulation):

reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk)) are used for state registers both inside and outside pipelines. which are used to separate stages.
value: Type used to represent signed integers. The generic parameter (<N>) specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
ies the number of bits
= Truncates the input to a smaller size, throwing away the most signReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
icant bits. The size of the resulting value is type inferred.
value + 1);

A register which counts from 0 to 200 (inclusive) and is reset to 0 by rst:

reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk)) are used for state registers both inside and outside pipelines. which are used to separate stages.
value Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuerst: 0) = Returns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
value == 200 { 0 } else { Truncates the input to a smaller size, throwing away the most signReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
icant bits. The size of the resulting value is type inferred.
value + 1) };

Pipeline stage markers

Stage markers (reg;) are used in pipelines to specify where pipeline registers should be inserted. After a reg statement, all variables above the statement will be put in registers and any reference to those variables refer to the registered version.

Syntax

Repeated

In cases where more than one stage should be inserted without any new statements in between, there is a shorthand syntax:

reg * N; creates N Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. registers with no computation between them. This is typically used when waiting for another Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline., or to insert several registers at the end of a computation to be re-timed into the computation by the synthesis tool.

where n is an integer. This is compiled into n simple reg statements, i.e.

reg * N; creates N Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. registers with no computation between them. This is typically used when waiting for another Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline., or to insert several registers at the end of a computation to be re-timed into the computation by the synthesis tool.

is the same as

reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; which are used to separate stages.
) are used for state registers both inside and outside pipelines.
reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; which are used to separate stages.
) are used for state registers both inside and outside pipelines.
reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; which are used to separate stages.
) are used for state registers both inside and outside pipelines.

Conditioned

A condition for the registers to accept values can also be specified in square brackets

reg[condition]

The semantics of this are explained in the section on dynamic pipelines

Pipeline stage labels

Pipeline stages can be given names to refer to them from other stages. This is done using 'name.

  'first
  let is used to define a variable. Spade infers the type of most variables from context, but you can also specReturns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
y the type with : <type> before the =.
x = ...; reg; is used in a Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline. to separate stages. When you refer to a variable defined above a reg; statement below a reg; statement you refer to a registered version of the original value. Registers defined with an explicit Type used to represent clock signals. (reg(clk) is used to define registers which maintain the state of your circuit.
All registers have a Type used to represent clock signals. (clk), a name and a new value after the = which is given as a function of the current value. Registers can also have a Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuetrigger: value) wich means that the reset is synchronously set to value when trigger is true.
In pipelines, you can also define registers with reg; which are used to separate stages.
) are used for state registers both inside and outside pipelines.

To refer to a named stage, use a []

Set

Set the value of a mutable wire to the specified value.

set wire = value;

Set statements can only appear at the top block of a unit. This might be surprising as you would expect to be able to write

if condition {
  set wire = value;
}

However, this is not well-defined in hardware because the wire needs some value, but no value is specified if condition does not hold. This particular point isn’t true if an else branch is also specified, but the exact hardware that gets generated from imperative code like this is not obvious, particularly with more nesting.

Therefore, if you want to write

Returns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
condition { set wire = on_true; } else { set wire = on_false }

you should move the set statement outside to make it unconditional, i.e.

set wire =
  Returns the value of the first branch if the condition is true, otherwise the second branch.
Note that unlike software languages, Spade does not have conditional execution. You do not conditionally assign values inside if expressiosn, you compute a value and return it.
condition { on_true } else { on_false }

Syntax

set expression = expression ;

Assert

Takes a boolean condition and evaluates it, raising a runtime error in simulation if it ever evaluates to false. In synthesis, this is ignored

assert this_should_be_0 == 0;
NOTE: Assert statements are currently not supported for synthesis with Verilator, only with Icarus.

Comptime

TODO

Real world example