FPGA tutorial – VGA video Generation with FPGA and Verilog – add video memory to the project and object animation The previous blog about video generation is here.
For the weekend I posted Verilog Programming challenge to change the shape of the square to circle but unfortunately we didn’t got single solution 🙂

I guess you guys also learn yet and this was hard challenge to solve 🙂

In this post I will show you that this is not so hard.

Let's see again the source from the older post, here is where square is generated:

if(c_col > l_sq_pos_x && c_col < r_sq_pos_x && c_row > u_sq_pos_y && c_row < d_sq_pos_y) begin
//generate blue square
vga_r_r <= 0;
vga_g_r <= 0;
vga_b_r <= 7;
end

What this codes does? If the video coordinates are within square we assign some color to VGA output.

This is the part we should modify to draw circle but how?

We will use for this purpose video memory and in this memory we will draw circle then when the video beam is in this area it will draw the content of the video memory.

Let’s define the memory:

reg [19:0] sq_figure [0:19];

This defines 20 registers which are 20 bit wide, so we define 20×20 bit video memory which we will use to draw image on the VGA screen.

We also need two counters which to count XY beam position within the square area where we will draw:

wire [4:0] sq_fig_x;
wire [4:0] sq_fig_y;

assign sq_fig_x = c_col - l_sq_pos_x; // our figure's x axis when in square boundary
assign sq_fig_y = c_row - u_sq_pos_y; // our figure's y axis when in square boundary

This video memory registers must be load with the ball image, we will do this during the reset state where we initialize other registers too:

if(reset == 1) begin //while RESET is high init counters
sq_figure[19:0] <= 20'b00000000000000000000;
sq_figure[19:0] <= 20'b00000001111100000000;
sq_figure[19:0] <= 20'b00000111111111000000;
sq_figure[19:0] <= 20'b00011111111111110000;
sq_figure[19:0] <= 20'b00111111111111111000;
sq_figure[19:0] <= 20'b00111111111111111000;
sq_figure[19:0] <= 20'b01111111111111111100;
sq_figure[19:0] <= 20'b01111111111111111100;
sq_figure[19:0] <= 20'b11111111111111111110;
sq_figure[19:0] <= 20'b11111111111111111110;
sq_figure[19:0] <= 20'b11111111111111111110;
sq_figure[19:0] <= 20'b11111111111111111110;
sq_figure[19:0] <= 20'b11111111111111111110;
sq_figure[19:0] <= 20'b01111111111111111100;
sq_figure[19:0] <= 20'b01111111111111111100;
sq_figure[19:0] <= 20'b00111111111111111000;
sq_figure[19:0] <= 20'b00111111111111111000;
sq_figure[19:0] <= 20'b00011111111111110000;
sq_figure[19:0] <= 20'b00000111111111000000;
sq_figure[19:0] <= 20'b00000001111100000000;

c_hor <= 0;
c_ver <= 0;
vga_hs_r <= 1;
vga_vs_r <= 0;
c_row <= 0;
c_col <= 0;
end

Now we have loaded our video memory with the image of the ball and we should add code which draw it:

if(c_col > l_sq_pos_x && c_col < r_sq_pos_x && c_row > u_sq_pos_y && c_row < d_sq_pos_y) begin
//generate picture from the video memory
if(sq_figure[sq_fig_y][sq_fig_x] == 1) begin
vga_r_r <= 7;
vga_g_r <= 0;
vga_b_r <= 7;
end
else begin
vga_r_r <= 0;
vga_g_r <= 0;
vga_b_r <= 0;
end

What we do here? If the video memory is 1 we draw pink dot otherwise black on the screen. Is it really so simple? Let’s compile and see what happens!

Wow it works! You see the picture above.

Let’s copy this code it to example_4.v for further reference.

Now when we have video memory we can change it content and make animations by change dynamically the image inside the video memory.

To do this we have to load the registers with different ‘picture’.

Before we do this first let’s fix something annoying with the keyboard handling which bothers me. When I press up key ball start to move up and I can’t change the direction until it hits the wall.

This is because we commented the code for key release, so the arrow flags are clear press key flag is to hit the wall.

Let’s make this modification:

if(c_row == 1 && c_col == 1) begin //once per video frame
if(u_arr) begin
if (sq_pos_y > square_size) begin
sq_pos_y <= sq_pos_y - 1;
end
else begin
u_arr <= 0;
d_arr <= 1;
end
end;

if(d_arr) begin
if (sq_pos_y < (v_pixels - 1 - square_size)) begin
sq_pos_y <= sq_pos_y + 1;
end
else begin
d_arr <= 0;
u_arr <= 1;
end
end;

if(l_arr) begin
if (sq_pos_x > square_size) begin
sq_pos_x <= sq_pos_x - 1;
end
else begin
l_arr <= 0;
r_arr <= 1;
end
end;

if(r_arr) begin
if (sq_pos_x < (h_pixels - 1 - square_size)) begin
sq_pos_x <= sq_pos_x + 1;
end
else begin
r_arr <= 0;
l_arr <= 1;
end
end;

end

Great! Now I can change up down left right direction on the fly while ball is moving, but the ball after a while start moving only diagonally because up down do not change left right direction 🙂
Let’s save current example to example_5.v for further reference and try to modify one more time the code.

Let’s make if ball is moving up but also in any of X direction pressing second time up to make it move stright up and same for other keys.

First we will need to add de-bounce time as once we press the key each frame this means 25 per second key will be scanned .

We will add de-bounce timer:

reg [19:0] arr_timer; // delay between key check

We define 20 bit counter, which will be clocked at 25Mhz and will overflow after 0.041(6) seconds, we will check keys only when this counter oveflow:

arr_timer <= arr_timer + 1;

if(arr_timer == 0) begin
if(ps2_data_reg_prev == 8'he0) begin //0xE0 means key pressed
if(ps2_data_reg == 8'h75) begin
if(u_arr == 1) begin
u_arr <= 1; //0x75 up key
d_arr <= 0;
l_arr <= 0;
r_arr <= 0;
end
else begin
u_arr <= 1; //0x75 up key
d_arr <= 0;
end
ps2_data_reg <= 0;
end
if(ps2_data_reg == 8'h6b) begin
if(l_arr == 1) begin
l_arr <= 1; //0x6B left key
r_arr <= 0;
u_arr <= 0;
d_arr <= 0;
end
else begin
l_arr <= 1; //0x6B left key
r_arr <= 0;
end
ps2_data_reg <= 0;
end
if(ps2_data_reg == 8'h72) begin
if(d_arr == 1) begin
d_arr <= 1; //0x72 down key
u_arr <= 0;
l_arr <= 0;
r_arr <= 0;
end
else begin
d_arr <= 1; //0x72 down key
u_arr <= 0;
end
ps2_data_reg <= 0;
end
if(ps2_data_reg == 8'h74) begin
if(r_arr == 1) begin
r_arr <= 1; //0x74 right key
l_arr <= 0;
u_arr <= 0;
d_arr <= 0;
end
else begin
r_arr <= 1; //0x74 right key
l_arr <= 0;
end
ps2_data_reg <= 0;
end
end
end

When u_arr is 0 and it is set 1 we just clear d_arr, but if u_arr already has been 1 and we set u_arr again we clear l_arr and r_arr too.

This way if ball moves diagonally up and we press the up key again it will go straight up, same for the other directions too.

Now everything is perfect! Let save it as example_6.v

One last mod: Let’s use arr_timer to dynamically change the video memory, we add this code

if(arr_timer == 0) begin
sq_figure[19:0] <= sq_figure[19:0] ^ 20'b00000001111000000000;
sq_figure[19:0] <= sq_figure[19:0] ^ 20'b00000001111000000000;
sq_figure[19:0] <= sq_figure[19:0] ^ 20'b00000001111000000000;
sq_figure[19:0] <= sq_figure[19:0] ^ 20'b00000001111000000000;

What we do here, each time arr_timer overflow (25 000 000 / 2^20) i.e. each 0.0416 seconds we xor few lines of the video memory and thus make square hole inside the ball.

We compile and see that the ball animation works but too fast. Let’s change the arr_timer to 21 bit and slow town the blinking.

The new code is saved as example_7.v What we learn so far? How to define memory in Verilog and how to display this memory content at given coordinates.

All changes are now uploaded at GitHub.

What Next?

In the next Tutorial we will use iCE40HX1K-EVB SRAM memory as video memory to generate video with resolution 640×480 pixels 512 colors.

Then we will teach you how to use the 100Mhz  iCE40-ADC and iCE40-DAC.

Using  iCE40HX1K-EVB as 100Msps Logic Analizer for signals with voltage levels from  1.65V to 5.5V using iCE40-DIO and connected to Sigrok Pulseview and how you can sniff CAN, USB, RFID, I2C, I2S, JTAG, MIDI, MODBUS, SPDIF, SPI, and all other 66 decoding protocols which Sigrok supports.

Hynix DDR memory plants in fire after chemical explosion, market in panic Yesterday two of Hynix DDR memory plants burned in fire due to chemical explosion.

Hynix is producing 25% of world DDR memory supply, the prices of DDR memory rised with 10% in the first hour after the news and rise with another 10% later yesterday.

So 20% was seen just in the first day after the explosion, although these two factories produce about 10% of world memory supply.

All dealers stopped sales waiting the situation to calm down.

These factories were the only source for GDDR5 memories for nVidia and AMD, so what will happend to the prices of the graphics cards is yet to be seen.

How does this affect OLinuXino? For the moment no affect as we have DDR in stock and can wait to see what will happen with the prices in the next months.

Before this explosion the DDR3 memory prices already were two times more expensive than 8 months ago (Dec 2012 was their pick low when several DDR manufacturers went in bancrupcy and closed factories), so going up for long term period is unlikely, but market speculators wait for situations like this to make quick profit.