-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvsync.v
167 lines (159 loc) · 3.95 KB
/
vsync.v
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
/*
Designer: Lazaros Athanasiadis
Designed in: Fall Semester 2019-20
Designed for: Digital Systems Lab, 3rd lab assignment (VGA driver)
Description: Vertical timings for the vga driver. Outputs vsync, a signal
that goes straight to the VGA, and enable, a signal that I use
to determine whether I should display pixels,
meaning the FSM is at its ACTIVE VIDEO state, or not.
*/
module vsync_generator(clk, reset, vpixel, vsync, en, frame);
input clk, reset;
output vsync, en;
output [5:0] frame;
output [6:0] vpixel;
reg vsync, en;
reg [1:0] state, next_state;
reg [5:0] frame;
reg [6:0] vpixel;
//Assuming a 20ns clock...
/*
pixel_counter: counts up to 7999 (160us elapsed) to change vpixel value
On a 640*480 display , the 15.36ms of active video time are enough
to scan each one of the 480 vertical lines one time
With my 128*96 VRAM, each line must get displayed 5 times to get displayed properly.
Thus, the pixel counter for generating the vpixel signal must count for 32us(scanlight time)*5 = 160us,
or 8000 clock (T = 20ns) cycles
*/
reg [12:0] pixel_counter;
reg [11:0] pulse_counter; //count up to 3199 (64us elapsed -- pulse width)
reg [15:0] back_counter; //count up to 46399 (928us elapsed -- back porch)
reg [19:0] active_counter; //count up to 767999 (15.36ms elapsed -- active video time)
reg [13:0] front_counter; //count up to 15999 (320us elapsed -- front porch)
parameter PULSE_WIDTH = 2'b00,
BACK_PORCH = 2'b01,
DISPLAY = 2'b10,
FRONT_PORCH = 2'b11;
//FSM: next state
always @(posedge clk or posedge reset) begin
if (reset == 1'b1) begin
state <= PULSE_WIDTH;
end
else begin
state <= next_state;
end
end
//increase counters at their respective states
always @(posedge clk or posedge reset) begin
if (reset == 1'b1) begin
pulse_counter <= 12'b0;
back_counter <= 16'b0;
active_counter <= 20'b0;
front_counter <= 14'b0;
pixel_counter <= 13'b0;
end
else begin
case (state)
PULSE_WIDTH:
begin
front_counter <= 14'd0;
pulse_counter <= pulse_counter + 12'd1;
end
BACK_PORCH:
begin
pulse_counter <= 12'd0;
back_counter <= back_counter + 16'd1;
end
DISPLAY:
begin
back_counter <= 16'd0;
active_counter <= active_counter + 20'd1;
if (pixel_counter == 13'd7999)
pixel_counter <= 13'd0;
else
pixel_counter <= pixel_counter + 13'd1;
end
FRONT_PORCH:
begin
active_counter <= 20'd0;
front_counter <= front_counter + 14'b1;
end
endcase
end
end
//calculate vpixel and frame
always @(posedge clk or posedge reset) begin
if (reset == 1'b1) begin
frame <= 6'd0;
vpixel <= 7'b0;
end
else begin
//frame
if (state == FRONT_PORCH) begin
if (front_counter == 14'd15999) begin
if (frame == 6'd59) begin
frame <= 0;
end
else begin
frame <= frame + 6'd1;
end
end
end
//vpixel
if (state == DISPLAY) begin
if (pixel_counter == 13'd7999) begin
vpixel <= vpixel + 1;
end
else begin
vpixel <= vpixel;
end
end
else begin
vpixel <= 7'b0;
end
end
end
//FSM: next state and outputs (vsync, enable)
always @(state or pulse_counter or back_counter or active_counter or front_counter or pixel_counter) begin
case (state)
PULSE_WIDTH:
begin
vsync = 1'b0;
en = 0;
if (pulse_counter == 12'd3199)
next_state = BACK_PORCH;
else
next_state = PULSE_WIDTH;
end
BACK_PORCH:
begin
vsync = 1'b1;
en = 0;
if (back_counter == 16'd46399)
next_state = DISPLAY;
else
next_state = BACK_PORCH;
end
DISPLAY:
begin
vsync = 1'b1;
en = 1;
if (active_counter == 20'd767999) begin
next_state = FRONT_PORCH;
end
else begin
next_state = DISPLAY;
end
end
FRONT_PORCH:
begin
vsync = 1'b1;
en = 0;
if (front_counter == 14'd15999)
next_state = PULSE_WIDTH;
else
next_state = FRONT_PORCH;
end
endcase
end
endmodule