[베릴로그 RTL 예제] 탁구 게임기 -6편: 탁구대, 움직이는 공 그리고 탁구채-
목차:
1. RTL 베릴로그로 "탁구대" 그리기
2. 그래픽 LCD 구동 칩의 시뮬레이션 모델
3. "탁구대"의 그래픽 테스트 벤치
4. 움직이는 탁구공
5. GLCD의 버스 기능 모델
6. 탁구대, 움직이는 공 그리고 탁구채
6-1. "탁구대"와 "움직이는 공" 시현
6-2. "탁구채"
6-3. 대화형 하드웨어 시뮬레이터
6-4. 실습 및 과제
----------------------------------------------------------------------------------------------------------------
오픈-소스 반도체 설계 도구가 설치된 "내 칩 디자인 킷"의 WSL 가상 디스크 이미지 [링크]
----------------------------------------------------------------------------------------------------------------
6. 탁구대, 움직이는 공 그리고 탁구채
알고리즘을 하드웨어로 구현하면서 얻는 가장 큰 장점을 꼽자면 낮은 속도(=긴 주기)의 클럭으로 높은 처리율(스루풋)을 얻을 수 있다는 점이다. 물론 단점 또한 만만치 않다. 장단점에 관하여 따로 논의해보기로 한다. 이에 덧붙여 병렬성은 매우 강력한 개발 수단이다. 소프트웨어에서 구현하기 어려운 병렬 처리를 단숨에 해결할 수 있다.
6-1. "탁구대"와 "움직이는 공" 시현
앞서 영상 데이터 시현을 위해 좌표의 생성을 디지털 카운터로 단숨에 해결 했었다. "탁구대" 그리기는 비교문 하나면 충분 했다. 탁구공을 시현하고 움직이기 위해 다소의 좌표변환(탁구공 이미지 좌표를 화면 좌표계 내로 변환)을 필요로 했지만 그래픽 알고리즘 중에서도 워낙 단순해서 그리 큰 어려움은 없었다. "탁구대"와 "공"을 생성하는 하드웨어는 그래픽 좌표 생성과 GLCD 인터페이스용 FSM을 공유하면서 독립적으로(또는 병렬로) 작동한다. 두 병렬처리 하드웨어에서 생성된 이미지를 한 화면에 합치려면 논리 합 연산 하나로 족하다.
"탁구대"와 "공"을 그리기 위한 화소 값을 각각 pixel_table 과 pixel_ball 로 선언하고 할당 한다.
// Table --------------------------------------------------------
wire pixel_table = ((x_pos>5) && (x_pos<15))? 1:0;
// Ball ---------------------------------------------------------
reg pixel_ball;
always @*
if ((x_ball<=x_pos) && ((x_ball+7)>=x_pos) &&
(y_ball<=y_pos) && ((y_ball+7)>=y_pos))
pixel_ball = rom_data[rom_bit];
else
pixel_ball = 0;
두 화소를 논리 합 연산 만으로 "탁구대"와 "움직이는 공"을 한화면에 시현할 수 있다. 여기에 약간의 기교를 부려 화소의 겹침을 보여주기 위해 배타적 논리합 연산으로 처리하였다.
// Pixel --------------------------------------------------------
assign pixel = pixel_table ^ pixel_ball;
예제를 실행 해보자. 소스 파일의 구성은 이전편에서 다뤘던 구성과 동일하다. 다만 베릴로그의 소스 파일 pong_SbS.v 에 탁구대와 공의 화소 겹침 연산 구문이 추가되었을 뿐이다.
$ cd ~/ETRI050_DesignKit/Projects/RTL/pong_SbS/06_Table_Ball
$ tree
.
├── _Docs_
├── pong_SbS
│ └── pong_SbS.v
└── simulation
├── Makefile
├── sc_glcd128x64_TLM.cpp
├── sc_glcd128x64_TLM.h
├── sc_pong_SbS_TB.cpp
├── sc_pong_SbS_TB.h
└── sc_main.cpp
$ cd simulation
$ make build
$ make run
6-2. 탁구채
탁구 게임기를 구성하는 객체는 "탁구대", "공" 그리고 "채"다. "탁구공"은 내부의 규정(벽 또는 채에 부딪치면 반사)대로 움직이지만 "채"는 외부 버튼의 누름 여부에 따라 상하로 이동해야 한다. 버튼 입력이 추가된 베릴로그 모듈은 다음과 같다.
//
// Filename: pong_SbS.v
//
module pong_SbS(clk,reset,x_pos,y_pos,pixel,p_tick,busy,up,down);
input clk;
input reset;
output [6:0] x_pos;
output [5:0] y_pos;
output pixel;
output p_tick;
input busy;
input up;
input down;
......
endmodule
탁구채의 위치는 6비트 레지스터 paddle 이다. 화면이 갱신 될 때 버튼의 눌림을 탐지하여 채의 위치를 변경한다. 화면이 갱신 된다는 제어신호는 FSM에서 생성되는 v_sync 다.
// Paddle Postion -----------------------------------------------
reg [5:0] paddle;
always @(posedge clk or posedge reset)
begin
if (reset)
paddle <= 0;
else
begin
if (up && paddle > 0 && v_sync)
paddle <= paddle - 1;
if (down && paddle < 44 && v_sync)
paddle <= paddle + 1;
end
end
탁구채의 위치에 맞춰 그려주는 화소 생성 구문은 다음과 같다. 채의 크기는 20으로 잡았다,
// Paddle -------------------------------------------------------
wire pixel_paddle;
assign pixel_paddle = ((x_pos>122) && (y_pos>paddle) && (y_pos<(paddle+20)))? 1:0;
이제 "탁구 게임기"를 구성하는 세 객체를 합쳐 한 화면에 시현되도록 한다.
// Pixel --------------------------------------------------------
assign pixel = (pixel_table ^ pixel_ball) | pixel_paddle;
6-3. 대화형 하드웨어 시뮬레이터
게임기는 플레이어가 누르는 버튼에 따라 동적으로 작동하는 자동기계다. 플레이어가 버튼을 누르는 순간이 예정되어 있지 않다. 대화형 시뮬레이터를 제작하여 규칙에 맞춰 게임이 작동하는지 검증하기 로 한다. 이미 칩으로 제작된 하드웨어는 수정이 불가하다. 따라서 칩이 응용될 실제 상황에 접근된 검증이 이뤄져야 할 것이다. 앞서 SystemC로 작성했던 시현 장치(GLCD)의 시뮬레이션 모델에 키보드 입력을 받아 시험 입력으로 전달하는 스레드를 추가했다. 키보드 입력 스레드가 추가된 시스템 수준 모델의 외형은 다음과 같다.
//
// Filename: sc_glcd128x64_TLM.h
//
#ifndef _SC_GLCD128x64_TLM_H_
#define _SC_GLCD128x64_TLM_H_
#include <systemc.h>
#include <SDL2/SDL.h>
SC_MODULE(sc_glcd128x64_TLM)
{
sc_in<bool> reset;
sc_in<sc_uint<7> > x_pos;
sc_in<sc_uint<6> > y_pos;
sc_in<bool> pixel;
sc_in<bool> p_tick;
sc_out<bool> busy;
sc_out<bool> up;
sc_out<bool> down;
void Display_Thread(void);
void Button_Thread(void);
// SDL2--------------------------
......
SC_CTOR(sc_glcd128x64_TLM)
{
SC_THREAD(Display_Thread);
sensitive << p_tick;
SC_THREAD(Button_Thread);
// SDL2--------------------------
......
}
};
#endif
키보드 입력을 탐지하여 버튼 up 과 down 의 사건으로 출력하는 스레드 함수 Button_Thread()에 사건 감응이 지정될 필요 없다. 사건 감응 없이 일반적인 함수처럼 작동 하도록 기술한 경우 "시스템 수준" 모델이라 한다.
키보드 탐지 스레드 함수 Button_Thread()는 다음과 같다. 게임을 비록하여 멀티미디어 응용프로그램 제작용 오픈소스 라이브러리 SDL(Simple Directmedia Layer)가 사용되었다.
//
// Filename: sc_glcd128x64_TLM.cpp
//
#include <unistd.h>
#include "sc_glcd128x64_TLM.h"
void sc_glcd128x64_TLM::Button_Thread(void)
{
SDL_Event event;
bool quit = false;
up.write(false);
down.write(false);
while(!quit)
{
if (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
quit = true;
break;
case SDL_KEYDOWN:
switch( event.key.keysym.sym )
{
case SDLK_UP:
up.write(true);
break;
case SDLK_DOWN:
down.write(true);
break;
case SDLK_r:
goto EXIT;
break;
default:
break;
}
break;
case SDL_KEYUP:
switch( event.key.keysym.sym )
{
case SDLK_UP:
up.write(false);
break;
case SDLK_DOWN:
down.write(false);
break;
default:
break;
}
break;
default:
break;
}
}
else
wait(100, SC_NS);
}
EXIT:
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
sc_stop();
}
void sc_glcd128x64_TLM::Display_Thread(void)
{
......
}
키보드 눌림 SDL_KEYDOWN 을 탐지하여 윗 화살표 키 SDLK_UP 이면 up 출력에 true를 내보낸다. 아래 화살표 키 SDLK_DOWN 이면 down 출력에 true를 내보낸다. 키보드 뗌 SDL_KEYUP 이 탐지되면 해당 출력에 false 를 내보낸다. SDL의 키보드 사건이 없다면 wait(100, SC_NS)로 쓰레드가 시뮬레이터를 점유하는 시간을 미루고 실행을 양보한다. SystemC의 하드웨어 시뮬레이션 커널은 비 선점형 다중처리(Non-Preemptive Multi-Processing)다.
6-4. 실습 및 과제
예제의 시뮬레이터 빌드와 실행은 모두 make 유틸리티로 수행한다. 소스 파일의 구성은 앞장에서와 동일하다. "탁구채"를 묘사하기 위해 베릴로그와 키보드 입력이 추가된 "시스템수준" 테스트벤치가 변경 되었다.
$ cd ~/ETRI050_DesignKit/Projects/RTL/pong_SbS/07_Table_Ball_Paddle
$ tree
.
├── _Docs_
├── pong_SbS
│ └── pong_SbS.v
└── simulation
├── Makefile
├── sc_glcd128x64_TLM.cpp
├── sc_glcd128x64_TLM.h
├── sc_pong_SbS_TB.cpp
├── sc_pong_SbS_TB.h
└── sc_main.cpp
a. 실습
시뮬레이터를 빌드하고 실행,
$ make build
$ make run
탁구 게임기를 구성하는 세 객체가 모두 시현되는 화면을 보게될 것이다. 키보드 입력에 반응하여 탁구채가 이동한다.
b. 과제
[과제1] 예제의 소스로 보여주는 "탁구 게임기"는 미완성이다. 다양한 게임의 규칙이 적용되도록 베릴로그 설계를 변경해 보자. 예를들어 공이 탁구채의 상단 혹은 하단에 부딪칠 경우 공의 속도가 바뀌면 게임이 한층 재미를 더할 수 있다.
[과제2] "시스템 수준 모델링"을 공부해보자.
구글 인공지능에 "시스템 수준 모델링"을 문의[링크]하면 이렇게 답한다.
"시스템 수준 모델링(System-Level Modeling)은 복잡한 시스템의 구성 요소, 상호작용, 행위를 추상화하여 전체적인 관점에서 기능과 구조를 정의하는 과정입니다. 주로 초기 설계 단계에서 요구사항 분석, 아키텍처 설계, 빠른 시뮬레이션을 통해 시스템의 동작을 검증하고, 시제품 제작 전 비용과 시간을 절감하는 데 목적이 있습니다."
적용 분야로는,
"임베디드 시스템: 하드웨어와 소프트웨어의 통합 동작 검증."
"시스템 아키텍처: 논리적, 물리적 구성을 정의하여 시스템 인터페이스 설계."
위의 인공지능 답변을 근거로 "탁구 게임기"의 테스트벤치가 "시스템 수준"에서 작성된 측면에 대하여 논하라.




















