Created
March 18, 2021 02:03
-
-
Save newhouseb/9e8591b1a1c3b910482cef24930d9068 to your computer and use it in GitHub Desktop.
1.8GHz Gray Code Oscillator/Counter
This file contains hidden or 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
# 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