Created
August 13, 2018 16:11
-
-
Save josyb/f3807e28d61b6d25d0739f27638176a0 to your computer and use it in GitHub Desktop.
A simple ringcounter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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