Assignment under elsif does not work

OP (Company: Bilkent Uni) #5000373
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?
OP (Company: Bilkent Uni) #5000495
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.
Guest #5000556
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.
Moderator (Company: Titel) #5000591
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...
OP (Company: Bilkent Uni) #5000835
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.

Reply

Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.

Formatting
  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]
  • [[Title]] – link to an article
  • Link to another post: right-click its post ID (#8078628), copy the address, paste it into the text

More about formatting

Post long source code as an attachment, not in the text.

Already registered? Log in

Not shown to anyone. We send you a link; your post appears once you confirm it there.

By submitting you create a free account and accept the terms of use.