Program/ Hardware Design


Write_SRAM Project

Displaying the Backgound Image

We are proud to state that we become the pioneer to write any image into the SRAM and display the image on the VGA Monitor. Now we can display any types of image in to an 8 bit color with 640 x 480 resolutions on VGA monitor using our VGA controller.

Writing Image into SRAM

We write our own separate project to write an image into the SRAM. The project has both the hardware part and the software part. The basic purpose of the project is to read image data and transfer it to the SRAM. We used MATLAB to generate the bit map data for the image in text file. We generated 8 bit data for each pixel.

The MATLAB program is available in the APPENDIX. Below is the description of our whole project. 

 

 

Hardware:

The hardware portion basically consists of a state machine. This state machine deals with the interaction with the CPU. The basic function of this state machine is to provide the two way handshaking so that the communication between the CPU and the hardware could be possible. It accepts data form the CPU and writes it into SRAM and sets a flag to let CPU know that writing has been completed. It gives the CPU a 1 bit status for ready that is when it is read to accept more data.

2 WAY HANDSHAKING

The handshaking works like this:

The hardware state machine asserts a ready flag which means that it is ready to accept the data. The CPU provides the data, address and a valid signal. The valid signal is the indication to write. As soon as the hardware gets the valid signal it writes the data at the address provided by the CPU and after writing, it asserts a flag which tells the CPU that data has been written. The state machine than goes back to its initial state and asserts its ready flag for accepting another data. The CPU after getting the writing done signal clears the Valid so that same data is not written again. 

TWO WAY HANDSHAKING State Machine

 

Software:

The function of the software is to read data from the text file calculate its address (location in the SRAM) and send it to the hardware according to the proper two way handshaking protocol.

The biggest problem we faced is to read data from the text file. Initially we used the fopen function but soon Dr.Land told us that fopen function could not be used to read data from a file stored into the file system of PC. NIOS II cannot recognize the local file system of the PC. Therefore we simply initialized an array which contained the whole text file.

Each word of an array is of 8 bit and represents one pixel. We needed to send 16 bit of data to SRAM with an 18 bit address. We needed 16 bit data because we have packed 2 pixels in 1 word of an SRAM. Therefore software is designed in such a way that it performs two reads and than sends it to SRAM. One read is of 8 bit and another read is of 8 bit again. When the word becomes 16 bit its address is calculated. After getting the address and the 16 bit data, write_data function is called to send it to SRAM.  Write_data function performs 2 way handshaking with the hardware to send data and address to the SRAM. The address is calculated in such a way that for every 320 increments of x there is only one increment of y until y reaches 480. x is 320 because again we are packing two pixels in one words so x is divided by 2.

This whole project was used to write an image to SRAM. The image is than read by a VGA controller to display it on the VGA monitor. It is to be noted that the reading of the image by the VGA Controller is also changed because SRAM no more contains one pixel per symbol.

 

DE2_NIOS_HOST_MOUSE_VGA Project

Hardware:

VGA Controller

The VGA Controller decides the output color for each pixel.  It consists of a priority encoder to select the outputs from different images, the cursor, the stick, the BBQ meat ball images, the BBQ meat ball on the stick image, the Level number, the Score number, the Stick Stack number, the You Lost Image and the background.  The image display is pipelined.

Priority Encoder                                  

After getting the flag set for the cursor and the stick we used priority encoder to pass the colors to the VGA monitor. Depending upon the flags the colors are passed to the registers Cur_Color_R, Cur_Color_G and Cur_Color_B. These registers are than further multiplexed with the enable signals to pass to the VGA DAC. The following chunk of code is used to multiplex these registers.

Memory Description

We have used different memories for storing our images. We have used SRAM to store our background information. We have used registers to store the stick and mouse images. We have used ROM ( M4K ) to store the different images that appears on the background image, such as BBQ icon image, Number image, and You Lost Image. We have used RAM ( M4K ) to store the location of the images on the screen. These image storage locations are than multiplexed for an access to a VGA Controller.

SRAM Controller

The VGA Controller outputs the X (Coord_X) and Y(Coord_Y) coordinates of the screen, each 10 bits, which is treated as a SRAM address. We took the lower 9 bits of the Y coordinate mCoord_Y[8:0] and upper 9 bits of the X coordinate  mCoord_Y[9:1]. As

our SRAM contains two pixels per one word so we have taken the upper 9 bits of X coordinate. By taking the upper 9 bits of the X coordinate we have divided it by two and made its range from 0 to 319. The Y remains 480 which is well addressed by lower 9 bits.

We have used the SRAM as our memory for storing information about the pixel and its color. The SRAM provides reading and writing with one clock cycle delay. For writing supply data, address and enable signal and it would take one clock cycle to write and same for the reading (you invert the enable signal and gets the data in next clock cycle).

In our design the SRAM is used by the VGA controller.The 18 bit address of the SRAM is treated as X and Y Coordinate for the VGA Screen and the Color information is treated as SRAM data.

The Data given by SRAM is read by the VGA which is the information for Red (mVGA_R), Green (mVGA_G) and Blue (mVGA_R). It is to be noted that each input for the Red, Green and Blue is 10 bits. And each pixel in the SRAM is of 1 byte with 3 bit of red, 3 bits of green and 2 bits of blue. So we have concatenated the 3 red bits together to get the whole 10 bit red. The same thing we did for Green and Blue. We have used the LSB of the X coordinate to multiplex between the two pixels in one word. The following chunk of code is used to read two pixels from one word of SRAM one by one.

//          VGA Data Reorder

//  Each pixel conetains 1 byte of color, 3 bits of red, 3 bits of green and 2 bits of blue

assign  mVGA_R                   =          mCoord_X[0]            ?          {SRAM_DQ[15:13],SRAM_DQ[15:13],            SRAM_DQ[15:13],   SRAM_DQ[15]}:      

                                                                                                                                    {SRAM_DQ[7:5],            SRAM_DQ[7:5],       SRAM_DQ[7:5],       SRAM_DQ[7]};

assign  mVGA_G                   =          mCoord_X[0]            ?          {SRAM_DQ[12:10],SRAM_DQ[12:10],            SRAM_DQ[12:10],   SRAM_DQ[12]}:      

                                                                                                                                    {SRAM_DQ[4:2],            SRAM_DQ[4:2],       SRAM_DQ[4:2],       SRAM_DQ[4]};        

assign  mVGA_B                   =          mCoord_X[0]            ?          {SRAM_DQ[9:8],      SRAM_DQ[9:8],            SRAM_DQ[9:8],       SRAM_DQ[9:8],       SRAM_DQ[9:8]}:

                                                                                                                                    {SRAM_DQ[1:0],            SRAM_DQ[1:0],       SRAM_DQ[1:0],       SRAM_DQ[1:0],       SRAM_DQ[1:0]};

 

Displaying Cursor

We used registers to display images. To display cursor we also used registers. The iCursor_X and iCursor_Y are the X and Y Coordinates of the cursor supplied by the software. We calculated Cursor_Xref and Cursor_Yref as shown in the following chunk of code.  

assign Cursor_Xref = X_START[9:0] + 10'd6 + iCursor_X;

assign Cursor_Yref = Y_START[9:0] + iCursor_Y;

Where X_START[9:0] and Y_START[9:0] are :

X_START                 =          H_SYNC_CYC+H_SYNC_BACK+4;

Y_START                 =          V_SYNC_CYC+V_SYNC_BACK;

In short X_START and Y_START are values before the active porch of the H_Sync and Y_sync pulses. 

There are two counters in the VGA controller. One is V_Cont which is used to count the vertical frames of the screen. One is H_Cont which is used to count the horizontal pixels on the screen. The H_Cont keeps incrementing until it reaches the end of the screen. On the other hand when H_Cont reaches the end of the screen the Y_Cont is incremented by one. In this way both counters cover the whole screen. 

We used these counters to display our picture. When checked for (V_Cont - Cursor_Yref). When it reaches zero it means that V_Cont is at the postion of the Cursor. At this position we checked if H_Cont==Cursor_Xref, means that whether H_Cont is also at this position of the pixel. If both the condition are true we set the flag for the cursor ( fCursor ) high. In the similar fashion we checked the exact pixels we wanted to display by checking the V_Cont and H_Cont values and set the flag high on the true conditions. This method enabled us to draw any shape of the object. For drawing the cursor we lighted up following pixels on the screen.

// draw the cursor

                                    /*

                                                  01234567

                                   

                                    0          00x0000000

                                    1          00xx000000

                                    2          00xxx00000

                                    3          00xxxx0000

                                    4          00xxxxx000

                                    5          00xxxx0000

                                    6          00x0xx0000

                                    7          00000xx000

                                    8          00000xx000

                                    9          000000xx00

                                                                       

                                          01234567

                                    */                                

Where “x” represents the cursor.

Displaying Stick

By using the same logic we displayed the stick. But the flag used in the stick is different and the reference for the stick is also different. The reference for the cursor includes the whole boundary while the stick reference is limited to the blue screen of background in the picture below. The reference of the stick is limited to the game window only. User cannot move the stick to on the whole screen.

 

 

The stick X and Y references are calculated by the following chunk of code:

assign Stick_Xref = fStick_X_hold? Stick_Xref : (Cursor_Xref < BBQ_LEFT+9'd3)? (BBQ_LEFT+9'd3) : (Cursor_Xref > BBQ_RIGHT-9'd1)? (BBQ_RIGHT-9'd1) : Cursor_Xref;

assign Stick_Yref = STICK_NTOP - iStick_length;

In the above chunk of code fStick_X_hold tells that if the stick length is at its original or not. In our design a user cannot move the stick while increasing the length. The stick can only be moved around while it is at its original length. Therefore if fStick_X_hold is true means that stick length is increasing the Stick_Xref is assigned to itself but if it is not true than the game boundaries are checked. The BBQ_LEFT is the left boundary and BBQ_RIGHT is the right boundary. If the stick is crossing the boundaries it is adjusted accordingly as specified in the above chunk of code.

Below is the description of the pixels lighted up to for the stick. 

                                                // draw the stick

                                                /*

                                                            321012 

                                   

                                                0          000x00

                                                1          000x00

                                                2          00xxx0

                                                3          00xxx0

                                                4          00xxx0

                                                5          0xxxx0

                                                6          0xxxx0

                                                */

Where “x” represents the stick.

Displaying the Cute BBQ Meat Balls

To display the BBQ meat balls we used two memories, one is ROM and another one is RAM. 

The RAM stores the BBQ display table (7x7) information which indicates which type of BBQ icon should be displayed at which position.

 

BBQ Display Table, Figure_RAM, 7X7

The ROM stores eight different type of image.  The image is stored in the ROM by first using the matlab code, figure_trans.m, in the appendix; and simply copy and paste the matrix from the matlab to the mif file of the ROM.

The reading of the ROM is provided by the code below:

assign Fig_addr_mem={Fig_index_mem[2:0],Fig_y_addr_mem, Fig_x_addr_mem};

where Fig_index_mem is the output from the Figure_RAM file, and x&y addresses are generated alone with the H_Cont and V_Cont.

For detail description and implementation of the displaying for the BBQ Icon, please see comments on the VGA_Controller.v in the appendix.

Displaying the BBQ Meat Balls on the Stick

To display the BBQ Meatball on the Stick, the same ROM for the BBQ icon is used.  A different RAM, StickFig_RAM is used to store the type and the address information of the BBQ icon on the stick.

BBQ icon on the Stick, StickFig_RAM, 1X7

The address of the BBQ icon on the Stick is relative to the stick reference, so it will move as the stick moves. 

The reading of the ROM is provided by the code below:

assign StickFig_addr_mem = {StickFig_index_mem[2:0],StickFig_y_addr_mem, StickFig_x_addr_mem};

where StickFig_index_mem is the output from the StickFigure_RAM file, and x&y addresses are generated alone with the H_Cont and V_Cont.

For detail description and implementation of the displaying for the BBQ icon on the stick, please see comments on the VGA_Controller.v in the appendix.

Displaying the Number

The Number ROM stores 20 different types of images, 0-9 32x64 and 0-9 32x32.  The image is stored in the ROM by first using the matlab code, number_trans.m, in the appendix; and simply copy and paste the matrix from the matlab to the mif file of the ROM.

The ROM is arranged in the way below:

 

0

64 bits

 1

 

2

 

3

:

4

:

5

:

6

 

7

 

8

 

9

64 bits

0

32 bits

1

 

2

 

3

:

4

:

5

:

6

 

7

 

8

 

9

32 bits

The Level logic reads the 32x64 bits number to display the number of Level.
The Score logic mux with stick stack number to read the 32x32 bits number to display the Score or the number of BBQ on the stick.

The reading addresses for the ROM are:

/////// For Level Number           --> 32X64 //////

assign LevelNum_addr_mem = {LevelNum_mem, LevelNum_y_addr_mem, LevelNum_x_addr_mem[4:0]};

////// For Score_StickStack number  --> 32X32 //////

// mux of Score and StickStack, the original address + the offset for ROM table reading

assign Score_StickStack_Num_addr_mem = fStickStackNum_en_mem? {StickStackNum_addr_mem+15'h5800}:{ScoreNum_addr_mem+15'h5800};
// For Score number

assign ScoreNum_addr_mem = {ScoreNum_mem, ScoreNum_y_addr_mem[4:0], ScoreNum_x_addr_mem[4:0]};

// For StickStack anumber

assign StickStackNum_addr_mem = {StickStackNum_mem, StickStackNum_y_addr_mem[4:0], StickStackNum_x_addr_mem[4:0]};

For detail description and implementation of the displaying for the Number on the stick, please see comments on the VGA_Controller.v in the appendix.

Displaying the You Lost Image  

The Lost ROM contains the You Lost message to the user on the screen. Simply read the ROM when the player lost the game will display such message on the VGA monitor.

For detail description and implementation of the displaying for the Number on the stick, please see comments on the VGA_Controller.v in the appendix.

The State Machine

The state machine manages the flow of the game.

State Diagram of FPGA BBQ Stick

 

For detail description and implementation of the state machine, please see comments on the VGA_Controller.v in the appendix. 

 

Software:

Length of the Stick

The length of the stick is controlled with the mouse left button. The stick gets elongated with the left click of the mouse. The length of the stick can be adjusted by pressing and releasing the left button of the mouse for different time intervals. The length of the stick is provided by the software.

The software detects press of the left button of the mouse and starts a counter. The counter is basically the length of the stick. The counter value is passed to the hardware. As long as the left mouse button is pressed the counter gets incremented until it reaches the maximum value that is the boundary of the screen. As soon as the user releases the left mouse button the counter starts decrementing with the decrements of five so that the stick length decreases immediately. The following chunk of code is used to implement the logic of the length of the stick.

Things we tried but failed.

Writing image to SRAM became one of the difficult tasks. It took us more than 100 man hours to do it. Initially we believed that it would be an easy task but as soon as we started to implement it, it became more complicated.

Our project required a background image of 640 x 480 resolution. We were using the Altera Paint Brush Example which uses M4K blocks to display the background image. We first tried to change the default background image displayed by the Altera. We tried to initialize our image into the M4K Blocks.

Initializing an Image Into M4K Block

Image can be initialized into the M4K block if image data is available into the MIF format. The basic procedure of doing that is to take the image and change its attributes to appropriate size using the Windows application Paint. After getting the required resolution image it needs to be converted into the text file. By text file we mean that it contains the value of each pixel in numbers separated by comma. We used Terasic  imgconv tool to convert the image into text file. After getting the text file it needs to be converted into the MIF format.

MIF ( Memory Initialization File )

An ASCII text file (with the extension .mif) that specifies the initial content of a memory block (CAM, RAM, or ROM), that is, the initial values for each address. This file is used during project compilation and/or simulation.

A MIF is used as an input file for memory initialization in the Compiler and Simulator. You can also use a Hexadecimal (Intel-Format) File (.hex) to provide memory initialization data.

A MIF contains the initial values for each address in the memory. A separate file is required for each memory block. In a MIF, you are also required to specify the memory depth and width values. In addition, you can specify the radixes used to display and interpret addresses and data values.

Following is a sample MIF:

DEPTH = 32;
WIDTH = 8;
ADDRESS_RADIX = HEX;
DATA_RADIX = BIN;
CONTENT
BEGIN

00 : 00000000;
01 : 00000001;
02 : 00000010;
03 : 00000011;
04 : 00000100;
05 : 00000101;
06 : 00000110;
07 : 00000111;
08 : 00001000;
09 : 00001001;
0A : 00001010;
0B : 00001011;
0C : 00001100;

END;

MIF file can be created by writing a small C program that reads from the text file and assign address to it. It can also be generated by using quartus II. Quartus II has an application that takes text file as an input and provides the MIF file.

After getting through this whole procedure we initialized our memory contents with MIF file. We got the image but it is black and white. It is discovered at this point that the VGA controller used by Altera could only provide two colors that is ON and OFF and if one can look seriously to the default image of Altera it is also of two colors that is Blue and White.

We changed our scheme of using the Altera Paint Brush example’s VGA controller. We also changed our memory for background image from M4K to SRAM. The basic reason for the change of memory is because of the size of the image to be displayed which is 640 x 480.

We also tried to use the CONTROL PANNEL tool provided by the Terasic to write an image into SRAM. The DE2 board comes with a CONTROL PANNEL facility that allows a user to access various components on the board through a USB connection from a host computer. One of the functions is to write an image into SRAM. But after exploring its all options we discovered that CONTROL PANNEL tool is not able to display a color image. It can only be used to display black and white or grey scale images.

FPGA BBQ Stick

Muhammad Bilal Shahid & Yang-Ching Cheng


IntroductionHigh Level  DesignProgram/Hardware DesignResults & ConclusionTricks & InventionsAppendix