I have the following loop in Chisel, that counts the number of ones in a register:
val word = RegInit(0.U(32.W))
// Register for data input
word := Mux(io.optn === 1.U, io.dataIn, word)
counter := 0.U
for (i <- 31 to 0 by -1) {
when(word(i)) {
counter := counter + 1.U
} .otherwise {
counter := counter
}
}
Using Firtool to generate the equivalent verilog I get this:
reg [31:0] word;
reg [5:0] counter;
wire [5:0] _counter_T_1 = counter + 6'h1;
always @(posedge clock) begin
if (reset) begin
word <= 32'h0;
end else if (io_optn == 2'h1) begin
word <= io_dataIn;
end
if (reset) begin
counter <= 6'h0;
end else if (word[0]) begin
counter <= _counter_T_1;
end
I am a beginner with hardware description languages, and I don’t understand why word is indexed with 0 at each cycle, in the generated verilog ?
The canonicaliser in Firtool appears to collapse all the bit accesses of the unrolled loop at word[i] into word[0]. Is there something I am missing about the properties of registers ? (e.g. word is shifted each cycle)
firtool recognizes that the last when block is the only one that matters and it optimizes away all the dead previous ones.
You’re likely looking for a population count utility ( chisel3.util.PopCount / PopCount$ - chisel_2.13 6.0.0-M3 javadoc) and can then update the counter with the number of ones in word.
Adding to what @seldridge said: if you wanted to implement this yourself, you’d have to make counter be a Scala variable that you keep updating. Using the := connect operator will override all previous assignments, which isn’t what you want. For example:
val word = RegInit(0.U(32.W))
word := Mux(io.optn === 1.U, io.dataIn, word)
var currentCount = 0.U
for (i <- 31 to 0 by -1) {
currentCount = currentCount + word(i).asUInt
}
counter := currentCount
With := you are redefining the value of counter 32 times, and only the last definition will stick around. And note that after counter := ... in the previous loop happened, the following loop iteration will not read that previously assigned value for counter, it will read what counter will eventually be assigned to after all assignments have been resolved.
Instead, you want to use a Scala var and build up a nesting of 32 adders that add each word bit to the count of the previous iteration. Then at the very end just assign that as the counter value.
In practice you’ll want to create a more optimized tree structure for this, which is what @seldridge’s suggestion will give you.