-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproject_fpga_vga.html
More file actions
200 lines (161 loc) · 9.44 KB
/
project_fpga_vga.html
File metadata and controls
200 lines (161 loc) · 9.44 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
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
<!-- Simple personal projects blog website -->
<!DOCTYPE html>
<!-- Path: index.html -->
<html lang="en">
<head>
<script src="cubeScript.js"></script>
<script src="prism.js"></script>
<link rel="stylesheet" href="prism.css">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Henri's world</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="styleCube.css">
</head>
<body>
<div class="container">
<!-- Navigation bar -->
<div class="navbar">
<div class="cube3d_scene">
<div class="cube3d">
<div class="front"> <img src="images/cubeFace.png"> </div>
<div class="back"> <img src="images/cubeFace.png"> </div>
<div class="right"> <img src="images/cubeFace.png"> </div>
<div class="left"> <img src="images/cubeFace.png"> </div>
<div class="down"> <img src="images/cubeFace.png"> </div>
<div class="top"> <img src="images/cubeFace.png"> </div>
</div>
</div>
<nav>
<ul>
<li><a href="index.html">Home</a>
</li>
<li><a href="about.html">About</a>
</li>
<li><a href="projects.html">Projects</a>
</li>
</ul>
</nav>
</div>
<!-- Main content -->
<div class="main">
<h1 id="Label">FPGA VGA Graphics Controller</h1>
<h2>About</h2>
<p style = "text-indent:1cm;">
In this project I created a double buffered VGA graphics design using an Xilinx Spartan-7 series FPGA board.
The FPGA board that I have has enough memory for a 1-bit colored 320x240 pixel image.
All the code was written and tested in Xilinx Vivado using VHDL language.
</p>
<img src="images/cmod_s7.png" style="max-width:50%;">
<center><b class="imgvid_title">Cmod S7 - Xilinx Spartan-7 Breadboardable FPGA board</b></center>
<p>
FPGA board is hooked up as shown below.
One end of VGA cable was cut and jumper wires were soldered to the ends of the wires.
</p>
<img src="images/cmod_s7_vga_connected.jpg">
<center><b class="imgvid_title">Cmod S7 - Xilinx Spartan-7 Breadboardable FPGA board</b></center>
<p>
My targets for this project were to have double buffered graphics and simple interface to the top module.
The controller was to be able to set individual pixels, draw lines and swap buffers with or without clearing the old buffer.
</p>
<p>
Double buffering is done in non-conventional way.
The VGA Controller has two buffers, one for drawing (rgb-buff)
and one for displaying (vga-buff).
The drawing buffer is True Dual Port Ram meaning that
it has two sides, each in different clock domain, which can be
accessed and written to independently.
The display buffer is a single side, i.e., ordinary Ram memory.
When "swapping buffers", or flipping as I call it in this project,
the content of rgb-buffer is copied to the vga-buffer.
When flipping with destructive_read_req, zeros are written to rgb-buff
while copying the contents to vga-buff.
</p>
<p>
Every draw request goes through write queue (FIFO) inside the VGA Graphics controller.
This way the requests can be queued up for the VGA Controller so that
VGA Controller can process them when ready.
This queue is processed when VGA controller is currently not flipping.
This takes away for any other part of the system (e.g. CPU) the need to wait for
the VGA Controller to finish processing the request.
Only when requesting to swap buffers, the CPU has to wait for the VGA Controller
to finish processing old drawing requests.
The need for waiting is best explained by the following example:
CPU is in a loop where it requests to draw a long line and immediately requests to swap buffers.
In this case CPU is requesting lines and flips faster than the VGA Controller can process them.
This leads to anomalies, such as undefined end result on the screen.
</p>
<p>
Individual pixels are set by pushing the target pixel location along with the color to the FIFO of the VGA Graphics Controller.
</p>
<div class="video">
<video width="640" height="320" controls>
<source src="videos/vga_single_bit_addressing.mp4">
Your browser does not support the video tag.
</video>
</div>
<center><b class="imgvid_title">Writing indivudual pixels and then swaping buffer with (with clearing)</b></center>
<p>
Lines are drawn using Bresenham's line algorithm.
The algorithm chosen as it does not require any division.
Requests for lines are created by pushing the start and end points of the line
along with the color to the FIFO of the VGA Graphics Controller.
</p>
<div class="video">
<video width="640" height="320" controls>
<source src="videos/vga_line_drawing.mp4">
Your browser does not support the video tag.
</video>
</div>
<center><b class="imgvid_title">Drawing lines and then swaping buffer with occasional clearing</b></center>
<h2>Putting it together</h2>
<img src="images/fgpa_vga_block_diagram.png">
<center><b class="imgvid_title">Rough diagram of the VGA Graphics Controller</b></center>
<div class="video">
<video width="640" height="240" controls>
<source src="videos/VGA_graphics_top.mp4">
Your browser does not support the video tag.
</video>
</div>
<center><b class="imgvid_title">Example: Drawing pixels/lines, flipping with/without clearing</b></center>
<p>
After line- and pixel drawing worked independently,
they were combined into single module.
This module has another FIFO queue (Draw Request Queue) that takes drawing requests,
either pixel or line requests.
Format of the data (vga_req_fifo_din) is following:
<ul>
<li>
(38 downto 37) --- type (pixel="00" and line="01")
</li>
<li>
(36 downto 28) --- x0 (Used for pixel requests x coordinate)
</li>
<li>
(27 downto 20) --- y0 (Used for pixel requests y coordinate)
</li>
<li>
(19 downto 11) --- x1
</li>
<li>
(10 downto 3) ---- y1
</li>
<li>
(2 downto 0) ----- color
</li>
</ul>
</p>
<p>
I used 2-bit type for possible expansion of the functionality.
For example, sprite drawing from memory, x0 and y0 could be
used for location to draw sprite to and x1, y1 and color could be used
as memory location from where to start drawing sprite.
Sprite end could have specific binary value to indicate end of sprite.
This type of drawing would mean that even if the sprite has large bounding box,
it only takes up space in memory by the amount of non-zero pixels.
</p>
<a class="hyperLink" href="source_explore/fpga_vga.html">Explore Source</a>
</div>
</div>
</body>
</html>