From ee1f6c47e1eff920068f4bceaf604f9535a2e8a9 Mon Sep 17 00:00:00 2001 From: Wojciech Kosior Date: Tue, 1 Sep 2020 10:54:59 +0200 Subject: start anew --- models/vga_display.v | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 models/vga_display.v (limited to 'models/vga_display.v') diff --git a/models/vga_display.v b/models/vga_display.v new file mode 100644 index 0000000..bb683e2 --- /dev/null +++ b/models/vga_display.v @@ -0,0 +1,203 @@ +`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 almost entirely the same as horizontal */ + if (new_line) begin + if (unexpected_v_sync_pulse) begin + v_state <= SYNC_PULSE; + v_counter <= 1; + + 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 <= 1; + + `MSG(({"VGA: error: missing expected vertical sync pulse signal ", + "(line %0d of sync pulse)"}, v_counter)); + end else 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 // else: !if(missing_v_sync_pulse) + 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 -- cgit v1.2.3