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.
This commit is contained in:
saji 2024-04-30 23:48:10 -05:00
parent bd2fa51f2d
commit 9a4dfea4f0
7 changed files with 252 additions and 20 deletions

View file

@ -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

View file

@ -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

144
verilog/coordinator.sv Normal file
View file

@ -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

View file

@ -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;

24
verilog/pixgen.sv Normal file
View file

@ -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

View file

@ -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

View file

@ -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