Counter

To implement a counter we can use the Register primitive and the + operator. How can we make a more general counter of arbitray width?


In [1]:
import magma as m
from mantle import Register

The generator for a counter is parameterized by the number of bits in the counter, n.


In [2]:
class Counter(m.Generator):
    @staticmethod
    def generate(width: int):
        class _Counter(m.Circuit):
            name = f'Counter{width}'
            io = m.IO(O=m.Out(m.UInt[width])) + m.ClockIO()

            reg = Register(width, _type=m.UInt)
            io.O @= reg(reg.O + 1)
        return _Counter

Simulate the counter.


In [3]:
from fault import PythonTester

Counter4 = Counter.generate(4)
tester = PythonTester(Counter4, Counter4.CLK)

tester.eval()
val = tester.peek(Counter4.O)
print(tester.peek(Counter4.O))
assert val == 0

for i in range(1,11): 
    tester.step() # toggle clock - now High
    assert i == tester.peek(Counter4.O)
    print(tester.peek(Counter4.O))

    tester.step() # toggle clock - now Low
    assert i == tester.peek(Counter4.O)

print("Success!")


0
1
2
3
4
5
6
7
8
9
10
Success!

In [4]:
m.compile("build/Counter4", Counter4, inline=True)
!coreir -i build/Counter4.json -p instancecount
!cat build/Counter4.v


An instance count of all the primitives
=======================================
Counter4 | instances in current | instances in children | 
  coreir_add__width4 | 1 | 0
  coreir_const__width4 | 1 | 0
  coreir_reg__width4 | 1 | 0

=======================================
{"top":"global.Counter4",
"namespaces":{
  "global":{
    "modules":{
      "Counter4":{
        "type":["Record",[
          ["O",["Array",4,"Bit"]],
          ["CLK",["Named","coreir.clkIn"]]
        ]],
        "instances":{
          "const_1_4":{
            "genref":"coreir.const",
            "genargs":{"width":["Int",4]},
            "modargs":{"value":[["BitVector",4],"4'h1"]}
          },
          "magma_Bits_4_add_inst0":{
            "genref":"coreir.add",
            "genargs":{"width":["Int",4]}
          },
          "reg_P_inst0":{
            "genref":"coreir.reg",
            "genargs":{"width":["Int",4]},
            "modargs":{"clk_posedge":["Bool",true], "init":[["BitVector",4],"4'h0"]}
          }
        },
        "connections":[
          ["magma_Bits_4_add_inst0.in1","const_1_4.out"],
          ["reg_P_inst0.out","magma_Bits_4_add_inst0.in0"],
          ["reg_P_inst0.in","magma_Bits_4_add_inst0.out"],
          ["self.CLK","reg_P_inst0.clk"],
          ["self.O","reg_P_inst0.out"]
        ]
      }
    }
  }
}
}
/Users/travis/build/leonardt/pycoreir/coreir-cpp/src/binary/coreir.cpp:238 Modified?: No
module coreir_reg #(
    parameter width = 1,
    parameter clk_posedge = 1,
    parameter init = 1
) (
    input clk,
    input [width-1:0] in,
    output [width-1:0] out
);
  reg [width-1:0] outReg=init;
  wire real_clk;
  assign real_clk = clk_posedge ? clk : ~clk;
  always @(posedge real_clk) begin
    outReg <= in;
  end
  assign out = outReg;
endmodule

module Counter4 (
    output [3:0] O,
    input CLK
);
coreir_reg #(
    .clk_posedge(1'b1),
    .init(4'h0),
    .width(4)
) reg_P_inst0 (
    .clk(CLK),
    .in(O + 4'h1),
    .out(O)
);
endmodule


In [ ]: