Introduction High Level Design Hardware Design Results/Conclusion References/Appendix


Interested in graphics and in computer vision, I decided to design an elementary graphic card for the ECE5630 final project. The objective was to design a module which could receive geometry data and lightening information as in input and displays them on the VGA. My component implements several specific topics of graphic cards:

This project was the first step in the designing as a more complex graphic card which I will implement as my MEng Project.

High Level Design

Triangle rasterization

The first part of the project was the linear extrapolation between vertices of a triangle. This is performed by drawing two lines from a common vertex to the two others, and extrapolating between points of the lines, as explained in the diagram below:

This is a 2D version of the linear extrapolation we have performed in Lab 4. On the X-axis, we have 2 points at the same abcisse which evoluate as extrapolation of single lines. There is the same extrapolation on these two points.


I implemented Z-buffering in writing the Z of each pixel in memory. When a new pixel is to be drawn, memory is check whether there is a closer point to user's point of view.

I have implemented a basic scenario of lightening, only based on directional light, regardless of the distances, like that of the sun. Nevertheless, this project does not manage shadows.

Logical structure

I have splitted the project into different modules which could be used independently. The three modules are:

Line Triangle Renderer
This is the main component than in Lab 4, but dedicated to extrapolation on X-axis.
Triangle Renderer
This is the equivalent component of the previous one, but in 2D.
Memory triangle controller
This is the main component which controls the data to be sent in the memory.
Each one requires the previous. I have also implemented a top main module to make the demonstrations.

Hardware Design

Most of these modules have similar architecture based on a state machine and on controlling signals which are explained below:

If false, then the module should reset: clear all its registers and come back in Idle state
For the transition of the state machine
Should be high to active the transition of the state machine. This permit to “freeze” a module without clearing its registers.

Line triangle renderer

This is the basic component to draw a line. It implements the algorithm described for Lab4, so it would not be described again. It permits to extrapolate many values (exhaustively Red, Green, Blue and Z) between that of the two extremities of the line. Because the triangle will be displayed column by column, one important consideration was the output to prevent that the module was reaching a new x in its extrapolation. This is the list of communicating signals, in addition to these mentioned above (for readability, size of signals is omitted):

input start
the user module asks Line Triangle Renderer to start rendering
output completed
Line Triangle Renderer warns user module that it has completed its rendering
input p1_x, p1_y, p1_z, p1_r, p1_g, p1_b
Input data for Point 1
input p2_x, p2_y, p2_z, p2_r, p2_g, p2_b
Input data for Point 2
output x, y, z, r, g, b
Data for current point
Warns user module that new point has a new x

The main state machine was composed of four different states:

The module has nothing to do and has completed its previous rendering.
Empty state to prevent the user module that the line is currently reaching a new point. Line Triangle Renderer remains idle this state in the probable case user module will likely freeze it to deal with the new point.
One iteration in the algorithm to reach a new point.
The module has completed its rendering and wait for the start signal to be low. If user module keeps sending start signal until it has completed, Line Triangle Renderer is not confused and do not try to render the same line.


Triangle renderer

This module is the core of triangle rasterization. Its objective is to receive the data of three points and to extrapolate data (r, g, b, z) of the points inside the delimited triangle. One redundancy about this module was to deal with the similar but different cases (order of the points, clock-wise versus counter-clock-wise). This is the list of specific signals:

start, completed
as in Line Triandle Renderer
input p1_x,…, p1_b, p2_x, …, p3_b
input data for the three points
output x, y, z, r, g, b
data for curent point
output newPoint
to warn the user module that data for new point is being provided

This modules instanciates two Line Triangle Renderer to move the top and bottom lines. It garantuees that when the first line reaches its final point, this line will switch to the third point. One critical point of this module was the synchronisation of the lines. The main state machine reflects these considerations.

Similar to that of Line Triangle Renderer
Triangle Renderer is expecting both lines to switch to the next point with a different X
Triangle Renderer is expecting only top line to switch to the next point with a different X
Triangle Renderer is expecting only bottom line to switch to the next point with a different X
Initializes extrapolation with new X.
When both lines are on a point with same X, this is the state where Triangle Renderer extrapolates between these points on a y-axis
Similar to that of Line Triangle Renderer

One critical consideration in this module is performance. It is important that in most cases (on Drawing state) on each cycle, a new point is being calculated and provided to user module. Two other registers, corner and second, were used to permit the switching of the top/bottom line when the second point is reached. This switching was another difficulty. Transitions:

Memory triangle controler

This component's objective is to fill the data in memory with the output of a Triangle Renderer. This is where the Z-buffering and lightnening are implemented. This is the list of the signals users see: Memory access

output write
write enable for memory
output addr_reg
output data_reg
input p1_x .. p3_b
Data for extremity
input z_enable
z-buffering enable
input z_existence
Tells Memory triangle controler that a points has already been placed in memory at the current location
input z_data
Tells Memory triangle controler the z about the point currently in buffer, should it exists.
input light_enable
light enable
input light_r, light_g, light_b
Light's colors.
input material_r, material_g, material_b
Material colors
input light_n_x, light_n_y, light_n_z
Light normal
input n_x, n_y, n_z
Normal of triangle

In order to implement Z-buffering with a sizeable resolution, and to keep 5 bits per color channel, I have lowered my screen resolution to 512*256. This permited me to have 2 memory slots per pixel on screen, one exlusively dedicated to Z-buffering. The main state machine was composed of these different states:

Same as usual.
Initializing state.
Common state of rendering.
Module is getting Z information from memory at the position of the current pixel and decides to write something in it.
From previous state, updating the Z-buffer with new pixel.

The module is implemented in a DE2_TOP module as an example of the use of the module.

Results & Conclusions

Without Z BufferWith Z Buffer
Without lighting
With lighting

I did not have precise limits about what I wanted to implement, but I consider that I have succeeded in implementing the real basic-end of the graphic pipeline. The project lets some very interesting pathes for progress :

In addition to these technical issues, I stayed too much in the very last part in the pipeline. As an example, I did not reach the 3D floating computation for example, as many things which are closer to the end-user.

I will keep working on this project as my MEng project.


I would like to thank both professor Land and TA Adam Shapiro for their disponibility, all the help they provided me and to have animated one of the most teachable and interesting course of this semester.



Altera Website
ECE 5760 Website


The harware files

Total project