FOMU VGA

FOMU로 최면을 거는 듯한 그래픽 생성하기

0단계: 개발 툴체인 설치

FOMU 관련 안내는 여기를 참고하십시오.

1단계: FOMU에 전선 이식하기

FOMU에는 FPGA 핀 E4, D5, E5, F5에 연결된 네 개의 패드 user_1,...,user_4가 있습니다. 이 패드들을 사용하여 HSync와 VSync VGA 신호에 더해 2비트의 색상 데이터를 생성할 수 있습니다. 그림에 보이는 것처럼 각 패드에 전선을 하나씩 납땜하고, 접지에도 전선을 하나 납땜해야 합니다(총 다섯 개의 전선). 제가 해 보니 심선이 하나인 단단한 전선이 납땜하기 더 쉬웠습니다. FOMU가 무언가에 단단히 고정되어 있는지 확인하고(저는 "제3의 손"을 사용합니다), 심호흡을 하십시오. 모든 것이 잘될 것이며, 여러분은 분명히 해낼 수 있습니다(아마 저보다 더 깔끔한 결과물이 나올 것입니다)! 그런 다음 돋보기로 단락이 없는지 확인하십시오.

2단계: VGA 커넥터

그림에 보이는 것처럼 VGA 커넥터에 연결하십시오.

여기서는 연결이 간편한 VGA 커넥터를 사용하고 있지만, 대신 오래된 VGA 케이블을 하나 희생하고 도통 테스터로 어떤 전선이 어떤 핀에 연결되어 있는지 찾아낼 수도 있습니다. 또한 여기서는 저항 사다리로 4단계 그레이스케일을 생성하는 것(다음에 다룰 예정입니다)과 같은 다른 실험을 위해 브레드보드도 사용하고 있습니다.

3단계: FOMU를 컴퓨터에 연결하기

쉽게 꽂고 뺄 수 있도록 USB 연장 케이블을 사용하고 있습니다. FOMU에 플라스틱 덮개를 씌우고 USB 연장 케이블에 조심스럽게 꽂으십시오. 그런 다음 USB 연장 케이블의 다른 쪽 끝을 컴퓨터에 연결하십시오. 정상이라면 FOMU의 LED가 천천히 깜빡일 것입니다.

이제 화면을 VGA 커넥터에 연결할 수 있습니다.

4단계: 프로그래밍

$ cd learn-fpga/Basic/FOMU/FOMU_VGA
$ ./make_it.sh

모든 것이 잘되면 최면을 거는 듯한 원들과 스크롤되는 회로처럼 보이는 무언가가 화면에 표시됩니다.

5단계: 동작 원리 / 프로그램 가지고 놀기

이제 직접 설계를 작성할 차례입니다. 이를 위해 vga.v를 수정하고 ./make_it.sh로 설계를 합성하여 장치로 전송할 수 있습니다. 다만 알아 두어야 할 점이 있습니다. FOMU를 다시 프로그래밍하기 전에 FOMU를 뽑았다가 다시 꽂아 DFU 모드로 리셋되도록 해야 합니다.

vga.v를 살펴봅시다. 먼저 모듈의 인터페이스입니다.

module vga (
   input  clki,     // ->48 Mhz clock input
   output rgb0,     // \
   output rgb1,     //  >LED
   output rgb2,     // /
   output user_1,   // ->hsync
   output user_2,   // ->vsync
   output user_3,   // ->color0
   output user_4,   // ->color1
   output usb_dp,   // \
   output usb_dn,   //  >USB pins (should be driven low if not used)
   output usb_dp_pu // /
   );
   

여기에는 48 MHz 클록 clki, VGA 신호를 생성하는 데 사용할 네 개의 패드 user_1,...user_4, 멀티컬러 LED를 제어하는 세 개의 선, 그리고 사용하지 않을 경우 0으로 설정해야 하는 USB용 세 개의 선이 있습니다.

파일의 다음 부분은 VGA 생성기입니다. 저는 세 가지 모드(640x480, 1024x768, 1280x1024)를 구현했습니다. 각 모드는 몇 가지 파라미터를 정의합니다.

픽셀 라인 하나가 끝날 때마다 블랭킹 구간(수평 프런트 포치)이 있고, 이어서 hsync 신호의 펄스, 그다음 또 다른 블랭킹 구간(수평 백 포치)이 옵니다. 프레임 하나가 끝날 때마다 같은 일이 일어납니다(수직 프런트 포치, vsync 펄스, 그다음 수직 백 포치). 프런트/백 포치와 동기 펄스의 폭은 모두 '픽셀' 단위로 주어집니다. 참고: 일부 저자는 각 픽셀 행을 백 포치로 시작하고, 이어서 픽셀 데이터, 프런트 포치와 동기 순으로 배치하는데, 저는 이 방식이 덜 자연스럽다고 생각합니다. 타이밍은 표준으로 정해져 있으며, 예를 들어 여기에서 찾을 수 있습니다. 픽셀 클록을 생성하려면 FOMU의 48 MHz 클록을 다른 주파수(예를 들어 640x480의 경우 25 MHz)로 변환해야 합니다. 이 변환은 특수한 FPGA 프리미티브가 수행합니다(FOMU가 사용하는 ICE40UP5k의 경우 SB_PLL40_CORE). 올바른 파라미터를 찾으려면 icepll 유틸리티를 사용하면 됩니다. 예를 들어 640x480의 경우 25.175 MHz 픽셀 클록이 필요하며, icepll -i 48 -o 25.175를 실행하면 SB_PLL40_CORE를 구성하는 데 필요한 파라미터를 얻을 수 있습니다.

다음으로 VGA 생성기의 범용 부분이 있으며, 이 부분은 화면의 모든 VGA_X, VGA_Y 위치를 스캔합니다. 실제로는 화면보다 넓은 영역을 스캔합니다. 화면 바깥 영역은 hsync 및 vsync 신호에 해당합니다. 이 영역은 그림에 그려진 사각형 전체이며, 수평/수직 프런트 포치, 동기, 백 포치를 모두 포함합니다. VGA_DrawArea 신호는 현재 화면 안에 있는지(1), 아니면 동기 신호를 생성하는 중인지(0)를 알려 줍니다. 애니메이션을 표시하는 데 사용하는 VGA_Frame 카운터도 있습니다. 마지막으로, 현재 픽셀의 색상을 저장하는 2비트 out_color 레지스터가 있습니다(R, G, B 중 와이어 두 개만 사용할 수 있다는 점을 기억하십시오).

그다음에는 실제 그래픽 효과를 계산하는 코드가 있습니다. 두 가지 효과가 구현되어 있습니다. 움직이는 동심원과 XOR-모듈로 "외계인 아트"입니다.

마지막으로, IO 핀에 연결된 플립플롭을 사용하는 특수한 SB_IO 블록 네 개로 이루어진 벡터가 있습니다:

   SB_IO #(
      .PIN_TYPE(5'b0101_00) // 0101: latched output  00: no input
   ) user_IO[3:0] (         // Yes, in Verilog you can declare 4 pins in 1 decl
       .PACKAGE_PIN({user_1,user_2,user_3,user_4}),
       .D_OUT_0({VGA_hSync, VGA_vSync, VGA_DrawArea ? out_color : 2'b00}),
       .OUTPUT_CLK({4{pixel_clk}})
   );

이 벡터는 VGA 신호가 제대로 동기화되도록 보장합니다. 이것이 없어도 설계는 640x480에서 대체로 동작하지만, 더 높은 해상도에서는 글리치가 많이 발생합니다. 이 글리치는 생성된 네 신호 사이의 전파 지연에 존재하는 미세한 차이 때문에 발생합니다. IO 핀 드라이버에 내장된 플립플롭을 사용하면 신호의 안정성과 이미지 품질이 크게 향상됩니다.