1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
`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
|