From 37dabd603aa41a9a0d05bcfaaf80c3b0ea81acce Mon Sep 17 00:00:00 2001 From: saji Date: Wed, 1 May 2024 16:14:32 -0500 Subject: [PATCH] coordinator works now fixed some off by one errors to make the screen work good --- groovylight/hub75.py | 40 +----- groovylight/platform/colorlight_5a_75b_8_0.py | 2 - groovylight/soc.py | 8 +- verilog/bitslicer.sv | 19 +-- verilog/coordinator.sv | 31 +++-- verilog/hub75e.sv | 32 +++-- verilog/lineram.v | 127 +++++++++--------- verilog/pixgen.sv | 2 +- verilog/tb/coordinator_tb.sv | 2 +- 9 files changed, 117 insertions(+), 146 deletions(-) diff --git a/groovylight/hub75.py b/groovylight/hub75.py index b54b471..0bd7eed 100644 --- a/groovylight/hub75.py +++ b/groovylight/hub75.py @@ -94,53 +94,21 @@ class Hub75Driver(Module): 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_addr = 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, + inst = Instance("coordinator", + i_clk = ClockSignal(), 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 + o_display_addr = self.o_addr, ) self.specials += inst diff --git a/groovylight/platform/colorlight_5a_75b_8_0.py b/groovylight/platform/colorlight_5a_75b_8_0.py index 1afab65..a3dc8d7 100644 --- a/groovylight/platform/colorlight_5a_75b_8_0.py +++ b/groovylight/platform/colorlight_5a_75b_8_0.py @@ -113,8 +113,6 @@ class _CRG(LiteXModule): # pll.create_clkout(self.cd_sdram, sys_clk_freq, phase=180) pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq) pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180) - pll.create_clkout(self.cd_hub, 60e6) - sdram_clk = ClockSignal("sys2x_ps") # sdram_clk = ClockSignal("sdram") diff --git a/groovylight/soc.py b/groovylight/soc.py index 30d4b9b..d8927ee 100644 --- a/groovylight/soc.py +++ b/groovylight/soc.py @@ -51,7 +51,7 @@ 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")(Hub75VerilogDriver()) + self.submodules.hub75 = hub75 = Hub75VerilogDriver() self.comb += [ hub_io.r0.eq(hub75.o_panel_rgb0[0]), hub_io.g0.eq(hub75.o_panel_rgb0[1]), @@ -60,11 +60,11 @@ class GroovySoC(SoCCore): 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.addr.eq(hub75.o_addr), hub_io.oe.eq(hub75.o_out_enable), hub_io.stb.eq(hub75.o_latch), ] - platform.add_source("verilog/hub75e.sv") + platform.add_sources("./verilog/", "bitslicer.sv", "coordinator.sv", "hub75e.sv", "lineram.v", "pixgen.sv") @@ -85,7 +85,7 @@ def main(): trellis_args(parser.add_argument_group('Trellis options')) args = parser.parse_args() platform = Groovy1Platform() - soc = GroovySoC(platform, 75e6, **soc_core_argdict(args)) + soc = GroovySoC(platform, 60e6, **soc_core_argdict(args)) builder = Builder(soc, **builder_argdict(args)) diff --git a/verilog/bitslicer.sv b/verilog/bitslicer.sv index 4038ad6..ac17af4 100644 --- a/verilog/bitslicer.sv +++ b/verilog/bitslicer.sv @@ -1,7 +1,8 @@ module bitslicer ( input clk, - input [23:0] rgb[2], - input [8:0] pixnum, // x-value of the pixels we are being fed. + input [23:0] rgb0, + input [23:0] rgb1, + input [7:0] pixnum, // x-value of the pixels we are being fed. input start_write, output reg [5:0] bitplane_data, output [10:0] bitplane_addr, @@ -10,14 +11,14 @@ module bitslicer ( ); reg [2:0] bitplane_bit = 0; - assign bitplane_addr = (pixnum << 3) + bitplane_bit; + assign bitplane_addr = {bitplane_bit, pixnum}; assign bitplane_data = { - rgb[1][bitplane_bit], - rgb[1][bitplane_bit+8], - rgb[1][bitplane_bit+16], - rgb[0][bitplane_bit], - rgb[0][bitplane_bit+8], - rgb[0][bitplane_bit+16] + rgb1[bitplane_bit], + rgb1[bitplane_bit+8], + rgb1[bitplane_bit+16], + rgb0[bitplane_bit], + rgb0[bitplane_bit+8], + rgb0[bitplane_bit+16] }; reg [3:0] state = StateInit; diff --git a/verilog/coordinator.sv b/verilog/coordinator.sv index 8472e80..f2afc1d 100644 --- a/verilog/coordinator.sv +++ b/verilog/coordinator.sv @@ -1,12 +1,19 @@ module coordinator ( - input clk + input clk, + output display_clk, + output out_enable, + output latch, + output [2:0] panel_rgb0, + output [2:0] panel_rgb1, + output reg [4:0] display_addr ); // pixgen signals reg pixgen_start; reg [8:0] x; reg [8:0] y; - wire [23:0] pix_rgb[2]; + wire [23:0] pix_rgb0; + wire [23:0] pix_rgb1; wire [1:0] pix_done; pixgen pix0 ( @@ -14,7 +21,7 @@ module coordinator ( .start(pixgen_start), .x(x), .y(y), - .rgb(pix_rgb[0]), + .rgb(pix_rgb0), .done(pix_done[0]) ); pixgen pix1 ( @@ -22,7 +29,7 @@ module coordinator ( .start(pixgen_start), .x(x), .y(y + 9'd32), - .rgb(pix_rgb[1]), + .rgb(pix_rgb1), .done(pix_done[1]) ); @@ -36,7 +43,8 @@ module coordinator ( bitslicer bslice ( .clk(clk), - .rgb(pix_rgb), + .rgb0(pix_rgb0), + .rgb1(pix_rgb1), .pixnum(x), .start_write(bitslice_start), .bitplane_data(bitplane_data), @@ -48,7 +56,6 @@ module coordinator ( // bram signals wire [8:0] din; - wire [10:0] addr_w; wire [8:0] dout; wire [10:0] addr_r; wire read_clk; @@ -67,11 +74,6 @@ module coordinator ( // driver reg write_line; wire line_done; - wire [2:0] panel_rgb0; - wire [2:0] panel_rgb1; - wire display_clk; - wire out_enable; - wire latch; hub75e driver ( .clk(clk), @@ -102,6 +104,8 @@ module coordinator ( StateInit: begin x <= 0; y <= 0; + display_addr <= 0; + write_line <= 0; state <= StateStartFrame; end StateStartFrame: begin @@ -111,7 +115,7 @@ module coordinator ( StateGenerateLine: begin pixgen_start <= 0; if (bitplane_done) begin - if (x < 127) begin + if (x < 128) begin x <= x + 1; pixgen_start <= 1; // generate next @@ -129,8 +133,9 @@ module coordinator ( end StateIncrementLine: begin x <= 0; + display_addr <= display_addr + 1; y <= y + 1; - if (y == 31) begin + if (display_addr == 31) begin state <= StateInit; end else begin state <= StateStartFrame; diff --git a/verilog/hub75e.sv b/verilog/hub75e.sv index 6c79d31..33c3244 100644 --- a/verilog/hub75e.sv +++ b/verilog/hub75e.sv @@ -9,8 +9,8 @@ module hub75e ( output reg done = 0, // bram interface (using clk) - output reg [10:0] pixbuf_addr, - input [8:0] pixbuf_data + output [10:0] pixbuf_addr, + input [ 8:0] pixbuf_data ); parameter integer ROW_DEPTH = 128, BIT_DEPTH = 8; @@ -47,9 +47,12 @@ module hub75e ( // short! wire should_clock, should_expose; - assign should_clock = counter < ROW_DEPTH * 2; + assign should_clock = (counter < ROW_DEPTH * 2 + 1); // the plus 1 is for the falling edge! assign should_expose = (counter < (16 << bcm_shift + 1)) && (bcm_shift != 7); + reg [7:0] pixnum; + assign pixbuf_addr = {bcm_shift, pixnum}; + always_ff @(posedge clk) begin counter <= counter + 1; case (state) @@ -57,7 +60,7 @@ module hub75e ( bcm_shift <= 7; counter <= 0; done <= 0; - pixbuf_addr <= 0; + pixnum <= ROW_DEPTH - 1; // wait for the signal to write out our lines. if (write_trig) begin state <= StateWriteRow; @@ -70,20 +73,12 @@ module hub75e ( display_clk <= counter[0]; if (~counter[0]) begin // the data from the previous cycle is now ready. - panel_rgb0 <= { - (pixbuf_data[bcm_shift]), - (pixbuf_data[bcm_shift + 8]), - (pixbuf_data[bcm_shift + 16]) - }; - panel_rgb1 <= { - (pixbuf_data[bcm_shift]), - (pixbuf_data[bcm_shift + 8]), - (pixbuf_data[bcm_shift + 16]) - }; + panel_rgb0 <= pixbuf_data[2:0]; + panel_rgb1 <= pixbuf_data[5:3]; // write it out! end else begin // update the bram address so it's ready at the next clock cycle. - pixbuf_addr <= pixbuf_addr + 1; + pixnum <= pixnum - 1; end end if (should_expose) begin @@ -95,7 +90,9 @@ module hub75e ( // the previous line, go to the latchout stage. if (~should_clock && ~should_expose) begin counter <= 0; + pixnum <= 0; state <= StateLatchout; + display_clk <= 0; end end @@ -103,9 +100,10 @@ module hub75e ( // raise latch high; compute next bcm. latch <= 1; out_enable <= 1; - pixbuf_addr <= 0; + pixnum <= ROW_DEPTH - 1; counter <= counter + 1; if (counter > 3) begin + counter <= 0; if (bcm_shift == 0) begin // we've reached the lsb of this data, go to the next one! state <= StateFinishExpose; @@ -130,7 +128,7 @@ module hub75e ( end end default: begin - state <= StateInit; + state <= StateInit; end endcase end diff --git a/verilog/lineram.v b/verilog/lineram.v index d03d4f1..022b959 100644 --- a/verilog/lineram.v +++ b/verilog/lineram.v @@ -11,73 +11,74 @@ 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]; - + // `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:0] ram[2**ADDR_WIDTH]; +`ifndef YOSYS initial begin for (int i = 0; i < 2 ** ADDR_WIDTH; i = i + 1) begin ram[i] = 0; end end +`endif always @(posedge write_clk) begin if (write_en) ram[addr_w] <= din; @@ -85,5 +86,5 @@ module lineram #( always @(posedge read_clk) begin dout <= ram[addr_r]; end -// `endif + // `endif endmodule diff --git a/verilog/pixgen.sv b/verilog/pixgen.sv index b79a0bb..8509dc1 100644 --- a/verilog/pixgen.sv +++ b/verilog/pixgen.sv @@ -16,7 +16,7 @@ module pixgen #( always @(posedge clk) begin if (start) begin done <= 1; - rgb <= { x[8:0], y[8:0] }; + rgb <= { 8'b0, x[7:0], y[7:0] }; end else done <= 0; end diff --git a/verilog/tb/coordinator_tb.sv b/verilog/tb/coordinator_tb.sv index 17fbc23..3fb59c7 100644 --- a/verilog/tb/coordinator_tb.sv +++ b/verilog/tb/coordinator_tb.sv @@ -7,7 +7,7 @@ coordinator dut(.clk(clk)); initial begin $dumpfile("coordinator.vcd"); $dumpvars(0, coordinator_tb); - repeat (10000) @(posedge clk); + repeat (100000) @(posedge clk); $finish; end endmodule