From 9a4dfea4f0c7a0a1ba2b62c6ce89682bbcfd9764 Mon Sep 17 00:00:00 2001 From: saji <saji@saji.dev> Date: Tue, 30 Apr 2024 23:48:10 -0500 Subject: [PATCH] wip: basic pixel generator + coordinator module coordinator is a high level hub75 controller. It drives multiple panels by generating the x/y coordinates that would be displayed on each, then converting those into the BRAM format to be written quickly. --- Makefile | 10 ++- verilog/bitslicer.sv | 34 +++++---- verilog/coordinator.sv | 144 +++++++++++++++++++++++++++++++++++ verilog/hub75e.sv | 3 - verilog/pixgen.sv | 24 ++++++ verilog/tb/bitslicer_tb.sv | 43 +++++++++++ verilog/tb/coordinator_tb.sv | 14 ++++ 7 files changed, 252 insertions(+), 20 deletions(-) create mode 100644 verilog/coordinator.sv create mode 100644 verilog/pixgen.sv create mode 100644 verilog/tb/coordinator_tb.sv diff --git a/Makefile b/Makefile index 61e143d..f1ae0e4 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,11 @@ - - - .PHONY all clean test +VERILOG_SOURCES := $(join $(wildcard verilog/*.v), $(wildcard verilog/*.sv)) +TESTBENCH_SOURCES := $(wildcard verilog/tb/*.sv) +ICARUS_ARGS := "-g2012" +%.vcd: %.vvp + vvp $^ - +%.vvp: %.sv diff --git a/verilog/bitslicer.sv b/verilog/bitslicer.sv index e0342fd..4038ad6 100644 --- a/verilog/bitslicer.sv +++ b/verilog/bitslicer.sv @@ -1,7 +1,7 @@ module bitslicer ( input clk, input [23:0] rgb[2], - input [7:0] pixnum, // x-value of the pixels we are being fed. + input [8: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, @@ -9,8 +9,16 @@ module bitslicer ( output reg done ); - reg [3:0] bitplane_bit = 0; + reg [2:0] bitplane_bit = 0; assign bitplane_addr = (pixnum << 3) + bitplane_bit; + 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] + }; reg [3:0] state = StateInit; localparam integer StateInit = 0; @@ -26,27 +34,27 @@ module bitslicer ( bitplane_wren <= 0; if (start_write) begin state <= StateWriteout; + bitplane_wren <= 1; end end StateWriteout: begin - 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] - }; - bitplane_wren <= 1; + // 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] + // }; bitplane_bit <= bitplane_bit + 1; if (bitplane_bit == 7) begin state <= StateDone; + bitplane_wren <= 0; end end StateDone: begin - bitplane_wren <= 0; - done <= 1; // strobe + done <= 1; // strobe state <= StateInit; end default: begin diff --git a/verilog/coordinator.sv b/verilog/coordinator.sv new file mode 100644 index 0000000..8472e80 --- /dev/null +++ b/verilog/coordinator.sv @@ -0,0 +1,144 @@ +module coordinator ( + input clk +); + + // pixgen signals + reg pixgen_start; + reg [8:0] x; + reg [8:0] y; + wire [23:0] pix_rgb[2]; + wire [1:0] pix_done; + + pixgen pix0 ( + .clk(clk), + .start(pixgen_start), + .x(x), + .y(y), + .rgb(pix_rgb[0]), + .done(pix_done[0]) + ); + pixgen pix1 ( + .clk(clk), + .start(pixgen_start), + .x(x), + .y(y + 9'd32), + .rgb(pix_rgb[1]), + .done(pix_done[1]) + ); + + + // slicer signals + wire bitslice_start; + wire [5:0] bitplane_data; + wire [10:0] bitplane_addr; + wire bitplane_wren; + wire bitplane_done; + + bitslicer bslice ( + .clk(clk), + .rgb(pix_rgb), + .pixnum(x), + .start_write(bitslice_start), + .bitplane_data(bitplane_data), + .bitplane_addr(bitplane_addr), + .bitplane_wren(bitplane_wren), + .done(bitplane_done) + ); + + // bram signals + + wire [8:0] din; + wire [10:0] addr_w; + wire [8:0] dout; + wire [10:0] addr_r; + wire read_clk; + wire write_clk; + + lineram bram ( + .write_clk(clk), + .read_clk(clk), + .addr_w(bitplane_addr), + .din({3'b000, bitplane_data}), + .write_en(bitplane_wren), + .addr_r(addr_r), + .dout(dout) + ); + + // 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), + .write_trig(write_line), + .panel_rgb0(panel_rgb0), + .panel_rgb1(panel_rgb1), + .display_clk(display_clk), + .out_enable(out_enable), + .latch(latch), + .done(line_done), + .pixbuf_addr(addr_r), + .pixbuf_data(dout) + ); + + + reg [4:0] state = 0; + + localparam unsigned StateInit = 0; + localparam unsigned StateStartFrame = 1; + localparam unsigned StateGenerateLine = 2; + localparam unsigned StateShowLine = 3; + localparam unsigned StateIncrementLine = 4; + // we're gonna try this + assign bitslice_start = pix_done[0] & pix_done[1]; // bitslice start when both pix done. + + always @(posedge clk) begin + case (state) + StateInit: begin + x <= 0; + y <= 0; + state <= StateStartFrame; + end + StateStartFrame: begin + pixgen_start <= 1; + state <= StateGenerateLine; + end + StateGenerateLine: begin + pixgen_start <= 0; + if (bitplane_done) begin + if (x < 127) begin + x <= x + 1; + pixgen_start <= 1; + // generate next + end else begin + write_line <= 1; + state <= StateShowLine; + end + end + end + StateShowLine: begin + write_line <= 0; + if (line_done) begin + state <= StateIncrementLine; + end + end + StateIncrementLine: begin + x <= 0; + y <= y + 1; + if (y == 31) begin + state <= StateInit; + end else begin + state <= StateStartFrame; + end + end + default: state <= StateInit; + endcase + end + + +endmodule diff --git a/verilog/hub75e.sv b/verilog/hub75e.sv index f72089d..6c79d31 100644 --- a/verilog/hub75e.sv +++ b/verilog/hub75e.sv @@ -1,8 +1,6 @@ module hub75e ( input clk, input write_trig, - 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, @@ -30,7 +28,6 @@ module hub75e ( reg [7:0] state = StateInit; // our state - assign addr = 5'b10101; // initial begin // state <= StateInit; diff --git a/verilog/pixgen.sv b/verilog/pixgen.sv new file mode 100644 index 0000000..b79a0bb --- /dev/null +++ b/verilog/pixgen.sv @@ -0,0 +1,24 @@ +module pixgen #( + parameter integer X_DEPTH = 9, + parameter integer Y_DEPTH = 9, + parameter integer RGB_DEPTH = 24 +) ( + input clk, + input start, + input [X_DEPTH-1:0] x, + input [Y_DEPTH-1:0] y, + output reg [RGB_DEPTH-1:0] rgb, + output reg done +); + +// given x and y inputs, create an rgb output + +always @(posedge clk) begin + if (start) begin + done <= 1; + rgb <= { x[8:0], y[8:0] }; + end + else done <= 0; +end + +endmodule diff --git a/verilog/tb/bitslicer_tb.sv b/verilog/tb/bitslicer_tb.sv index e69de29..5df318f 100644 --- a/verilog/tb/bitslicer_tb.sv +++ b/verilog/tb/bitslicer_tb.sv @@ -0,0 +1,43 @@ +`timescale 1ns / 100ps // 1 ns time unit, 100 ps resolution + +module bitslicer_tb; + reg clk = 0; + + reg [23:0] rgb_in [2]; + reg start_write = 0; + reg [7:0] pixnum = 0; + wire [5:0] bitplane_data; + wire [10:0] bitplane_addr; + wire bitplane_wren; + wire done; + + bitslicer dut( + .clk(clk), + .rgb(rgb_in), + .pixnum(pixnum), + .start_write(start_write), + .bitplane_data(bitplane_data), + .bitplane_addr(bitplane_addr), + .done(done) + ); + + always #5 clk = !clk; + initial begin + $dumpfile("bitslicer_tb.vcd"); + $dumpvars(0, bitslicer_tb); + rgb_in[0] <= 24'hEE8833; + rgb_in[1] <= 24'hDD7722; + pixnum <= 3; + @(posedge clk); + start_write <= 1; + @(posedge clk); + start_write <= 0; + @(done); + repeat (10) @(posedge clk); + $finish(); + end + initial begin + repeat (100000) @(posedge clk); + $finish(); + end +endmodule diff --git a/verilog/tb/coordinator_tb.sv b/verilog/tb/coordinator_tb.sv new file mode 100644 index 0000000..17fbc23 --- /dev/null +++ b/verilog/tb/coordinator_tb.sv @@ -0,0 +1,14 @@ +`timescale 1ns / 100ps // 1 ns time unit, 100 ps resolution + +module coordinator_tb(); +reg clk = 0; +coordinator dut(.clk(clk)); + always #8 clk = !clk; + initial begin + $dumpfile("coordinator.vcd"); + $dumpvars(0, coordinator_tb); + repeat (10000) @(posedge clk); + $finish; + end +endmodule +