go-board-code/vga_pattern_generator.v

190 lines
4.1 KiB
Verilog

module VGA_Pattern_Generator(
input i_Clk,
input [3:0] i_Pattern,
input i_HSync,
input i_VSync,
output reg o_HSync = 0,
output reg o_VSync = 0,
output reg [VIDEO_WIDTH-1:0] o_Red,
output reg [VIDEO_WIDTH-1:0] o_Green,
output reg [VIDEO_WIDTH-1:0] o_Blue
);
// Go Board only supports 3 bits per channel. That's even less than the
// Amiga!
parameter VIDEO_WIDTH = 3;
parameter TOTAL_COLUMNS = 800;
parameter TOTAL_ROWS = 525;
parameter ACTIVE_COLUMNS = 640;
parameter ACTIVE_ROWS = 480;
localparam COLOR_BAR_WIDTH = ACTIVE_COLUMNS / 8;
wire w_HSync, w_VSync;
wire [VIDEO_WIDTH-1:0] w_Red[0:15];
wire [VIDEO_WIDTH-1:0] w_Green[0:15];
wire [VIDEO_WIDTH-1:0] w_Blue[0:15];
wire [$clog2(TOTAL_COLUMNS)-1:0] w_X;
wire [$clog2(TOTAL_ROWS)-1:0] w_Y;
VGA_Current_Beam_Position #(
.TOTAL_COLUMNS(TOTAL_COLUMNS),
.TOTAL_ROWS(TOTAL_ROWS)
) CurrentPosition (
.i_Clk(i_Clk),
.i_HSync(i_HSync),
.i_VSync(i_VSync),
.o_HSync(w_HSync),
.o_VSync(w_VSync),
.o_X(w_X),
.o_Y(w_Y)
);
// all these pattern operations take one clock tick
// so delay sync signals by that much
always @(posedge i_Clk) begin
o_HSync <= w_HSync;
o_VSync <= w_VSync;
end
// none more black
assign w_Red[0] = 0;
assign w_Green[0] = 0;
assign w_Blue[0] = 0;
// red
assign w_Red[1] = (
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
{VIDEO_WIDTH{1'b1}} :
0
);
assign w_Green[1] = 0;
assign w_Blue[1] = 0;
// green
assign w_Red[2] = 0;
assign w_Green[2] = (
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
{VIDEO_WIDTH{1'b1}} :
0
);
assign w_Blue[2] = 0;
// blue
assign w_Red[3] = 0;
assign w_Green[3] = 0;
assign w_Blue[3] = (
(w_X < ACTIVE_COLUMNS && w_Y < ACTIVE_ROWS) ?
{VIDEO_WIDTH{1'b1}} :
0
);
// checkerboard
// cell size is 32 pixels
assign w_Red[4] = (w_X[5] ^ w_Y[5]) ? {VIDEO_WIDTH{1'b1}} : 0;
assign w_Green[4] = w_Red[4];
assign w_Blue[4] = w_Red[4];
wire [2:0] w_colorBarSelect;
// color bars
// yes this is the hardware way to do this b/c multi/div
assign w_colorBarSelect =
w_X < COLOR_BAR_WIDTH ? 0 :
w_X < COLOR_BAR_WIDTH * 2 ? 1 :
w_X < COLOR_BAR_WIDTH * 3 ? 2 :
w_X < COLOR_BAR_WIDTH * 4 ? 3 :
w_X < COLOR_BAR_WIDTH * 5 ? 4 :
w_X < COLOR_BAR_WIDTH * 6 ? 5 :
w_X < COLOR_BAR_WIDTH * 7 ? 6 :7;
assign w_Red[5] = (
w_colorBarSelect == 4 ||
w_colorBarSelect == 5 ||
w_colorBarSelect == 6 ||
w_colorBarSelect == 7
) ? {VIDEO_WIDTH{1'b1}} : 0;
assign w_Green[5] = (
w_colorBarSelect == 2 ||
w_colorBarSelect == 3 ||
w_colorBarSelect == 6 ||
w_colorBarSelect == 7
) ? {VIDEO_WIDTH{1'b1}} : 0;
assign w_Blue[5] = (
w_colorBarSelect == 1 ||
w_colorBarSelect == 3 ||
w_colorBarSelect == 5 ||
w_colorBarSelect == 7
) ? {VIDEO_WIDTH{1'b1}} : 0;
// border
localparam BORDER_WIDTH = 2;
assign w_Red[6] = (
w_X < BORDER_WIDTH || w_X >= ACTIVE_COLUMNS - BORDER_WIDTH ||
w_Y < BORDER_WIDTH || w_Y >= ACTIVE_ROWS - BORDER_WIDTH
) ? {VIDEO_WIDTH{1'b1}} : 0;
assign w_Green[6] = 0;
assign w_Blue[6] = 0;
always @(posedge i_Clk) begin
case (i_Pattern)
0:
begin
o_Red <= w_Red[0];
o_Green <= w_Green[0];
o_Blue <= w_Blue[0];
end
1:
begin
o_Red <= w_Red[1];
o_Green <= w_Green[1];
o_Blue <= w_Blue[1];
end
2:
begin
o_Red <= w_Red[2];
o_Green <= w_Green[2];
o_Blue <= w_Blue[2];
end
3:
begin
o_Red <= w_Red[3];
o_Green <= w_Green[3];
o_Blue <= w_Blue[3];
end
4:
begin
o_Red <= w_Red[4];
o_Green <= w_Green[4];
o_Blue <= w_Blue[4];
end
5:
begin
o_Red <= w_Red[5];
o_Green <= w_Green[5];
o_Blue <= w_Blue[5];
end
6:
begin
o_Red <= w_Red[6];
o_Green <= w_Green[6];
o_Blue <= w_Blue[6];
end
default:
begin
o_Red <= w_Red[0];
o_Green <= w_Green[0];
o_Blue <= w_Blue[0];
end
endcase
end
endmodule