-
-
Save twam/51733f6ae1c9fd7f53bd5ab05060b410 to your computer and use it in GitHub Desktop.
seven_segment_serial.py
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
from typing import List, Dict | |
from enum import IntEnum | |
from nmigen import * | |
from nmigen.utils import * | |
from nmigen.back.pysim import * | |
from nibble_to_segments import * | |
from tlc591x import * | |
class SevenSegmentSerialState(IntEnum): | |
CONVERT = 0, | |
TRANSMIT = 1 | |
class SevenSegmentSerial(Elaboratable): | |
def __init__(self, number_of_digits = 1): | |
self.number_of_digits = number_of_digits | |
# SPI | |
self.do = Signal(reset=0) | |
self.sclk = Signal(reset=0) | |
self.le = Signal(reset=0) | |
self.oe = Signal(reset=1) # Output is disabled by default | |
# Data | |
self.data = Signal(self.number_of_digits*4) | |
self.data_segments = Signal(self.number_of_digits*8) | |
# Internal | |
self.state = Signal(SevenSegmentSerialState) | |
self.nibble = Signal(4) | |
self.segments = Signal(8) | |
self.counter = Signal(5) | |
def ports(self) -> List[Signal]: | |
return [] | |
def elaborate(self, platform) -> Module: | |
m = Module() | |
m.submodules.nibble_to_segments = nibble_to_segments = NibbleToSegments() | |
m.d.comb += nibble_to_segments.nibble.eq(self.nibble) | |
m.d.comb += self.segments.eq(nibble_to_segments.segments) | |
m.submodules.tlc591x = tlc591x = Tlc591x(number_of_chips = self.number_of_digits) | |
m.d.comb += tlc591x.data.eq(self.data_segments) | |
m.d.comb += self.do.eq(tlc591x.do) | |
m.d.comb += self.sclk.eq(tlc591x.sclk) | |
m.d.comb += self.le.eq(tlc591x.le) | |
m.d.comb += self.oe.eq(tlc591x.oe) | |
m.d.sync += self.counter.eq(self.counter + 1) | |
m.d.comb += tlc591x.latch.eq(0) | |
with m.Switch(self.state): | |
with m.Case(SevenSegmentSerialState.CONVERT): | |
# m.d.comb += self.nibble.eq(self.data.word_select(self.number_of_digits-1-self.counter, 4)) | |
m.d.comb += self.nibble.eq(self.data.bit_select((self.number_of_digits-1-self.counter)*4, 4)) | |
# m.d.sync += self.data_segments.word_select(self.counter, 8).eq(self.segments) | |
m.d.sync += self.data_segments.bit_select(self.counter*8, 8).eq(self.segments) | |
with m.If(self.counter == self.number_of_digits-1): | |
self.switch_state(m, SevenSegmentSerialState.TRANSMIT) | |
with m.Case(SevenSegmentSerialState.TRANSMIT): | |
with m.If(self.counter == 0): | |
m.d.comb += tlc591x.latch.eq(1) | |
with m.If(self.counter == 1): | |
with m.If(tlc591x.ready == 0): | |
m.d.sync += self.counter.eq(1) | |
with m.Else(): | |
self.switch_state(m, SevenSegmentSerialState.CONVERT) | |
return m | |
def switch_state(self, m: Module, state: SevenSegmentSerialState): | |
m.d.sync += self.counter.eq(0) | |
m.d.sync += self.state.eq(state) | |
if __name__ == "__main__": | |
dut = SevenSegmentSerial(number_of_digits = 4) | |
sim = Simulator(dut) | |
sim.add_clock(1e-6) | |
def process(): | |
yield dut.data.eq(0x0123) | |
for i in range(dut.data.width*4*2+10): | |
yield | |
sim.add_sync_process(process) | |
with sim.write_vcd('seven_segment_serial.vcd', 'seven_segment_serial.gtkw', traces=[]+dut.ports()): | |
sim.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment