2017-04-25 9 views
0

저는 Spartan3e 용 vhdl에서 현재 스네이크 게임을 구현했습니다.Vhdl 스네이크 - 꼬리 구현을 자동화하는 방법

VGA 화면에서 셀 사각형을 그리는 부분을 이미 작성했으며 사각형 주위로 이동할 수 있습니다.

문제는 꼬리 구현입니다. 지금까지 수동으로 다른 셀 세그먼트를 내뱀에 추가했지만 자동화하고 싶습니다 (예 : 자바에서 대기열과 셀을 간단히 만들고 다음 위치의 positiong를 설정하는 경우) 셀을 셀로 사용). 나는 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에서 편리한 라이브러리, 즉 클래스가있을 수 있지만 직접 세부 사항을 구현해야합니다. 그러나 그것은 단순한 세부 사항입니다. 액세스 유형, 특히 동적 할당 synthesisable되지 않습니다 - -

도로가 내려 가지 마세요 당신이 일반적으로 생성하고 실행중인 시스템에 하드웨어의 무료 덩어리 없습니다 ...

(그러나 당신이 할 수있는 시뮬레이터에서 기존 스네이크를 합성 가능 버전과 병행하여 실행하여 결과를 비교하고 이미 입증 된 소프트웨어 버전과 일치하는지 확인하십시오. 군사, 항공 우주 또는 항공기로 설계된 고 신뢰성 스네이크가 필요한 경우 안전 중요 요구 사항을 충족 시키려면이 단계가 필요합니다.)

물리적으로 실현 가능한 것을 알고 있으면 하드웨어 설계에 다른 생각이 필요합니다. 그것을 개념으로 번역하십시오.

대신 시스템을 시작하기 전에 뱀 세그먼트를 구현하는 방법을 고려하고 필요할 때만 켭니다. 그런 다음 시스템을 시작하기 전에 필요한만큼 생성하는 방법을 고려하십시오.

예를 들어 세그먼트에서 색상 및 X/Y 좌표를 알아야 할 수도 있고 다른 것들은 켜기/표시 할 수 있습니다. 어떻게 그 모든 것을 나타낼 수 있습니까?

게임을하고 50 개의 세그먼트에 도달했는지를 결정할 수 있습니다. 100 개이면 게임에서 승리 할 수 ​​있습니다.

이제 레코드와 고정 크기 배열은 절대적으로 합성 가능합니다.

이렇게하면 시작할 수 있습니다 ...

+0

빠른 답변 감사합니다!vhdl 언어의 한계를 알고 있지만 구현 팁을 묻습니다. 내가 currect 및 다음 위치, 방향, 가시성을 포함하는 레코드 배열을 사용해야한다는 것을 알고 있습니다. 문제는 어떻게하면 현재 하나의 셀 (세그먼트)을 사용하여 동시 레코드로 레코드 배열을 반복 할 수 있는가입니다. 나는 내가 직면해야하는 애니메이션으로 그런 조작을 할 필요가있다. –

+0

성능 요구에 따라 다릅니다. 간단한 루프는 단일 클럭 사이클에서 배열의 범위를 반복 할 수 있지만 BlockRam으로 구현되지 않도록하며 거대한 하드웨어를 생성 할 수 있습니다. 아마도 상태 머신을보고 클럭 사이클 당 하나의 셀을 반복합니다. 그것은 당신의 정확한 요구 사항에 달려 있습니다. –