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:
process(refresh_tick,ball_x,ball_y,xv_reg,yv_reg) begin ball_x_next <=ball_x; ball_y_next <=ball_y; xv_next<=xv_reg; yv_next<=yv_reg; if refresh_tick = '1' then if ball_y> 400 and ball_x > (bar_l -ball_u) and ball_x < (bar_l +120) then --the ball hits the bar yv_next<= -y_v ; elsif ball_y <= 0 then--The ball hits the wall yv_next<= y_v; elsif ball_x <= 0 then --The ball hits the left side of the screen xv_next<= x_v; elsif ball_x >= 640 then xv_next<= -x_v ; --The ball hits the right side of the screen elsif is_ball_on_bricks_area and bricks_collection(current_brick_row, current_brick_column) = '1' then yv_next <= y_v; bricks_collection(current_brick_row, current_brick_column) <= '0'; end if; ball_x_next <=ball_x +xv_reg; ball_y_next <=ball_y+yv_reg; end if; 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
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,.."
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.
elsif is_ball_on_bricks_area and bricks_collection(current_brick_row, current_brick_column) = '1' then yv_next <= y_v; bricks_collection(current_brick_row, current_brick_column) <= '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.
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.
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:
elsif is_ball_on_bricks_area and bricks_collection(current_brick_row, current_brick_column) = '1' then yv_next <= y_v; bricks_collection(current_brick_row, current_brick_column) <= '0'; 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...
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.