Added Hub75 Led Matrix driver

master
wolfgang 2 years ago
parent 792179779b
commit 01de59f1b9
  1. 107
      hub75sender.py

@ -0,0 +1,107 @@
#!/usr/bin/env python3
# This file is Copyright (c) 2020 Wolfgang Villing <ringel@it-ringel.de>
# SPDX-License-Identifier: BSD-3-Clause
import math
from migen import *
from migen.fhdl import verilog
class Hub75Sender(Module):
def __init__(self, numCols=8, numRows=4, content=None):
addressOffset = Constant(numCols * numRows/2)
rowCountShift = math.ceil(math.log2(numCols))
# Memory mapped to Wishbone - having second read port
self.specials.mem = Memory(8, numCols * numRows, init=content)
ram = self.mem.get_port()
self.specials += ram
# Pixel and Row counter
self.pixCount = Signal(max=numCols+1)
self.rowCount = Signal(max=numRows)
# Temporary Pixeldata register
self.pixUpper = Signal(8)
self.pixLower = Signal(8)
# Output Ports
self.outAddr = Signal(6) # abcde
self.outClk = Signal()
self.outOe = Signal()
self.outLat = Signal()
self.outRGB = Signal(8) # (6) r0 r1 g0 g1 b0 b1
fsm = FSM(reset_state="RESET")
self.submodules.fsm = fsm
fsm.act("RESET",
NextValue(self.pixCount, 0),
NextValue(self.outOe, 1),
NextState("AdrUp"))
fsm.act("AdrUp", # Address upper Pixel
ram.adr.eq(self.pixCount + (self.rowCount << rowCountShift)),
NextState("AdrLo"))
fsm.act("AdrLo", # Address lower Pixel + Readout Upper Pixel data
ram.adr.eq((self.pixCount + addressOffset) + (self.rowCount << rowCountShift)),
NextValue(self.pixCount, self.pixCount+1),
self.pixUpper.eq(ram.dat_r),
NextState("ReadLow"))
fsm.act("ReadLow", # Readout Lower Pixel data
self.pixLower.eq(ram.dat_r),
self.pixUpper.eq(self.pixUpper),
# Set Output
self.outRGB.eq(Cat(self.pixUpper[0:4], self.pixLower[0:4])),
NextState("ClkOn"))
fsm.act("ClkOn", # Clock the Data out
self.outRGB.eq(self.outRGB),
self.outClk.eq(1),
NextState("ClkOff"))
fsm.act("ClkOff", # Clock the Data out
self.outRGB.eq(self.outRGB),
If(self.pixCount == numCols,
NextValue(self.outOe, 0),
NextValue(self.rowCount, self.rowCount + 1),
NextValue(self.pixCount, 0),
NextState("OeOff") # Finished with Row
).Else(
NextState("AdrUp")
))
fsm.act("OeOff", NextValue(self.outLat, 1), NextState("LatOn"))
fsm.act("LatOn", NextValue(self.outAddr, self.rowCount), NextState("AdrRow"))
fsm.act("AdrRow", NextValue(self.outLat, 0), NextState("LatOff"))
fsm.act("LatOff", NextValue(self.outOe, 1), NextState("OeOn"))
fsm.act("OeOn",
If(self.rowCount == Constant(numRows/2),
NextValue(self.rowCount, 0),
NextState("Done")
).Else(
NextState("AdrUp"))
)
fsm.act("Done", NextState("Done"))
def testbench():
content = (0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f)
dut = Hub75Sender(6, 8, content)
def memtest():
for _ in range(200):
yield
yield
#print(verilog.convert(dut, dut.ios))
run_simulation(dut, memtest(), vcd_name="hub75sender.vcd", clocks={"sys": 1000})
Loading…
Cancel
Save