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