Naming
This chapter describes the naming scheme used by the compiler when generating Verilog. The goal of the Verilog generator is not to generate readable Verilog, but there should be a clear two-way mapping between signal names in the source Spade code and generated Verilog. This mapping should be clear both to users reading lists of signals, for example, in VCD files, and tools, for example VCD parsers.
Variables
Because Spade does not have the same scoping rules as Verilog, some deconfliction of names internal to a Verilog module is needed.
If a name x only occurs once in a unit, the corresponding Verilog name is \x. (This is using the Verilog raw escape string system, and some tools may report the name as x). If x occurs more than once, subsequent names are given an index ordered sequentially in the order that they are visited during AST lowering[^1] The kth occurrence of a name is suffixed by _n{k}
Pipelined versions of names are suffixed with _s{n} where n is the absolute stage index of the stage.
Names of port type with mutable wires have an additional variable for the mutable bits. This follows the same naming scheme as the forward name, but is suffixed by _mut
The following is an example of the naming scheme
Defines a pipeline. The number in in the parentheses is input-to-output latency of the pipeline.(1) pipe(
x: Type used to represent 1 bit values, // "\x "
y: (&Type used to represent 1 bit values, inv &Type used to represent 1 bit values) // "\y ", "y_o "
) {
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. true {
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 = true; // "x_n1"
} else {
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 = false; // "x_n2"
}
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 = true; // "x_n3"
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. // "\x_s1 ", "x_n3_s1
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 =. z = true; // "\z "
}
Spade makes no guarantees about name uniqueness between generated Verilog modules.
[^1]: This is currently the lexical order of the occurrences, i.e. names which occur early in the module are given lower indices.