-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathVGA.v
99 lines (81 loc) · 3.29 KB
/
VGA.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
`timescale 1ns / 1ps
module vga_sync(
input wire clk, reset,
output wire hsync, vsync, video_on, p_tick,
output wire [9:0] x, y
);
// constant declarations for VGA sync parameters
localparam H_DISPLAY = 640; // horizontal display area
localparam H_L_BORDER = 48; // horizontal left border
localparam H_R_BORDER = 16; // horizontal right border
localparam H_RETRACE = 96; // horizontal retrace
localparam H_MAX = H_DISPLAY + H_L_BORDER + H_R_BORDER + H_RETRACE - 1;
localparam START_H_RETRACE = H_DISPLAY + H_R_BORDER;
localparam END_H_RETRACE = H_DISPLAY + H_R_BORDER + H_RETRACE - 1;
localparam V_DISPLAY = 480; // vertical display area
localparam V_T_BORDER = 10; // vertical top border
localparam V_B_BORDER = 33; // vertical bottom border
localparam V_RETRACE = 2; // vertical retrace
localparam V_MAX = V_DISPLAY + V_T_BORDER + V_B_BORDER + V_RETRACE - 1;
localparam START_V_RETRACE = V_DISPLAY + V_B_BORDER;
localparam END_V_RETRACE = V_DISPLAY + V_B_BORDER + V_RETRACE - 1;
// mod-2 counter to generate 25 MHz pixel tick
reg pixel_reg;
wire pixel_next, pixel_tick;
always @(posedge clk or posedge reset)
begin
if(reset)
pixel_reg <= 0;
else
pixel_reg <= pixel_next;
end
assign pixel_next = ~pixel_reg; // next state is complement of current
assign pixel_tick = (pixel_reg == 0); // assert tick half of the time
// registers to keep track of current pixel location
reg [9:0] h_count_reg, h_count_next, v_count_reg, v_count_next;
// register to keep track of vsync and hsync signal states
reg vsync_reg, hsync_reg;
wire vsync_next, hsync_next;
// infer registers
always @(posedge clk, posedge reset)
if(reset)
begin
v_count_reg <= 0;
h_count_reg <= 0;
vsync_reg <= 0;
hsync_reg <= 0;
end
else
begin
v_count_reg <= v_count_next;
h_count_reg <= h_count_next;
vsync_reg <= vsync_next;
hsync_reg <= hsync_next;
end
// next-state logic of horizontal vertical sync counters
always @*
begin
h_count_next = pixel_tick ?
h_count_reg == H_MAX ? 0 : h_count_reg + 1
: h_count_reg;
v_count_next = pixel_tick && h_count_reg == H_MAX ?
(v_count_reg == V_MAX ? 0 : v_count_reg + 1)
: v_count_reg;
end
// hsync and vsync are active low signals
// hsync signal asserted during horizontal retrace
assign hsync_next = h_count_reg >= START_H_RETRACE
&& h_count_reg <= END_H_RETRACE;
// vsync signal asserted during vertical retrace
assign vsync_next = v_count_reg >= START_V_RETRACE
&& v_count_reg <= END_V_RETRACE;
// video only on when pixels are in both horizontal and vertical display region
assign video_on = (h_count_reg < H_DISPLAY)
&& (v_count_reg < V_DISPLAY);
// output signals
assign hsync = hsync_reg;
assign vsync = vsync_reg;
assign x = h_count_reg;
assign y = v_count_reg;
assign p_tick = pixel_tick;
endmodule