module VGABox ( // Clock e Reset input wire clk, // 100 MHz clock input wire reset, input wire pixel_clk, // Avalon Memory-Mapped Slave Interface input wire [3:0] avs_address, input wire avs_read, input wire avs_write, input wire [31:0] avs_writedata, output reg [31:0] avs_readdata, // VGA Output Signals output wire [7:0] VGA_R, output wire [7:0] VGA_G, output wire [7:0] VGA_B, output wire VGA_HS, output wire VGA_VS, output wire VGA_BLANK_N, output wire VGA_SYNC_N, output wire VGA_CLK ); // ============================================================================ // Timing Parameters per 800x600 @ 60Hz (Pixel Clock = 40 MHz) // ============================================================================ localparam H_DISPLAY = 800; localparam H_FRONT = 40; localparam H_SYNC = 128; localparam H_BACK = 88; localparam H_TOTAL = H_DISPLAY + H_FRONT + H_SYNC + H_BACK; // 1056 localparam V_DISPLAY = 600; localparam V_FRONT = 1; localparam V_SYNC = 4; localparam V_BACK = 23; localparam V_TOTAL = V_DISPLAY + V_FRONT + V_SYNC + V_BACK; // 628 assign VGA_CLK = pixel_clk; // ============================================================================ // Registri Configurabili via Avalon MM // ============================================================================ // Address Map: // 0x0: X position (10 bit) // 0x1: Y position (10 bit) // 0x2: Width (10 bit) // 0x3: Height (10 bit) // 0x4: Color (RGB 24-bit: [23:16]=R, [15:8]=G, [7:0]=B) reg [9:0] rect_x; // Posizione X del rettangolo reg [9:0] rect_y; // Posizione Y del rettangolo reg [9:0] rect_width; // Larghezza del rettangolo reg [9:0] rect_height; // Altezza del rettangolo reg [7:0] rect_r; // Componente Rossa reg [7:0] rect_g; // Componente Verde reg [7:0] rect_b; // Componente Blu // Avalon MM Write always @(posedge clk or posedge reset) begin if (reset) begin rect_x <= 10'd200; rect_y <= 10'd150; rect_width <= 10'd400; rect_height <= 10'd300; rect_r <= 8'hFF; rect_g <= 8'h00; rect_b <= 8'h00; end else if (avs_write) begin case (avs_address) 4'h0: rect_x <= avs_writedata[9:0]; 4'h1: rect_y <= avs_writedata[9:0]; 4'h2: rect_width <= avs_writedata[9:0]; 4'h3: rect_height <= avs_writedata[9:0]; 4'h4: begin rect_b <= avs_writedata[7:0]; rect_g <= avs_writedata[15:8]; rect_r <= avs_writedata[23:16]; end endcase end end // Avalon MM Read always @(*) begin case (avs_address) 4'h0: avs_readdata = {22'd0, rect_x}; 4'h1: avs_readdata = {22'd0, rect_y}; 4'h2: avs_readdata = {22'd0, rect_width}; 4'h3: avs_readdata = {22'd0, rect_height}; 4'h4: avs_readdata = {8'd0, rect_r, rect_g, rect_b}; default: avs_readdata = 32'd0; endcase end // ============================================================================ // Contatori VGA // ============================================================================ reg [10:0] h_count; reg [9:0] v_count; always @(posedge pixel_clk or posedge reset) begin if (reset) begin h_count <= 11'd0; v_count <= 10'd0; end else begin if (h_count == H_TOTAL - 1) begin h_count <= 11'd0; if (v_count == V_TOTAL - 1) v_count <= 10'd0; else v_count <= v_count + 1'b1; end else begin h_count <= h_count + 1'b1; end end end // ============================================================================ // Generazione Segnali di Sincronizzazione // ============================================================================ wire h_sync_region = (h_count >= (H_DISPLAY + H_FRONT)) && (h_count < (H_DISPLAY + H_FRONT + H_SYNC)); wire v_sync_region = (v_count >= (V_DISPLAY + V_FRONT)) && (v_count < (V_DISPLAY + V_FRONT + V_SYNC)); assign VGA_HS = ~h_sync_region; // Negative polarity assign VGA_VS = ~v_sync_region; // Negative polarity // ============================================================================ // Area Visibile // ============================================================================ wire display_area = (h_count < H_DISPLAY) && (v_count < V_DISPLAY); assign VGA_BLANK_N = display_area; assign VGA_SYNC_N = 1'b0; // Non usato nel VGA moderno // ============================================================================ // Coordinate Pixel Correnti // ============================================================================ wire [9:0] pixel_x = h_count[9:0]; wire [9:0] pixel_y = v_count[9:0]; // ============================================================================ // Logica di Rendering del Rettangolo // ============================================================================ wire in_rect_x = (pixel_x >= rect_x) && (pixel_x < (rect_x + rect_width)); wire in_rect_y = (pixel_y >= rect_y) && (pixel_y < (rect_y + rect_height)); wire draw_rect = in_rect_x && in_rect_y; // ============================================================================ // Output RGB // ============================================================================ reg [7:0] vga_r_reg, vga_g_reg, vga_b_reg; always @(posedge pixel_clk) begin if (display_area && draw_rect) begin vga_r_reg <= rect_r; vga_g_reg <= rect_g; vga_b_reg <= rect_b; end else begin vga_r_reg <= 8'h00; // Sfondo nero vga_g_reg <= 8'h00; vga_b_reg <= 8'h00; end end assign VGA_R = vga_r_reg; assign VGA_G = vga_g_reg; assign VGA_B = vga_b_reg; endmodule