`default_nettype none `timescale 1ns/1ns `include "messages.vh" `ifndef SIMULATION `error_SIMULATION_not_defined ; /* Cause syntax error */ `endif module VGA_640_480_60Hz( input wire horizontal_sync, input wire vertical_sync, input wire [2:0] red, input wire [2:0] green, input wire [2:0] blue, output reg [9:0] image_writes ); initial image_writes <= 0; parameter FRONT_PORCH = 0; parameter SYNC_PULSE = 1; parameter BACK_PORCH = 2; parameter ACTIVE_VIDEO = 3; parameter UNKNOWN_STATE = 4; integer h_state; integer v_state; initial begin h_state <= UNKNOWN_STATE; v_state <= UNKNOWN_STATE; end parameter H_SYNC_POLARITY = 1'b0; parameter H_FRONT_PORCH_LENGTH = 16; parameter H_SYNC_PULSE_LENGTH = 96; parameter H_BACK_PORCH_LENGTH = 48; parameter H_ACTIVE_VIDEO_LENGTH = 640; parameter V_SYNC_POLARITY = 1'b1; parameter V_FRONT_PORCH_LENGTH = 10; parameter V_SYNC_PULSE_LENGTH = 2; parameter V_BACK_PORCH_LENGTH = 33; parameter V_ACTIVE_VIDEO_LENGTH = 480; reg [8:0] picture [V_ACTIVE_VIDEO_LENGTH - 1 : 0] [H_ACTIVE_VIDEO_LENGTH - 1 : 0]; integer h_counter, v_counter; reg error; wire unexpected_h_sync_pulse; wire missing_h_sync_pulse; assign unexpected_h_sync_pulse = horizontal_sync == H_SYNC_POLARITY && h_state != SYNC_PULSE; assign missing_h_sync_pulse = horizontal_sync != H_SYNC_POLARITY && h_state == SYNC_PULSE; wire unexpected_v_sync_pulse; wire missing_v_sync_pulse; assign unexpected_v_sync_pulse = vertical_sync == V_SYNC_POLARITY && v_state != SYNC_PULSE; assign missing_v_sync_pulse = vertical_sync != V_SYNC_POLARITY && v_state == SYNC_PULSE; wire new_line; assign new_line = h_state == BACK_PORCH && h_counter + 1 == H_BACK_PORCH_LENGTH; wire new_screen; assign new_screen = v_state == BACK_PORCH && v_counter + 1 == V_BACK_PORCH_LENGTH && new_line; always #40 begin /* First, horizontal stuff */ if (unexpected_h_sync_pulse) begin h_state <= SYNC_PULSE; h_counter <= 1; if (h_state != UNKNOWN_STATE) begin `MSG(({"VGA: error: unexpected horizontal sync pulse signal ", "(tick %0d; state %0d)"}, h_counter, h_state)); end end else if (missing_h_sync_pulse) begin h_state <= BACK_PORCH; h_counter <= 1; `MSG(({"VGA: error: missing expected horizontal sync pulse signal ", "(tick %0d of sync pulse)"}, h_counter)); end else begin case (h_state) FRONT_PORCH : begin if (h_counter + 1 != H_FRONT_PORCH_LENGTH) begin h_counter <= h_counter + 1; end else begin h_state <= SYNC_PULSE; h_counter <= 0; end end SYNC_PULSE : begin if (h_counter + 1 != H_SYNC_PULSE_LENGTH) begin h_counter <= h_counter + 1; end else begin h_state <= BACK_PORCH; h_counter <= 0; end end BACK_PORCH : begin if (h_counter + 1 != H_BACK_PORCH_LENGTH) begin h_counter <= h_counter + 1; end else begin h_state <= ACTIVE_VIDEO; h_counter <= 0; end end ACTIVE_VIDEO : begin if (v_state == ACTIVE_VIDEO) begin picture[v_counter][h_counter] <= {red, green, blue}; end if (h_counter + 1 != H_ACTIVE_VIDEO_LENGTH) begin h_counter <= h_counter + 1; end else begin h_state <= FRONT_PORCH; h_counter <= 0; end end // case: ACTIVE_VIDEO endcase // case (h_state) end // else: !if(missing_h_sync_pulse) /* Vertical stuff is similar to horizontal */ if (h_state == ACTIVE_VIDEO) begin if (unexpected_v_sync_pulse) begin v_state <= SYNC_PULSE; v_counter <= 0; if (v_state != UNKNOWN_STATE) begin `MSG(({"VGA: error: unexpected vertical sync pulse signal ", "(line %0d; state %0d)"}, v_counter, v_state)); end end else if (missing_v_sync_pulse) begin v_state <= BACK_PORCH; v_counter <= 0; `MSG(({"VGA: error: missing expected vertical sync pulse signal ", "(line %0d of sync pulse)"}, v_counter)); end end // if (h_state == ACTIVE_VIDEO) if (new_line) begin case (v_state) FRONT_PORCH : begin if (v_counter + 1 != V_FRONT_PORCH_LENGTH) begin v_counter <= v_counter + 1; end else begin v_state <= SYNC_PULSE; v_counter <= 0; end end SYNC_PULSE : begin if (v_counter + 1 != V_SYNC_PULSE_LENGTH) begin v_counter <= v_counter + 1; end else begin v_state <= BACK_PORCH; v_counter <= 0; end end BACK_PORCH : begin if (v_counter + 1 != V_BACK_PORCH_LENGTH) begin v_counter <= v_counter + 1; end else begin v_state <= ACTIVE_VIDEO; v_counter <= 0; end end ACTIVE_VIDEO : begin if (v_counter + 1 != V_ACTIVE_VIDEO_LENGTH) begin v_counter <= v_counter + 1; end else begin v_state <= FRONT_PORCH; v_counter <= 0; if (!error) begin $writememb("VGAdump.mem", picture); `DBG(("VGA: written VGAdump.mem")); image_writes <= image_writes + 1; end end // else: !if(v_counter + 1 != V_ACTIVE_VIDEO_LENGTH) end // case: ACTIVE_VIDEO endcase // case (v_state) end // if (new_line) if (unexpected_h_sync_pulse || unexpected_h_sync_pulse || ((unexpected_v_sync_pulse || missing_v_sync_pulse) && new_line)) error <= 1; else if (new_screen) error <= 0; end // always #40 endmodule // VGA_640_480_60Hz