Skip to content

Instantly share code, notes, and snippets.

@newhouseb
Created March 18, 2021 02:03
Show Gist options
  • Save newhouseb/9e8591b1a1c3b910482cef24930d9068 to your computer and use it in GitHub Desktop.
Save newhouseb/9e8591b1a1c3b910482cef24930d9068 to your computer and use it in GitHub Desktop.
1.8GHz Gray Code Oscillator/Counter
# This is a 5bit wide gray code counter using the additional parts of the CLBs in Lattice Devices to build out LUT5s.
# We can go even bigger at the cost of oscillation speed (I think this is around 1.8GHz rather than 2GHz for the 4bit version)
class AsynchronousGrayCodeCounter(Elaboratable):
def __init__(self, sync=False, domain='sync'):
self.async_gray_count = Signal(5)
self.latched_gray_count = Signal(5)
self.sync = sync
self.domain = domain
def elaborate(self, platform):
m = Module()
# We could programmatically generate this in fewer lines,
# but I find it handy as a reference when checking signals
sequence = [
0b00000,
0b00001,
0b00011,
0b00010,
0b00110,
0b00111,
0b00101,
0b00100,
0b01100,
0b01101,
0b01111,
0b01110,
0b01010,
0b01011,
0b01001,
0b01000,
0b11000,
0b11001,
0b11011,
0b11010,
0b11110,
0b11111,
0b11101,
0b11100,
0b10100,
0b10101,
0b10111,
0b10110,
0b10010,
0b10011,
0b10001,
0b10000,
]
maps = []
for idx in range(5):
logicmap = [0]*len(sequence)
for i in range(len(sequence)):
logicmap[sequence[i]] = 1 if sequence[(i + 1) % len(sequence)] & (1 << idx) else 0
maps.append(logicmap)
def pack(m):
return sum([m[i] << i for i in range(len(m))])
def get_slice():
start_x = 10
start_y = 11
slice_i = 0
while True:
yield "X{}/Y{}/SLICE{}".format(start_x, start_y, ["A","B","C","D"][slice_i])
if slice_i == 3:
start_x += 1
slice_i = (slice_i + 1) % 4
gen_slice = get_slice()
inputs = self.latched_gray_count if self.sync else self.async_gray_count
for i in range(5):
lut = Instance("TRELLIS_SLICE",
a_BEL=next(gen_slice),
p_MODE="LOGIC",
p_REG0_SD="1",
p_REG1_SD="1",
p_LUT0_INITVAL=pack(maps[i][0:16]),
i_A0=inputs[0],
i_B0=inputs[1],
i_C0=inputs[2],
i_D0=inputs[3],
p_LUT1_INITVAL=pack(maps[i][16:32]),
i_A1=inputs[0],
i_B1=inputs[1],
i_C1=inputs[2],
i_D1=inputs[3],
i_M0=inputs[4],
o_OFX0=self.async_gray_count[i],
i_DI0=self.async_gray_count[i],
o_Q0=self.latched_gray_count[i],
i_CLK=ClockSignal(self.domain)
)
setattr(m.submodules, 'lut' + str(i), lut)
return m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment