使用VGA控制器创建两个移动对象

时间:2013-12-07 00:03:17

标签: vhdl

我正试图在800x600的屏幕上实现一些“球”弹跳。我不完全明白如何让第二球在屏幕上移动。现在,它只是静止地停留在屏幕上的某个位置。

以下是我到目前为止所拍摄的照片。

        library IEEE;
        use IEEE.STD_LOGIC_1164.ALL;
        use IEEE.STD_LOGIC_ARITH.ALL;
        use IEEE.STD_LOGIC_UNSIGNED.ALL;

        entity pong is
            Port ( myclk : in  STD_LOGIC;
                   rgb : out  STD_LOGIC_VECTOR (2 downto 0);
                   hs : out  STD_LOGIC;
                   vs : out  STD_LOGIC);
        end pong;

        architecture Behavioral of pong is

        signal clk: STD_LOGIC;
        signal horz_scan: STD_LOGIC_VECTOR (9 downto 0);
        signal vert_scan: STD_LOGIC_VECTOR (9 downto 0);
        signal vinc_flag: STD_LOGIC;
        signal dx: STD_LOGIC;
        signal dy: STD_LOGIC;
        signal refresh_counter: STD_LOGIC;
        signal posx: integer := 300;
        signal posy: integer := 300;
        signal color: STD_LOGIC_VECTOR (2 downto 0) := "111";

        signal vinc_flag2: STD_LOGIC;
        signal dx2: STD_LOGIC;
        signal dy2: STD_LOGIC;
        signal posx2: integer := 300;
        signal posy2: integer := 300;
        signal color2: STD_LOGIC_VECTOR (2 downto 0) := "001";
        signal refresh_counter2: STD_LOGIC;
        signal horz_scan2: STD_LOGIC_VECTOR (9 downto 0);
        signal vert_scan2: STD_LOGIC_VECTOR (9 downto 0);
        signal clk2: STD_LOGIC;
        begin

          -- Clock divide by 1/2
          process(myclk)
          begin
            if myclk = '1' and myclk'Event then
              clk <= not clk;
            end if;
          end process;

          -- horizonal clock
          process(clk)
          begin
            if clk = '1' and clk'Event then
              if horz_scan = "1100100000" then
                horz_scan <= "0000000000";
              else
                horz_scan <= horz_scan + 1;
              end if;
            end if;
          end process;

          -- vertial clock (increments when the horizontal clock is on the front porch
          process(vinc_flag)
          begin
            if vinc_flag = '1' and vinc_flag'Event then
              if vert_scan = "1000001001" then
                vert_scan <= "0000000000";
                  refresh_counter <= refresh_counter xor '1';
              else
                vert_scan <= vert_scan + 1;
              end if;
            end if;
          end process;

          process(vinc_flag2)
          begin
            if vinc_flag2 = '1' and vinc_flag2'Event then
              if vert_scan2 = "1000001001" then
                vert_scan2 <= "0000000000";
                  refresh_counter2 <= refresh_counter2 xor '1';
              else
                vert_scan2 <= vert_scan2 + 1;
              end if;
            end if;
          end process;

          process(refresh_counter)
          begin

            if refresh_counter = '1' and refresh_counter'Event then

              if dx = '0' then
                posx <= posx + 1;
                else
                  posx <= posx -1;
                end if;

                if dy = '0' then
                posy <= posy + 1;
              else
                posy <= posy -1;
                end if;

                color <= "100";
             end if;
          end process;

          process(refresh_counter2)
          begin

            if refresh_counter2 = '1' and refresh_counter2'Event then

              if dx2 = '0' then
                posx2 <= posx2 + 1;
                else
                  posx2 <= posx2 -1;
                end if;

                if dy2 = '0' then
                posy2 <= posy2 + 1;
              else
                posy2 <= posy2 -1;
                end if;

                color2 <= "001";
             end if;
          end process;

          process(posx)
          begin
            if posx = 144 then
               dx <= '0';
             elsif posx = 734 then
               dx <= '1';
             end if;
          end process;

          process(posy)
          begin
            if posy = 35 then
               dy <= '0';    
             elsif posy = 465 then
               dy <= '1';
             end if;
          end process;

          process(posx2)
          begin
            if posx = 144 then
               dx <= '0';
             elsif posx = 734 then
               dx <= '1';
             end if;
          end process;

          process(posy2)
          begin
            if posy = 35 then
               dy <= '0';    
             elsif posy = 465 then
               dy <= '1';
             end if;
          end process;

          -- horizontal sync for 96 horizontal clocks (96 pixels)
          hs <= '1' when horz_scan < 96 else '0';
          -- vertial sync for 2 scan lines
          vs <= '1' when vert_scan(9 downto 1) = "000000000" else '0';

          rgb <= color when (vert_scan >= posy and vert_scan < (posy+50) and horz_scan >= posx and horz_scan < posx+50) or (vert_scan >= posy2 and vert_scan < (posy2+50) and horz_scan >= posx2 and horz_scan < (posx2+50)) else "000";
          vinc_flag <= '1' when horz_scan = "1100011000" else '0';

        end Behavioral;

1 个答案:

答案 0 :(得分:2)

您的代码中似乎存在复制和粘贴错误。最后两个进程分别对posx2posy2敏感,但您似乎正在更改第一个球的状态(dxdy)。你不应该改变dx2dy2吗?

此外,以下两条建议可让您的代码更具可读性:

  • 不是将计数器声明为std_logic_vectors并将它们与位串文字(例如if vert_scan2 = "1000001001" then ...)进行比较,为什么不将计数器声明为整数?这将有助于使您的代码更具可读性。

  • 不要在整个代码中使用“幻数”或硬编码文字(例如,在表达式if posx = 144 then ...中, 144 是一个幻数)。相反,使用有意义的名称(constant BALL_X_POS_MIN: integer := 144;)创建一个常量,并在表达式(if posx = BALL_X_POS_MIN then ...)中使用它。