Registers
Until now, all the constructs we have seen outside the blinky examples have been combinational (pure “functions”, in software terms). However, only combinational circuits does not get you very far; at some point you need to store some state. State in hardware is stored in registers, and unlike Verilog and VHDL where what is and is not a register is inferred based on the structure of the code, Spade has a dedicated construct for registers.
The simplest register looks like this:
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 = next;
On every rising edge of the clk signal, the value of the register will update to the current value of the next signal.
With this, we can build a counter:
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 = value Add two values, producing a value of the same size while wrapping 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. the result overflows. This is unlike + where the addition results in one more bit than the input type, guaranteeing no overflows. 1;
Note that unlike a let binding, the variable defined by a reg statement is visible to itself allowing you to create a register that depends on itself.
One obvious question about this counter is what value it will start counting at. Since this wasn’t specified above, it will be initialized to an explicit undefined value in simulation, and whatever the hardware ends up doing in hardware. In almost every case where you have a register that depends on itself, you need to give it an explicit initial value which is usually done with a reset. That looks like this:
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) = value Add two values, producing a value of the same size while wrapping 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. the result overflows. This is unlike + where the addition results in one more bit than the input type, guaranteeing no overflows. 1;
This syntax often takes a bit getting used to, generally it helps to read it as “the register value is reset whenever the rst signal is true. It gets reset to 0, and if it is not being reset, its value is value + 1”.
In this case, the compiler will not be able to infer how many bits the value signal needs. In many cases, the compiler can infer it from context, but sometimes you have to specify the type explicitly, which like let bindings, is done with : type after the name:
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 unsigned 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 Defines the reset value of a register as (trigger: value). When trigger ist rue, the reset is synchronously reset to valuerst: 0) = value Add two values, producing a value of the same size while wrapping 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. the result overflows. This is unlike + where the addition results in one more bit than the input type, guaranteeing no overflows. 1;
This is also the reason we have to use +. and not +. Whatever type value has, value + 1 will be one bit larger, but since value + 1 needs to be stored in the register containing the value, it needs to be truncated back down.
Exercise
This register will count from 0 to 255, relying on the wrapping behaviour of +. to go back to 0. Modify the example to make the counter count up to 100 before going back to 0.
Initial Values
For hardware which supports it (in general FPGAs and not ASICs), you can specify an initial value which gets set at startup without an explicit reset signal:
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 initial(0) = value Add two values, producing a value of the same size while wrapping 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. the result overflows. This is unlike + where the addition results in one more bit than the input type, guaranteeing no overflows. 1;
While avoiding having to define and pass around an explicit reset signal is sometimes convenient, it does make the code less portable. Therefore, it is often best to use the initial value to define a reset signal for use by the rest of the design:
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. rst initial(true) = false;
Before the first clock cycle, this will initialize the rst value to true which can then be used to reset the rest of the circuit. After the first cycle, the rst signal will switch to false, starting up the rest of the circuit.