EmbDev.net

Forum: FPGA, VHDL & Verilog Assignment under elsif does not work


von Burak G. (Company: Bilkent Uni) (brekout)


Rate this post
useful
not useful
Hello everyone,

I am developing a brick breaking game in VHDL. For this project, I have 
successfully implemented a image generator and a VGA synchronizer. 
However, I am having problems with the game logic. In this game, bricks 
are supposed to be destroyed when the ball hits. When a collision is 
observed, the ball should change its direction. So as to realize this, I 
wrote the following code:
1
    process(refresh_tick,ball_x,ball_y,xv_reg,yv_reg)
2
    begin
3
         ball_x_next <=ball_x;
4
         ball_y_next <=ball_y;
5
         xv_next<=xv_reg;
6
         yv_next<=yv_reg;
7
         if refresh_tick = '1' then
8
           if ball_y> 400 and ball_x > (bar_l -ball_u) and ball_x < (bar_l +120) then --the ball hits  the bar
9
               yv_next<= -y_v ;
10
           elsif ball_y <= 0 then--The ball hits the wall
11
               yv_next<= y_v;
12
           elsif ball_x <= 0 then --The ball hits the left side of the screen
13
              xv_next<= x_v;
14
           elsif ball_x >= 640 then 
15
              xv_next<= -x_v ; --The ball hits the right side of the screen
16
           elsif is_ball_on_bricks_area and bricks_collection(current_brick_row, current_brick_column) = '1' then
17
              yv_next <= y_v;
18
              bricks_collection(current_brick_row, current_brick_column) <= '0';
19
           end if; 
20
           ball_x_next <=ball_x +xv_reg;
21
           ball_y_next <=ball_y+yv_reg; 
22
        end if;
23
    end process;

In this game, I define bricks as a 2D array:

    type brick_array is array (0 to 4, 0 to 9) of std_logic;
    signal bricks_collection : brick_array := (others => (others => 
'1'));

So, when a collision is detected, the destroyed brick is assigned as '0' 
and ball change its direction yv_next <= y_v; Unfortunately, only one of 
them is executed during the run time which is at this case 
bricks_collection(current_brick_row, current_brick_column) <= '0';. I 
know that the logic I came up with works, that is, collisions are 
detected successfully.

These statements under the last elsif statement should be run 
concurrently. But they are not. How do I make them run concurrently?

So I know that in a process if I do something like this, the second 
assignment takes place at the second clock tick:

    process(clk)
    begin
    a <= b;
    b <= c;
    end process;

Is this a similar problem?

: Edited by Moderator
von Klakx (Guest)


Rate this post
useful
not useful
firstly, please use vhdl formatting in this forum.

secondly, complete your sensitivity list with all used signals like 
"is_ball_on_bricks_area,x,x_v,y_v,.."

von Burak G. (Company: Bilkent Uni) (brekout)


Rate this post
useful
not useful
Thank you for your reply. I can not go back and change the formatting. 
Sorry about that.

I added is_ball_on_bricks_area to the sensitivity list. However, x_v and 
y_v are constant which are determining the speed of the ball. That is, 
if y_v is 3, ball goes down. If it is -3, the ball goes up.

So let me repeat the problem in different words.
1
elsif is_ball_on_bricks_area and 
2
bricks_collection(current_brick_row, current_brick_column) = '1' then
3
              yv_next <= y_v;
4
              bricks_collection(current_brick_row, current_brick_column) 
5
<= '0';

Here, if I remove bricks_collection part, yv_next <= yv part is executed 
correctly. However, when I keep it as it is, which I should, only the 
second assignment takes place.

von Klakx (Guest)


Rate this post
useful
not useful
current_brick_row and current_brick_column look also like no constants, 
try to add them also to sensitivity list.

also there is bricks_collection only defined in one arc which will lead 
to latch behavior. I dont know your code and cannot say if this was 
intended.

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
bricks_collection has to be in the sensitivity list also. But that will 
not help that far, because this is a very dirty tricky trick here:
1
           elsif is_ball_on_bricks_area and bricks_collection(current_brick_row, current_brick_column) = '1' then
2
              yv_next <= y_v;
3
              bricks_collection(current_brick_row, current_brick_column) <= '0';
4
           end if;
Here we have a asynchronous reset on bricks_collection and therefore a 
latch. Usually latches are a very bad thing, because mostly they 
happen accidentially. In your design this is (like nearly always) due to 
the 2-process coding style.
In other words: bricks_collection is storing some information. Storing 
elements in a FPGA should be flipflops. Therefore there should be 
something like a bricks_collection_next (like all of the other 
flipflops). And that bricks_collection_next then must be written to 
bricks_collection with the (one and olny) clock (like all the others).


BTW just one question: why do you use a process for that all?
It could be easily done concurrent...

von Burak G. (Company: Bilkent Uni) (brekout)


Rate this post
useful
not useful
Thank you so much. Indeed, latch behavior was not intended.

I was able to solve all my problems by introducing the register logic 
once more.

Miller, before starting on this project, I read few articles, reports, 
and went through some examples of similar games. I saw that they are 
using so-called 2-process design method. Therefore, I adapted a similar 
approach. However, I have never thought "latch behavior" could lead to 
prevent assignment of y_v to yv_next and I have yet to understand the 
reason behind that.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.