-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVGA_Controller.v
More file actions
137 lines (122 loc) · 3.1 KB
/
VGA_Controller.v
File metadata and controls
137 lines (122 loc) · 3.1 KB
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
module VGA_Controller(
input pclk,
input reset,
output hsync,
output vsync,
output valid,
// character display related
input [11:0] base_addr,
input [7:0] base_addr_y,
output [9:0] h_addr,
output [9:0] v_addr,
output [7:0] chr_addr_x,
output [3:0] cur_chr_x,
output [7:0] chr_addr_y,
output [3:0] cur_chr_y,
output [11:0] chr_addr,
output chr_disp_valid
);
parameter h_frontporch = 96;
parameter h_active = 144;
parameter h_backporch = 784;
parameter h_total = 800;
parameter v_frontporch = 2;
parameter v_active = 35;
parameter v_backporch = 515;
parameter v_total = 525;
parameter chr_width = 9;
parameter chr_height = 16;
parameter chr_cols = 70;
parameter chr_rows = 30;
parameter chr_count = chr_cols * chr_rows;
reg [9:0] x_cnt;
reg [9:0] y_cnt;
reg [3:0] _cur_chr_x, _cur_chr_y;
reg [7:0] _chr_addr_x, _chr_addr_y;
reg [11:0] _chr_addr;
reg wait_nl;
wire h_valid;
wire v_valid;
initial begin
x_cnt <= 10'd0;
y_cnt <= 10'd0;
_cur_chr_x <= 10'd0;
_cur_chr_y <= 10'd0;
_chr_addr <= 12'd0;
wait_nl <= 1'b0;
end
always @(posedge pclk) begin
if (!v_valid) begin
// reset everything
_cur_chr_x <= 0;
_cur_chr_y <= 0;
_chr_addr_x <= 0;
_chr_addr_y <= base_addr_y;
_chr_addr <= base_addr;
wait_nl <= 0;
end else begin
if (h_valid) begin
if (_chr_addr_x <= 68 || (_chr_addr_x == 69 && _cur_chr_x <= 8)) begin
if (_cur_chr_x >= chr_width - 1) begin
_cur_chr_x <= 0;
// next character
_chr_addr_x <= _chr_addr_x + 10'd1;
_chr_addr <= _chr_addr + 12'd1;
end else begin
_cur_chr_x <= _cur_chr_x + 4'd1;
end
wait_nl <= 1;
end
end else if (wait_nl) begin
// new line; increase y
wait_nl <= 0;
_cur_chr_x <= 0;
_chr_addr_x <= 0;
if (_cur_chr_y >= chr_height - 1) begin
_cur_chr_y <= 0;
if (_chr_addr_y == chr_rows - 1)
_chr_addr_y <= 0;
else
_chr_addr_y <= _chr_addr_y + 8'd1;
if (_chr_addr >= chr_rows * chr_cols)
_chr_addr <= _chr_addr - chr_rows * chr_cols;
end else begin
_cur_chr_y <= _cur_chr_y + 10'd1;
_chr_addr <= _chr_addr - chr_cols;
end
end
end
end
always @(posedge pclk) begin
if (reset == 1'b1) begin
x_cnt <= 1;
end else begin
if (x_cnt == h_total) begin
x_cnt <= 1;
end else begin
x_cnt <= x_cnt + 10'd1;
end
end
if (reset == 1'b1)
y_cnt <= 1;
else begin
if (y_cnt == v_total & x_cnt == h_total)
y_cnt <= 1;
else if (x_cnt == h_total)
y_cnt <= y_cnt + 10'd1;
end
end
assign hsync = (x_cnt > h_frontporch);
assign vsync = (y_cnt > v_frontporch);
assign h_valid = (x_cnt > h_active) & (x_cnt <= h_backporch);
assign v_valid = (y_cnt > v_active) & (y_cnt <= v_backporch);
assign valid = h_valid & v_valid;
assign h_addr = h_valid ? (x_cnt - 10'd145) : {10{1'b0}};
assign v_addr = v_valid ? (y_cnt - 10'd36 ) : {10{1'b0}};
assign cur_chr_x = _cur_chr_x;
assign cur_chr_y = _cur_chr_y;
assign chr_addr_x = _chr_addr_x;
assign chr_addr_y = _chr_addr_y;
assign chr_addr = _chr_addr;
assign chr_disp_valid = (x_cnt > h_active) & (x_cnt <= h_backporch - 10);
endmodule