What do you think would happen if
move_ball_en were asserted while the image was being displayed, instead of while the image is inactive?draw_ball: process(pixel_x, pixel_y, x0, y0)
begin
if (pixel_x >= x0) and (pixel_x < x0+4)
and (pixel_y >= y0) and (pixel_y < y0+4)
then
color <= RED;
else
color <= WHITE;
end if;
end process draw_ball;
pixel_x and pixel_y are coordinates from the controller, and RED and WHITE are 12-bit RGB constants (e.g., x"F00" and x"FFF").move_ball: process(clk)
begin
if rising_edge(clk) then
if move_ball_en = '1' then
x0 <= x0 + dx;
y0 <= y0 + dy;
end if;
end if;
end process move_ball;
dx and dy are the horizontal and vertical increments in the square’s position. The enable signal, move_ball_en, is asserted for only one clock cycle in every frame. The ball is drawn in a new position in each successive frame, and moves across the screen. The speed at which the ball moves will be \(60 \sqrt{(dx)^2 + (dy)^2}\) pixels/second.move_ball_en is during the inactive blanking period between the bottom of the frame and the top of the next frame. A state machine can be designed to watch for the v_blank signal to go low, enable the update for one clock cycle, and then watch for v_blank to go high again.move_ball_en were asserted while the image was being displayed, instead of while the image is inactive?move_ball_en were asserted for more than one clock cycle in each frame?FSM_comb: process(curr_state, v_blank)
begin
next_state <= curr_state; -- defaults
move_ball_en <= '0';
case curr_state is
when v_on =>
if v_blank = '0' then
next_state <= update;
end if;
when update => move_ball_en <= '1';
next_state <= v_off;
when v_off =>
if v_blank = '1' then
next_state <= v_on;
end if;
end case;
end process FSM_comb;
dx, should change sign so that the ball will reverse direction. The vertical increment does not change; if the ball is moving up and to the right when it hits the wall, it will be moving up and to the left after it bounces. Detecting a collision must take into account the size of the ball, so that the ball doesn’t move beyond the edge of the screen before bouncing.ball_hit_wall: process(clk)
begin
if rising_edge(clk) then
-- Hit the right wall
if (dx > 0) and (x0 >= 640-4) then
dx <= -dx;
-- Check the other walls
end if;
end if;
end process ball_hit_wall;
640-4 should, of course, be replaced by named integer constants for the location of the wall and the size of the ball. The remainder of the process is left as an exercise.ball_hit_wall process to include collisions with the other three walls.draw_ball, move_ball, and ball_hit_wall with the update state machine and a VGA controller will draw a ball bouncing around the screen. Once you have this, you can imagine drawing and moving other objects, controlling the movement of objects with user input (like pushbuttons), and colliding one moving object with another. A good project to try is the classic "Pong" game.