Skip to content

Instantly share code, notes, and snippets.

@josyb
Created August 13, 2018 16:11
Show Gist options
  • Save josyb/f3807e28d61b6d25d0739f27638176a0 to your computer and use it in GitHub Desktop.
Save josyb/f3807e28d61b6d25d0739f27638176a0 to your computer and use it in GitHub Desktop.
A simple ringcounter
class RingCounter():
''' a simple 'Overbeck' ring counter.
See https://en.wikipedia.org/wiki/Ring_counter
It has zero overhead cost as no logic is needed to start.
The following picture is worth a thousand words?
A B C D
---- | ---- | ---- | ---- |
-| 0 | |--| 1 |-----| 2 |-----| 3 |-----
| | | o- | | | | | |o-
| ---- ---- ---- ---- |
-------------------------------------------
0 1 2 3 A B C D
----------------
reset 0 0 0 0 1 0 0 0
clk1 1 1 0 0 0 1 0 0
clk2 1 0 1 0 0 0 1 0
clk3 1 0 0 1 0 0 0 1
clk4 0 0 0 0 1 0 0 0
This produces a self-starting ring counter
It does not self-correct! But we don't care about that, do we?
Even If SClr is used there is only one level of logic used, as
there is always a LUT in front of the register. Other solutions
use a wide AND-gate, which for longer ring-counters adds one or
more LUT levels. (Still an academic argument, though ....)
'''
def __init__(self, RANGE, Clk, Reset, SClr=None, CntEn=None, Q=None, CascadeOut=None):
self.RANGE = RANGE
assert RANGE > 1, 'A Ring Counter of size 1 doesn\'t make much sense'
self.Clk = Clk
self.Reset = Reset
self.SClr = SClr if SClr is not None else Signal(bool(0))
self.CntEn = CntEn if CntEn is not None else Signal(bool(0))
self.Q = Q if Q is not None else Signal(intbv(0)[RANGE:])
self.CascadeOut = CascadeOut if CascadeOut is not None else Signal(bool(0))
def rtl(self):
''' the logic '''
ringcounter = Signal(intbv(0)[self.RANGE:])
q0inv = Signal(bool(0))
if self.RANGE > 2:
@always_seq(self.Clk.posedge, reset=self.Reset)
def ringcount():
''' A simple 'Overbeck' ring counter.
But with a twist ...
'''
if self.SClr or self.CntEn:
if self.SClr:
ringcounter.next = 0
else:
ringcounter.next[0] = not ringcounter[self.RANGE - 1]
ringcounter.next[1] = q0inv
ringcounter.next[self.RANGE:2] = ringcounter[self.RANGE - 1:1]
else:
@always_seq(self.Clk.posedge, reset=self.Reset)
def ringcount():
''' A simple 'Overbeck' ring counter.
But with a twist ...
'''
if self.SClr or self.CntEn:
if self.SClr:
ringcounter.next = 0
else:
ringcounter.next[0] = not ringcounter[1]
ringcounter.next[1] = q0inv
@always_comb
def assign():
''' ringcounter: assignments '''
q0inv.next = not ringcounter[0]
self.Q.next = concat(ringcounter[:1], q0inv)
if self.CascadeOut != 'Open':
@always_comb
def assignco():
''' ringcounter: cascade-out assignment '''
self.CascadeOut.next = ringcounter[self.RANGE - 1] and self.CntEn
return instances()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment