2017-04-25 14 views
0

私は現在Spartan3eのvhdlでスネークゲームを実装しています。Vhdl Snake - テールの実装を自動化する方法

私は既にVGAスクリーン上にセルの正方形を描き、正方形の周りを動かすことを可能にする部品を書いています。

問題は尾の実装です - これまで私のヘビに別のセルセグメントを手動で追加しましたが、自動化したいと思います(たとえば、Javaの場合は単にセルのキューを作成して次の前のセルとしてのセル)。私はvhdlのような複雑な関数を書く方法を知らない。

begin 
    process (clk, reset, endOfGame) 
    begin 
     if reset='1' or endOfGame=true then 

     ball_y_reg <= to_unsigned(231,10); 
     ball_x_reg <= to_unsigned(311,10); 
     ball_x_reg_cell<=to_unsigned(231,10); 
     ball_y_reg_cell<=to_unsigned(311,10); 
-- velocity after reset schould be none 
     x_delta_reg <= ("0000000000"); 
     y_delta_reg <= ("0000000000"); 


     elsif (clk'event and clk='1') then 
     ball_x_reg_cell<=ball_x_next_cell; 
     ball_y_reg_cell<=ball_y_next_cell; 
     ball_x_reg <= ball_x_next; 
     ball_y_reg <= ball_y_next; 
     x_delta_reg <= x_delta_next; 
     y_delta_reg <= y_delta_next; 
     end if; 
    end process; 

    pix_x <= unsigned(pixel_x); 
    pix_y <= unsigned(pixel_y); 

    -- refr_tick: 1-clock tick asserted at start of v-sync 
    -- i.e., when the screen is refreshed (60 Hz) 
    refr_tick <= '1' when (pix_y=481) and (pix_x=0) else 
       '0'; 

    ---------------------------------------------- 
    -- pixel within wall 
    wall_on <= 
     '1' when ((WALL_X_LEFTSIDE_L<=pix_x) and (pix_x<=WALL_X_LEFTSIDE_R)) or ((WALL_X_RIGHTSIDE_L<=pix_x) and (pix_x<=WALL_X_RIGHTSIDE_R)) or ((WALL_Y_UPSIDE_U<=pix_y) and (pix_y<=WALL_Y_UPSIDE_D)) or ((WALL_Y_DOWNSIDE_U<=pix_y) and (pix_y<=WALL_Y_DOWNSIDE_D)) else 
     '0'; 
    -- wall rgb output 
    wall_rgb <= "001"; -- blue 



    ---------------------------------------------- 

    -- square ball 

    ball_x_l <= ball_x_reg; 
    ball_y_t <= ball_y_reg; 
    ball_x_r <= ball_x_l + BALL_SIZE - 1; 
    ball_y_b <= ball_y_t + BALL_SIZE - 1; 

    ball_x_l_cell <= ball_x_reg_cell; 
    ball_y_t_cell <= ball_y_reg_cell; 
    ball_x_r_cell <= ball_x_l_cell + BALL_SIZE - 1; 
    ball_y_b_cell <= ball_y_t_cell + BALL_SIZE - 1; 


    --tail 


    -- pixel within squared ball 
    sq_ball_on <= 
     '1' when ((ball_x_l<=pix_x) and (pix_x<=ball_x_r) and 
       (ball_y_t<=pix_y) and (pix_y<=ball_y_b)) 
       or 
       ((ball_x_l_cell<=pix_x) and (pix_x<=ball_x_r_cell) and 
       (ball_y_t_cell<=pix_y) and (pix_y<=ball_y_b_cell)) 
       else 
     '0'; 

    ball_x_next <= ball_x_reg + x_delta_reg 
        when refr_tick='1' else 
        ball_x_reg ; 
    ball_y_next <= ball_y_reg + y_delta_reg 
        when refr_tick='1' else 
        ball_y_reg ; 

    ball_x_next_cell <= ball_x_reg - BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_RIGHT 
        else ball_x_reg + BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_LEFT 
        else ball_x_reg when refr_tick='1' 
        else ball_x_reg_cell; 

    ball_y_next_cell <=  ball_y_reg - BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_UP 
         else ball_y_reg + BALL_SIZE when refr_tick='1' and CURRENT_DIRECTION = DIR_DOWN 
         else ball_y_reg when refr_tick='1' 
         else ball_y_reg_cell; 

    -- new bar y-position 
    process(ball_y_reg, ball_y_b, ball_y_t, refr_tick, btn, ball_x_reg ,ball_x_r, ball_x_l, x_delta_reg, y_delta_reg) 
    begin 
     x_delta_next <= x_delta_reg; 
     y_delta_next <= y_delta_reg; 


     if refr_tick='1' then 
     if btn(1)='1' and ball_y_b<(MAX_Y-1-BALL_SIZE) then 
      if CURRENT_DIRECTION /= DIR_UP then 

       CURRENT_DIRECTION <= DIR_DOWN; 
       y_delta_next <= BALL_V_P; -- move down 
       x_delta_next <= (others=>'0'); 

      end if; 
     elsif btn(0)='1' and ball_y_t > BALL_SIZE then 
      if CURRENT_DIRECTION /= DIR_DOWN then 

       CURRENT_DIRECTION <= DIR_UP; 
       y_delta_next <= BALL_V_N; -- move up 
       x_delta_next <= (others=>'0'); 

      end if; 
     elsif btn(2)='1' and ball_x_r<(MAX_X-1-BALL_SIZE) then 
      if CURRENT_DIRECTION /= DIR_LEFT then 

       CURRENT_DIRECTION <= DIR_RIGHT; 
       x_delta_next <= BALL_V_P; 
       y_delta_next <= (others=>'0'); 

      end if; 
     elsif btn(3)='1' and ball_x_l > BALL_SIZE then 
      if CURRENT_DIRECTION /= DIR_RIGHT then 

       CURRENT_DIRECTION <= DIR_LEFT; 
       x_delta_next <= BALL_V_N; 
       y_delta_next <= (others=>'0'); 

      end if; 
     end if; 

     if ball_x_l < WALL_X_LEFTSIDE_R or ball_y_t < WALL_Y_UPSIDE_D or ball_y_b > WALL_Y_DOWNSIDE_U or ball_x_r > WALL_X_RIGHTSIDE_L then 
     endOfGame <= true; 
     CURRENT_DIRECTION <= IDLE; 
     else 
     endOfGame <= false; 
     end if; 

     end if; 
    end process; 

"ボールのx次のセル" の部分は手動で追加された第二のセル:

は、ここに私のコードです。

私は類似の問題を含むトピックを検索していますが、vhdlではそれをカバーしていません。

ありがとうございました!

答えて

2

問題はVHDLではありません - VHDLとJavaの言語の違いに迷うことはありません - これらはここでは簡単です。

問題は合成性です。ハードウェアで表現できる概念的な設計が必要です。

Java実装でキューを使用しているとします。これはリンクされたリストに基づいており、ノード(セグメント)は動的に割り当てられ、ポインタで参照されます。実際には、アクセス・タイプ、新規および割り振り解除などを使用して、それを直接VHDLに変換することができます。 Javaで便利なライブラリ(クラス)が存在するのに対し、詳細は自分で実装する必要があります。しかし、それは単なる詳細です。

道路というダウン行ってはいけない -

...あなたが正常に動作しているシステムにハードウェアのチャンクを生成し、自由にすることはできません(しかし、あなたが行う可能性があります - アクセスの種類、特に動的な割り当てが合成可能ではありません合成可能なバージョンと並行して、既存のSnakeをシミュレータで実行して、その結果を比較し、合成可能なものがすでに証明されているソフトウェアバージョンと一致することを確認したい場合。安全なクリティカルな要件が必要な場合は、この手順が必要です)。

物理的に実現可能なものを知ることに基づいて、ハードウェア設計には異なる考え方が必要です。概念をそれに変換します。

代わりに、システムが起動する前に蛇セグメントを実装する方法を検討し、必要なときにのみ蛇セグメントをオンにする必要があります。次に、システムの起動前に必要な数だけ作成する方法を検討してください。

例えば、セグメントはその色とX/Y座標を知る必要があり、他のものはオン/可視です。あなたはそれをどのように表していますか?

ゲームをプレイして50セグメントに達した場合、ゲームに勝つには十分であると決めるかもしれません。

今や、レコードと固定サイズの配列は完全に合成可能です。

これは、あなたを始められるかもしれません...

+0

クイックアンサーに感謝します!私はVHDL言語の制限を認識していますが、私は実装のヒントについて尋ねています。私は、カレイドと次の位置、方向、可視性を含むレコードの配列を使用しなければならないことを知っています。質問は、どのように私は現在、私の1つのセル(セグメント)と同じように、レコードの配列を並列ステートメントとして繰り返すことができるかです。私は私が直面しなければならないアニメーションのためにそのような操作をする必要があります。 –

+0

あなたのパフォーマンスのニーズによって異なります。単純なループは、単一クロックサイクルでアレイの範囲を反復することができますが、アレイがBlockRamとして実装されるのを妨げ、HUGEハードウェアを生成する可能性があります。あなたはおそらく状態マシンを見ており、クロックサイクルごとに1つのセルを反復しています。それはあなたの正確な要件に依存します。 –

関連する問題