diff --git a/groovylight/hub75.py b/groovylight/hub75.py index 5dffe07..b54b471 100644 --- a/groovylight/hub75.py +++ b/groovylight/hub75.py @@ -2,9 +2,8 @@ # r0 g0 b0 gnd r1 g1 b1 e a b c d clk stb oe gnd from litex.build.generic_platform import Signal, Subsignal, Pins -from litex.build.io import FSM, Module -from litex.gen import If, NextState, NextValue -from migen import Cat +from litex.build.io import FSM, Module, Cat, Replicate +from litex.gen import ClockSignal, If, Instance, NextState, NextValue def make_hub75_iodevice(index, basename): b = basename @@ -23,6 +22,7 @@ def make_hub75_iodevice(index, basename): return [signals] + class Hub75Driver(Module): def __init__(self, base_freq=60e6, linedepth=128): if base_freq // 2 > 30e6: @@ -90,3 +90,57 @@ class Hub75Driver(Module): NextState("WRITEROW"), ) + + +class Hub75VerilogDriver(Module): + def __init__(self): + clk = Signal() + + self.i_write_trig = Signal() + self.i_addr_in = Signal(5) + self.o_addr_out = Signal(5) + self.o_display_clk = Signal() + self.o_enable = Signal() + self.o_latch = Signal() + self.o_out_enable = Signal() + self.o_done = Signal() + self.o_panel_rgb0 = Signal(3) + self.o_panel_rgb1 = Signal(3) + + self.pixbuf_addr = Signal(9) + self.pixbuf_data = Signal(36) + + self.comb += ClockSignal().eq(clk) + + # simple driver fsm + self.comb += self.pixbuf_data.eq(Replicate(self.pixbuf_addr, 3)) + + self.fsm = fsm = FSM() + + fsm.act("start", + NextValue(self.i_write_trig, 1), + NextState("wait"), + ) + fsm.act("wait", + NextValue(self.i_write_trig, 0), + If(self.o_done, + NextState("start"), + ) + ) + self.submodules += self.fsm + + inst = Instance("hub75e", + i_clk = clk, + i_write_trig = self.i_write_trig, + i_addr_in = self.i_addr_in, + o_addr_out = self.o_addr_out, + o_panel_rgb0 = self.o_panel_rgb0, + o_panel_rgb1 = self.o_panel_rgb1, + o_latch = self.o_latch, + o_display_clk = self.o_display_clk, + o_done = self.o_done, + o_out_enable = self.o_out_enable, + o_pixbuf_addr = self.pixbuf_addr, + i_pixbuf_data = self.pixbuf_data + ) + self.specials += inst diff --git a/groovylight/soc.py b/groovylight/soc.py index d39bd07..30d4b9b 100644 --- a/groovylight/soc.py +++ b/groovylight/soc.py @@ -13,7 +13,7 @@ from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII from platform.colorlight_5a_75b_8_0 import Groovy1Platform -from hub75 import Hub75Driver, make_hub75_iodevice +from hub75 import Hub75Driver, make_hub75_iodevice, Hub75VerilogDriver class GroovySoC(SoCCore): def __init__(self, platform, sys_clk_freq, @@ -51,20 +51,20 @@ class GroovySoC(SoCCore): self.add_spi_flash(mode="1x", module=SpiFlashModule, with_master=False) self.platform.add_extension(make_hub75_iodevice(0, "j8")) hub_io = self.platform.request("hub75_iodev", 0) - self.submodules.hub75 = hub75 = ClockDomainsRenamer("hub")(Hub75Driver()) + self.submodules.hub75 = hub75 = ClockDomainsRenamer("hub")(Hub75VerilogDriver()) self.comb += [ - hub_io.r0.eq(hub75.rgb[0]), - hub_io.r1.eq(hub75.rgb[3]), - hub_io.g0.eq(hub75.rgb[1]), - hub_io.g1.eq(hub75.rgb[4]), - hub_io.b0.eq(hub75.rgb[2]), - hub_io.b1.eq(hub75.rgb[5]), - hub_io.clk.eq(hub75.clock_out), - hub_io.addr.eq(hub75.addr), - hub_io.oe.eq(hub75.output_en), - hub_io.stb.eq(hub75.latch), - + hub_io.r0.eq(hub75.o_panel_rgb0[0]), + hub_io.g0.eq(hub75.o_panel_rgb0[1]), + hub_io.b0.eq(hub75.o_panel_rgb0[2]), + hub_io.r1.eq(hub75.o_panel_rgb1[0]), + hub_io.g1.eq(hub75.o_panel_rgb1[1]), + hub_io.b1.eq(hub75.o_panel_rgb1[2]), + hub_io.clk.eq(hub75.o_display_clk), + hub_io.addr.eq(hub75.o_addr_out), + hub_io.oe.eq(hub75.o_out_enable), + hub_io.stb.eq(hub75.o_latch), ] + platform.add_source("verilog/hub75e.sv") diff --git a/verilog/hub75e.sv b/verilog/hub75e.sv index 46eefb4..f72089d 100644 --- a/verilog/hub75e.sv +++ b/verilog/hub75e.sv @@ -1,7 +1,8 @@ module hub75e ( input clk, input write_trig, - output reg [4:0] addr, + input [4:0] addr_in, // only latched in during init. + output reg [4:0] addr_out, output reg [2:0] panel_rgb0, output reg [2:0] panel_rgb1, output reg display_clk = 0, @@ -10,8 +11,8 @@ module hub75e ( output reg done = 0, // bram interface (using clk) - output reg [8:0] pixbuf_addr, - input [35:0] pixbuf_data + output reg [10:0] pixbuf_addr, + input [8:0] pixbuf_data ); parameter integer ROW_DEPTH = 128, BIT_DEPTH = 8; @@ -132,6 +133,7 @@ module hub75e ( end end default: begin + state <= StateInit; end endcase end diff --git a/verilog/lineram.v b/verilog/lineram.v index 564b4ed..d03d4f1 100644 --- a/verilog/lineram.v +++ b/verilog/lineram.v @@ -1,6 +1,6 @@ module lineram #( - parameter DATA_WIDTH = 36, - parameter ADDR_WIDTH = 9 + parameter DATA_WIDTH = 9, + parameter ADDR_WIDTH = 11 ) ( input [DATA_WIDTH - 1:0] din, input [ADDR_WIDTH - 1:0] addr_w, @@ -11,10 +11,70 @@ module lineram #( input write_clk ); +// `ifdef YOSYS +// // use the ECP5 primitive. +// defparam ram.PORT_W_WR_EN_WIDTH = 1; +// $__ECP5_PDPW16KD_ ram ( +// .PORT_R_CLK(read_clk), +// .PORT_R_ADDR(addr_r), +// .PORT_R_RD_DATA(dout), +// .PORT_W_CLK(write_clk), +// .PORT_W_WRITE_EN(write_en), +// .PORT_W_WR_DATA(din), +// ); +// // PDPW16KD ram ( +// // .DI0 (din[0]), +// // .DI1 (din[1]), +// // .DI2 (din[2]), +// // .DI3 (din[3]), +// // .DI4 (din[4]), +// // .DI5 (din[5]), +// // .DI6 (din[6]), +// // .DI7 (din[7]), +// // .DI8 (din[8]), +// // .DI9 (din[9]), +// // .DI10(din[10]), +// // .DI11(din[11]), +// // .DI12(din[12]), +// // .DI13(din[13]), +// // .DI14(din[14]), +// // .DI15(din[15]), +// // .DI16(din[16]), +// // .DI17(din[17]), +// // .DI18(din[18]), +// // .DI19(din[19]), +// // .DI20(din[20]), +// // .DI21(din[21]), +// // .DI22(din[22]), +// // .DI23(din[23]), +// // .DI24(din[24]), +// // .DI25(din[25]), +// // .DI26(din[26]), +// // .DI27(din[27]), +// // .DI28(din[28]), +// // .DI29(din[29]), +// // .DI30(din[30]), +// // .DI31(din[31]), +// // .DI32(din[32]), +// // .DI33(din[33]), +// // .DI34(din[34]), +// // .DI35(din[35]), +// // .ADW0(addr_w[0]), +// // .ADW1(addr_w[1]), +// // .ADW2(addr_w[2]), +// // .ADW3(addr_w[3]), +// // .ADW4(addr_w[4]), +// // .ADW5(addr_w[5]), +// // .ADW6(addr_w[6]), +// // .ADW7(addr_w[7]), +// // .ADW8(addr_w[8]), +// // +// // ); +// `else reg [DATA_WIDTH - 1] ram[2**ADDR_WIDTH]; initial begin - for(int i=0; i < 2**ADDR_WIDTH; i=i+1) begin + for (int i = 0; i < 2 ** ADDR_WIDTH; i = i + 1) begin ram[i] = 0; end end @@ -25,4 +85,5 @@ module lineram #( always @(posedge read_clk) begin dout <= ram[addr_r]; end +// `endif endmodule