[BSV] Sequential Circuits and Modules
Registers and Sequential Circuits
In BSV (Bluespec SystemVerilog), we can construct sequential circuits with registers. Registers are modules that stores data, and can be updated at each clock cycle. Registers are accessed via the Reg# interface. The following example shows how register interfaces are declared, initialized and their value updated in a rule.
module mkCounter(Empty);
Reg#(UInt#(8)) regA <- mkReg(0);
Reg#(Bit#(4)) regB <- mkRegU;
Reg#(Bit#(4)) regC <- mkRegU;
rule updateA (regA < 64);
regA <= regA + 1;
endrule
rule swap;
regB <= regC;
regC <= regB;
endrule
endmodule
mkReg(0) instantiates a register module and initializes its value as 0. Meanwhile, mkRegU instantiates a register but does not initialize its value. The first rule, updateA increments the value of regA at every clock cycle, if the condition in the parenthesis (called the guard) is satisfied. The second rule swaps the value of regB and regC.
Rules are basically parallel. All the register updates in a rule is carried out simultaneously. (Because hardware is basically parallel. Recall how flip-flops and registers work) Each rules are atomic; in a single cycle, a rule is either carried out completely or not at all, no partial executions. Also, the execution of a rule is not affected by other rules in a cycle.
Modules and Interfaces
A module in BSV is like an object in objected-oriented programming language. The method of a module replaces the 'input', 'output', 'enable' and 'ready' wires in a hardware module. So we can treat a sequential circuit like an object. Furthermore, the module can be accessed from the outside world only through the interface of the module. This masks the internal structure of the module, providing abstraction of sequential circuits.
Following is an example of a module's methods and an interface. (The module implements a 64-bit multiplication module.)
interface Multiply;
method Action start(Bit#(64) a, Bit#(64) b);
method Bit#(128) result();
endinterface
module mkMultiply64 (Multiply);
Reg#(Bit#(64)) a <- mkRegU();
Reg#(Bit#(64)) b <- mkRegU();
Reg#(Bit#(64)) prod <-mkRegU();
Reg#(Bit#(64)) tp <- mkRegU();
Reg#(Bit#(7)) i <- mkReg(64);
rule mulStep (i != 64);
Bit#(64) m = (a[0]==0)? 0 : b;
Bit#(65) sum = add64(m,tp,0);
prod <= {sum[0], (prod >> 1)[62:0]};
tp <= truncateLSB(sum); a <= a >> 1; i <= i+1;
endrule
method Action start(Bit#(64) aIn, Bit#(64) bIn) if (i == 64);
a <= aIn; b <= bIn; i <= 0; tp <= 0; prod <= 0;
endmethod
method Bit#(128) result() if (i == 64);
return {tp,prod};
endmethod
endmodule
As you can see, methods can also have guards.
Also There are 3 kinds of methods.
BSV Methods
- Value methods: The module returns a value to the caller.
- Action methods: The caller changes internal state of the module.
- ActionValue methods: combination of Value and Action methods.
Value methods are specified with a return type, as shown above.
ActionValue methods are specified with return type of ActionValue#(type). (e.g. ActionValue#(Bit#(128)) result(); )
One interesting feature of BSV modules is that modules can be turned into polymorphic modules, by parameterizing the interface. Following is an example of a polymorphic multiplication module, from which we can instantiate multiplication circuits with various input bit lengths.
interface MultiplyN#(Numeric type n);
method Action start(Bit#(n) a, Bit#(n) b);
method Bit#(TAdd#(n,n)) result();
endinterface
module mkMultiplyN (MultiplyN#(n));
Reg#(Bit#(n)) a <- mkRegU();
Reg#(Bit#(n)) b <- mkRegU();
Reg#(Bit#(n)) prod <-mkRegU();
Reg#(Bit#(n)) tp <- mkRegU();
let nv = fromInteger(valueOf(n));
Reg#(Bit#(TAdd#(TLog#(n),1))) i <- mkReg(nv);
rule mulStep (i != nv);
Bit#(n) m = (a[0]==0)? 0 : b;
Bit#(Tadd#(n,1)) sum = addN(m,tp,0);
prod <= {sum[0], (prod >> 1)[(nv-2):0]};
tp <= truncateLSB(sum); a <= a >> 1; i <= i+1;
endrule
method Action start(Bit#(n) aIn, Bit#(n) bIn) if (i == nv);
a <= aIn; b <= bIn; i <= 0; tp <= 0; prod <= 0;
endmethod
method Bit#(Tadd#(n,n)) result() if (i == nv);
return {tp,prod};
endmethod
endmodule
The next post will cover designing and pipelining complex combinational circuits in BSV.
References
- Rishiyur. S. Nikhil, Kathy Czeck. "BSV by Example". Bluespec(2010).
- Bluespec SystemVerilog Reference Guide
- Class materials of SNU CSE (2025)