forked from alanswx/Tutorials_MiSTer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vga.v
114 lines (90 loc) · 3.02 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// A simple system-on-a-chip (SoC) for the MiST
// (c) 2015 Till Harbaum
// VGA controller generating 160x100 pixles. The VGA mode ised is 640x400
// combining every 4 row and column
// http://tinyvga.com/vga-timing/640x400@70Hz
module vga (
// pixel clock
input pclk,
// VGA output
output reg hs,
output reg vs,
output [7:0] r,
output [7:0] g,
output [7:0] b,
output VGA_DE
);
// 640x400 70HZ VESA according to http://tinyvga.com/vga-timing/640x400@70Hz
parameter H = 640; // width of visible area
parameter HFP = 16; // unused time before hsync
parameter HS = 96; // width of hsync
parameter HBP = 48; // unused time after hsync
parameter V = 400; // height of visible area
parameter VFP = 12; // unused time before vsync
parameter VS = 2; // width of vsync
parameter VBP = 35; // unused time after vsync
reg[9:0] h_cnt; // horizontal pixel counter
reg[9:0] v_cnt; // vertical pixel counter
reg hblank;
reg vblank;
// both counters count from the begin of the visibla area
// horizontal pixel counter
always@(posedge pclk) begin
if(h_cnt==H+HFP+HS+HBP-1) h_cnt <= 0;
else h_cnt <= h_cnt + 1;
// generate negative hsync signal
if(h_cnt == H+HFP) hs <= 1'b0;
if(h_cnt == H+HFP+HS) hs <= 1'b1;
if(h_cnt == H+HFP+HS) hblank <= 1'b1; else hblank<=1'b0;
end
// veritical pixel counter
always@(posedge pclk) begin
// the vertical counter is processed at the begin of each hsync
if(h_cnt == H+HFP) begin
if(v_cnt==VS+VBP+V+VFP-1) v_cnt <= 0;
else v_cnt <= v_cnt + 1;
// generate positive vsync signal
if(v_cnt == V+VFP) vs <= 1'b1;
if(v_cnt == V+VFP+VS) vs <= 1'b0;
if(v_cnt == V+VFP+VS) vblank <= 1'b1; else vblank<=1'b0;
end
end
// read VRAM
reg [13:0] video_counter;
reg [7:0] pixel;
reg de;
always@(posedge pclk) begin
// The video counter is being reset at the begin of each vsync.
// Otherwise it's increased every fourth pixel in the visible area.
// At the end of the first three of four lines the counter is
// decreased by the total line length to display the same contents
// for four lines so 100 different lines are displayed on the 400
// VGA lines.
// visible area?
if((v_cnt < V) && (h_cnt < H)) begin
if(h_cnt[1:0] == 2'b11)
video_counter <= video_counter + 14'd1;
pixel <= (v_cnt[2] ^ h_cnt[2])?8'h00:8'hff; // checkboard
// pixel <= video_counter[7:0]; // color pattern
de<=1;
end else begin
if(h_cnt == H+HFP) begin
if(v_cnt == V+VFP)
video_counter <= 14'd0;
else if((v_cnt < V) && (v_cnt[1:0] != 2'b11))
video_counter <= video_counter - 14'd160;
de<=0;
end
pixel <= 8'h00; // black
end
end
// seperate 8 bits into three colors (332)
assign r = { pixel[7:5], 3'b00000 };
assign g = { pixel[4:2], 3'b00000 };
assign b = { pixel[1:0], 4'b000000 };
//assign r = 8'h00;
//assign g = 8'hff;
//assign b = 8'h00;
//assign VGA_DE = ~(hblank | vblank);
assign VGA_DE = de;
endmodule