Ben Eater의 원리를 따른 FPGA 상 VGA 그래픽 카드 구현
HDL에 익숙한 개발자들은 Turing Complete 시뮬레이션에서 실제 하드웨어 구현으로의 전환을 높이 평가할 것입니다. Ben Eater의 이산 논리 비디오 강의 아이디어를 바탕으로 이 프로젝트는 FPGA에 간단한 그래픽 카드를 구축합니다. 15,000개의 로직 요소를 가진 Altera EP4CE15F23C8N 칩을 사용하며, 표준 800x600@60Hz 타이밍을 통해 VGA에 연결됩니다. 50 MHz 시스템 클럭을 5로 나누어 10 MHz를 생성하며, 원본 프로젝트와 맞춥니다.
ClockDivider 모듈이 클럭 분주를 처리합니다:
module ClockDivider
(
input wire clk,
output reg clk_out
);
reg [2:0] DATA;
always @(posedge clk)
begin
if(DATA == 3'd4)
begin
DATA <= 3'd0;
clk_out <= 1'd1;
end
else
begin
clk_out <= 1'd0;
DATA <= DATA + 1'd1;
end
end
endmodule
FPGA 개발을 위한 Verilog 특징
Verilog는 병렬 실행으로 인해 명령형 언어와 차별화됩니다. 변수는 상태를 유지하는 reg와 저장 기능 없는 단순 wire 두 가지로 나뉩니다. 대입 연산자는 서로 다른 하드웨어 회로를 생성합니다:
- assign은 조합 논리를 위한 것:
wire a,b,c;
assign c = a & b;
- always @(...) = (블로킹)은 블록 내 순차 실행을 위한 것.
- always @(posedge clk) <= (논블로킹)은 클럭드 레지스터를 위한 것:
reg A;
always @(posedge clk)
begin
A <= ~A;
end
모듈 파라미터는 #()를 사용해 기본값과 함께 정의되며, 인스턴스화 시 이름으로 전달됩니다. 전처리기 문제로 `define 지시어는 권장되지 않습니다.
VGA 타이밍을 위한 카운터
수평 카운터는 한 줄의 픽셀을 추적합니다:
module HorizontalCounter
#(
parameter ENDSTRING = 0
)
(
input wire clk,
output reg [8:0] DATA
);
always @(posedge clk )
begin
if(DATA == ENDSTRING) DATA <= 9'd0;
else DATA <= DATA + 1'd1;
end
endmodule
수직 카운터는 각 줄 끝에서 증가합니다:
module VerticalCounter
#(
parameter ENDFRAME = 0,
parameter ENDSTRING = 0
)
(
input wire clk,
input reg [8:0] Hor_count,
output reg [10:0] DATA
);
always @(posedge clk )
begin
if(DATA == ENDFRAME) DATA <= 11'd0;
else if (Hor_count == ENDSTRING) DATA <= DATA + 1'd1;
end
endmodu
Hsync, Vsync, Hblank, Vblank 등의 신호는 tinyvga.com의 타이밍에 기반해 단언되며 (H_count와 V_count의 case 문에서 front 및 back porch 값이 지정됩니다).
비디오 데이터 생성
가시 영역은 100x75 픽셀 해상도에 2비트 컬러 깊이(RGB 채널당 4레벨, 6비트로 패킹)를 가집니다. 이미지는 Photoshop에서 준비합니다: 100x75로 리사이즈, 사용자 팔레트(0x00/0x55/0xaa/0xff)로 Indexed Color 변환 후 8비트 BMP로 내보내기.
C++ 유틸리티가 BMP를 Verilog 메모리 배열 mem[]로 변환합니다:
#include <windows.h>
#include <iostream>
// ... (full code parsera BMP with SetPixCollor for mappinga palitry in 6-bitnye values)
SetPixCollor 함수가 RGB 값을 비트(R2R1 G2G1 B2B1)로 인코딩합니다. 출력 mem_block.txt가 FPGA ROM으로 로드되며, Hor_count[6:0]과 V_count[6:0]으로 어드레싱됩니다.
- BMP 로드하고 헤더 검증 (bfType=0x4D42, biBitCount=8).
- RGBQUAD[256] 팔레트 읽기.
- 픽셀 파싱하고 6비트 값으로 매핑.
- Verilog 코드와 ASCII 시각화 생성.
통합 및 디버깅
Quartus Prime에서 어셈블리: ENDSTRING=799, ENDFRAME=624 등의 파라미터로 모듈 인스턴스화. 안정적 동작을 위해 USB Blaster에 커스텀 펌웨어가 필요합니다. Quartus 시뮬레이터가 전통 디버거 역할을 하며, clk_out, H_count, RGB 등의 신호 오실로그램을 보여줍니다.
주요 포인트:
- 레지스터 작업 시 Verilog의 병렬성은 논블로킹 대입을 요구합니다.
- VGA 타이밍이 핵심: 800x600@60Hz를 위한 10 MHz 픽셀 클럭.
- 2비트 컬러로 ROM을 단순화(7500x6 비트)하면서 그래데이션 유지.
- FPGA 설정이 경제적: 최소 보드(추가 부품 없음) + 표준 VGA 케이블.
- 디버깅은 시뮬레이션에서 완전히 이뤄져 런타임 문제를 피합니다.
— Editorial Team
아직 댓글이 없습니다.