
모토로라 68000을 탑재한 자작 컴퓨터가 PCI 버스를 지원한다. 제작자는 10MHz CPU와 FPGA 브리지를 연결해 PCI 카드의 설정 공간을 읽고 쓰는 기능부터 직렬 통신·그래픽·네트워킹까지 구현했다. 다만 버스 마스터링과 DMA는 지원하지 않아 DMA가 필요한 카드는 작동하지 않는다.
완성된 보드에는 1MB SRAM, 4KB ROM, UART·타이머·I/O를 맡는 MC68681P, 5V PCI 슬롯 두 개가 있다. PCI 브리지는 Xilinx Spartan II FPGA(XC2S100)가 맡고, XC95144XL CPLD는 주변 회로의 제어 논리를 처리한다. 슬롯은 인터럽트를 지원하지만 버스 마스터링은 지원하지 않는다. 제작자는 현재 작동하며 사용할 수 있는 상태라고 설명했다.
회로도는 PDF, 소스 코드는 GitHub 저장소에서 확인할 수 있다.
PCI를 배우기 위한 실험
제작자는 이전 M8SBC-486을 개발할 때 VLB와 PCI를 추가하라는 제안을 받았지만, 당시에는 기본 보드 기능에 집중해 이를 미뤘다. VLB는 486 버스를 슬롯으로 연결하는 방식인 반면 PCI는 CPU의 버스 사이클을 PCI 사이클로 바꾸는 브리지가 필요하다. 버스 마스터링을 통한 메모리 직접 접근(DMA)도 가능해 전기적·소프트웨어적으로 구현이 더 복잡하다.
2026년 중반 무렵 M8SBC-486의 개발에 흥미가 줄고, 하드웨어 한계 때문에 진척도 느려지자 PCI를 활용할 다음 프로젝트를 구상했다. PCI 카드가 제공하는 다양한 확장 기능을 직접 써보고 싶었지만, 온라인 글 몇 편만 읽어서는 버스 구현을 이해하기 어렵다고 판단했다. Mindshare Inc.가 출간한 《PCI System Architecture》를 읽으며 기본 구조와 타이밍을 익혔다.
실습용으로는 PCI 버스에 직접 연결되는 Xilinx Spartan 2 FPGA(XC2S100)가 장착된 구형 전용 PCI 카드를 골랐다. 학교 선생님에게 고철로 받은 카드였고, 회로도와 핀 배치 정보가 없어 한 장을 참고해 역설계했다. 열풍기로 부품을 떼어내고 PCB를 스캔한 뒤, 2층 기판의 배선을 추적해 KiCad 회로도를 만들었다. 약 3~4일이 걸렸으며, 나중에 일부 배선을 연결하지 않은 부분을 발견해 수정했다. 이 카드의 FPGA는 5V 신호를 견딜 수 있어 5V PCI 환경에서 쓸 수 있었다.
제작자는 VHDL로 기본 PCI 카드도 만들었다. PCI 설정 공간 읽기·쓰기, 시스템에서 카드가 식별되게 하는 기본 레지스터, 64바이트 내부 RAM과 이를 위한 메모리 BAR, 내부 RAM을 대상으로 하는 읽기·쓰기 및 버스트 전송을 구현했다. 첫 번째 기록 바이트를 출력 레지스터처럼 사용해 핀에 연결한 LED를 깜박이게 했고, Linux 테스트 드라이버로 카드 메모리와 출력을 확인했다. 이 실험으로 설정 읽기 명령과 응답, BAR 할당 등 PCI의 기초를 익혔다.
버스와 보드 설계
PCI는 CPU와 독립적으로 동작하는 프로세서 비종속 버스다. 기본형은 32비트이며 주소와 데이터 핀을 AD 신호로 다중화해 커넥터 핀 수를 줄인다. 기본 32비트·33MHz 버스의 이론상 전송률은 132MB/s다. 64비트 확장에서는 264MB/s, 일부 환경에서 66MHz로 동작하면 528MB/s가 된다. 주소를 한 번 제시한 뒤 같은 사이클에서 여러 데이터를 보내는 버스트 전송도 규정한다.
PCI는 기본적으로 33MHz로 동작하지만 더 낮은 주파수로 줄이거나 멈출 수 있으며, 사양상 kHz 범위에서도 동작할 수 있다. 신호는 클록 상승 에지에 동기화된다. 5V와 3.3V 신호 환경이 있으며 슬롯과 카드의 키 구조로 구분한다. 양쪽 슬롯에서 쓸 수 있는 유니버설 카드도 있다. PCI의 반사파 스위칭은 신호 반사를 활용해 종단 저항을 줄이는 방식이지만, 기판과 신호 구동부를 세심하게 설계해야 한다. 이 보드의 PCI 클록은 33MHz보다 낮아 신호 품질 문제는 상대적으로 크지 않았다고 제작자는 설명했다.
버스 마스터링에서는 PCI 장치가 버스 접근을 요청하고 중재기가 허용하면 장치가 버스 신호를 제어한다. 이때 장치는 시스템 메모리나 다른 PCI 장치에 접근할 수 있다. 그러나 이번 설계는 DMA를 구현하지 않았다. PCI는 주소·데이터 핀과 명령·바이트 활성화 핀을 다중화하며, 각 전송은 시작·진행·종료 조건을 주고받는 핸드셰이크를 따른다. 읽기 전송에는 주소 단계 뒤 방향 전환을 위한 대기 상태가 하나 있다. 대상을 찾지 못하면 Master Abort가 발생하고, 버스트를 지원하지 않는 대상은 STOP#으로 전송을 중단할 수 있다. 설명에는 대기 상태, 타임아웃, 중재 등 생략된 내용도 있다.
소프트웨어에서 PCI는 설정 공간, 메모리 공간, I/O 공간으로 나뉜다. 각 카드에는 식별 정보와 기능·요구 사항을 담는 256바이트 설정 공간이 있다. BAR(Base Address Register)는 카드가 필요로 하는 메모리 또는 I/O 공간의 종류와 크기를 알리고, 시스템이 카드에 주소를 할당할 때 사용한다. 카드 하나는 최대 6개의 BAR 블록을 요청할 수 있다. PCI는 리틀엔디안이지만 모토로라 68000은 빅엔디안이므로, 큰 값의 바이트 순서를 보존할지 주소별 바이트 위치를 보존할지 선택해야 한다. 제작자는 레지스터 접근에는 값 보존 방식을, 문자열이나 프레임버퍼처럼 연속된 바이트 배열에는 주소 보존 방식을 썼다.
각 슬롯에는 INTA#부터 INTD#까지 인터럽트 핀이 네 개 있다. PCI 장치는 최대 여덟 개의 기능으로 나뉠 수 있고, 각 기능은 별도의 설정 공간과 레지스터를 가진다. 인터럽트는 여러 장치가 공유할 수 있으며, 단일 기능 장치는 INTA#를 사용한다. PCI의 기본 정보는 Wikipedia의 PCI 문서, OSDev.org의 PCI 문서, PCI 신호 설명, PCI 명령 설명에서 더 볼 수 있다.
프로젝트 아이디어는 고철 부품에서 나왔다. 제작자는 친구 Shadowdestroyer777에게 모토로라 68000 산업용 보드와 부품용 구형 Socket 7 메인보드 두 장을 받았다. 보드에서 CPU와 PCI 슬롯 등을 떼어 프로토타입 기판에 배치하다가, 68000 컴퓨터에 PCI를 달겠다는 생각을 떠올렸다. 기판 크기는 12×18cm였다.
부품은 MC68000P10 CPU, XC95144XL CPLD, 512KB SRAM 두 개, 2KB Xicor X2816C EEPROM 두 개, MC68681P DUART, IDE 인터페이스용 74245·74244 버퍼와 7405 인버터, PCI 슬롯 두 개 및 XC2S100 FPGA였다. FPGA 설정 비트스트림을 불러오기 위해 ATmega128도 나중에 추가했다. 처음에는 10MHz 발진기를 CPU와 PCI에 함께 쓰려 했지만 발진기가 고장 나 20MHz 발진기와 74163 카운터로 주파수를 절반으로 나눴다.
기판에는 QFP-100 CPLD와 QFP-144 FPGA, SOP 패키지 SRAM을 어댑터 없이 실장해야 했다. 제작자는 과거 FPGA 실험에서 144핀 칩에 얇은 에나멜선을 직접 납땜한 경험을 활용했다. PCI 슬롯은 핀 간격이 번갈아 1.27mm씩 어긋나 있어 핀을 구부려 2.54mm 간격에 맞췄다. 부품을 배치하는 데도 예상보다 시간이 걸려 일부 SMD 부품은 기판 뒷면에 놓였다. 배선에는 이전 486 자작 컴퓨터에서 쓴 에나멜선을 사용했고, 절연 균열로 단락되지 않도록 납땜 전에 선을 검사했다.
보드는 5V 전원으로 동작하지만 CPLD 코어에는 3.3V, FPGA 코어에는 2.5V가 필요하고 PCI에도 3.3V 전원이 필요했다. 제작자는 LM1117 조정기를 사용해 CPLD 전용 3.3V, FPGA I/O와 PCI용 3.3V, FPGA 코어용 2.5V를 만들었다. 이전 68000 보드의 리셋 회로와 DUART도 재사용했다. 이번에는 CPLD를 다시 프로그래밍할 수 있다는 점을 활용해 인터럽트도 설계에 포함했다.
CPU 구동과 프로그램 적재
전원 회로와 커패시터를 연결한 뒤 JTAG 데이지 체인에서 CPLD와 FPGA가 모두 처음부터 인식됐다. CPU와 RAM·ROM·CPLD를 연결하고 초기 논리를 작성해 68000이 ROM에서 명령을 읽는지 확인했다. 메모리 맵은 RAM이 0x000000~0x0FFFFF, ROM이 0x100000~0x100FFF, DUART가 0x200000~0x200FFF, IDE가 0x300000~0x300FFF, PCI가 0x800000~0xFFFFFF였다.
68000은 주소 공간의 시작에서 초기 벡터를 읽는다. 이에 따라 리셋 직후에는 ROM을 RAM 주소에 겹쳐 놓고, 실제 ROM 주소에 접근하면 CPLD가 겹침을 해제하는 오버레이를 구현했다. 처음에는 EEPROM 두 개의 상·하위 바이트를 뒤바꿔 프로그램이 실행되지 않았지만, 이를 수정한 뒤 동작했다. 메모리 테스트와 DUART 테스트도 작성했다. DUART의 R/W 선을 잘못 연결해 동작이 불안정했고, 약 4시간 뒤 배선 오류를 찾아 고쳤다. 이후 터미널에 문자가 출력됐고 DUART 출력 핀의 LED도 깜박였다.
-- ROM overlay over RAM trick to allow start vectors to be at 0x000000
-- After reset detection, we turn on ROM_BYPASS to overlay ROM over RAM
-- As soon as we detect ROM being accessed, we turn off the ROM_BYPASS to allow RAM to be accessed
PROCESS(CLK, RESET_n, ADDR)
VARIABLE ADDR_msb : STD_LOGIC_VECTOR(23 DOWNTO 20);
BEGIN
ADDR_msb := ADDR(23 DOWNTO 20);
IF RESET_n = '0' THEN
ROM_BYPASS <= '1';
ELSE
IF RISING_EDGE(CLK) THEN
IF ADDR_msb /= X"0" AND AS_n = '0' THEN -- AS must be low so we toggle only on valid cycles
ROM_BYPASS <= '0';
END IF;
END IF;
END IF; -- RESET_n = '0'
END PROCESS;
제작자는 Debian 13에서 gcc-m68k-linux-gnu를 설치해 C 프로그램을 빌드했다. 다만 Debian의 Linux용 툴체인은 기본적으로 68020 같은 신형 프로세서를 대상으로 하고, 포함된 libgcc.a가 원래 68000에서 지원하지 않는 32비트 수학 명령을 사용할 수 있다. 내장 라이브러리를 제외하고 필요한 루틴을 수정해 베어메탈 환경에서 사용했다. 제작자는 AI를 이용해 Makefile, 링커 스크립트, 빈 main 함수로 이어지는 부트스트랩 어셈블리를 만들고 libgcc.a 대체 코드도 작성했다고 밝혔다. 전체 프로젝트를 맡기기보다는 시간을 아끼고 확인하는 도구로 썼다고 설명했다. 소스는 GitHub 저장소에 공개돼 있다.
CPLD는 DUART 수신, 타이머, IDE, PCI 인터럽트 요청을 우선순위에 따라 68000의 IPL 핀에 전달한다. DUART는 레벨 4, IDE는 레벨 3, 첫 번째 PCI 슬롯은 레벨 2, 두 번째 슬롯은 레벨 1로 설정했다. 여러 요청이 동시에 오면 우선순위가 높은 DUART부터 처리하고, 해당 인터럽트가 해제된 뒤 IDE 요청을 전달한다. CPU의 인터럽트 확인 사이클은 FC 핀으로 감지하고 VPA를 활성화해 자동 벡터를 사용했다. C에서는 GCC의 인터럽트 속성과 예외 벡터 테이블에 핸들러 주소를 등록해 처리했다.
ROM을 반복해서 다시 쓰지 않도록 직렬 부트로더도 만들었다. 호스트 프로그램은 파일 크기를 먼저 보내고, 프로그램 데이터를 96바이트씩 전송하며 각 묶음 뒤 확인 바이트를 기다린다. 보드는 받은 데이터를 예외 벡터 테이블 바로 뒤인 0x000400에 기록하면서 체크섬을 계산하고, 끝에 결과를 돌려준다. MC68681P의 공식 최고 속도인 38400 보드레이트에서 20KB를 보내는 데 약 6~8초가 걸렸다. 프로그램은 RAM에서 실행되므로 ROM 실행 프로그램과 초기화 코드 및 링커 스크립트가 다르다. 업로드 중에는 보드의 직렬 포트를 점유한다. DUART의 두 번째 채널을 쓸 수도 있었지만 공간이 부족해 프로그램이 UART 입력을 기다린 뒤 실행되도록 했다.
FPGA 브리지와 PCI 카드 시험
CPU와 FPGA 사이의 인터페이스를 만드는 과정에서는 68000 버스가 비동기식이고 CPU가 클록 양쪽 에지에서 신호를 샘플링한다는 점이 까다로웠다. FPGA는 PCI와 설계를 단순화하려고 클록 분주 없이 상승 에지 하나로 동작하게 했다. 68000 버스는 S0부터 S7까지 상태를 거치며, 주소 접근은 S0에서 시작하지만 주소 스트로브가 S2에서 낮아져 FPGA가 이를 S4까지 기다려야 했다. CPU는 S4가 끝날 때 DTACK을 샘플링하므로 무대기 읽기·쓰기를 하려면 짧은 시간 안에 응답해야 했다. 쓰기에서 UDS#/LDS#가 S4 뒤에 내려가므로 S6 전에는 어느 바이트가 쓰이는지 알 수 없는 경우도 있었다. 데이터시트와 타이밍을 분석한 뒤 FPGA에서 CPU로 값을 읽고 쓰는 데 성공했다.
FPGA 핀을 아끼기 위해 슬롯의 IDSEL을 75Ω 저항을 거쳐 AD 버스에 연결했다. 설정 명령의 주소 단계에서는 AD16~31이 사용되지 않으므로 이를 IDSEL로 활용하는 방식이다. 저항은 추가 부하로 인한 신호 저하를 줄이고 IDSEL이 안정될 시간을 준다. FPGA 설정에는 ATmega128을 추가했다. 96KB 비트스트림을 10MHz 68000과 DUART로 비트 단위 전송하는 방식은 너무 느릴 것으로 예상했고, DUART 출력 핀도 병렬 전송에 필요한 9개보다 적었다. ATmega128의 내부 8MHz 발진기와 하드웨어 SPI를 사용해 수백 밀리초 안에 비트스트림을 로드했다. 설정 코드는 M8SBC-486 프로젝트에서 재사용했다.
CPU 메모리 공간의 PCI 영역은 0x800000부터 시작한다. 처음 64KB는 PCI I/O 공간으로 변환해 0x800000 접근이 PCI I/O 주소 0x0000에 해당하게 했다. 그 위의 주소는 PCI 메모리 접근으로 그대로 전달했다. 설정 공간은 0xFFFF00의 CONFIG_ADDRESS와 0xFFFF04의 CONFIG_DATA 레지스터로 접근한다. 주소 레지스터에는 장치와 레지스터 오프셋을 지정하고, 데이터 레지스터를 읽거나 쓰면 설정 트랜잭션이 시작된다. PC의 방식에서 Enable Bit와 Bus Number를 제외했다. 68000의 16비트 데이터 버스에서 32비트 접근은 두 번의 16비트 사이클이므로, FPGA 안에서 이를 합치지 않고 각각 별도의 PCI 전송으로 처리했다. 설정 레지스터에는 값 보존 방식의 바이트 변환을 적용했다. 0xFFFF08의 16비트 CONFIG_MISC 레지스터에는 PCI 리셋 제어 비트를 두어 비트스트림 로드나 전체 리셋 뒤에는 리셋을 유지하고 소프트웨어가 준비되면 해제하게 했다.
설정 읽기·쓰기가 작동한 뒤 Cirrus Logic GD5440 그래픽 카드와 Realtek RTL8169 네트워크 카드 등을 버스에서 확인했다. 여러 네트워크·그래픽·오디오 카드가 검색됐고 PCI-X 광섬유 네트워크 카드도 인식됐다. 일부 카드는 인식되지 않거나 전원 공급 장치의 과전류 차단을 일으켰다. 회로를 살펴본 결과 사용하지 않는 GNT# 핀의 풀업을 빼먹은 것이 원인이었다. 이를 수정하자 해당 카드들도 작동했다.
BAR 크기는 대상 레지스터에 0xFFFFFFFF를 쓰고 값을 읽은 뒤 비트를 반전해 1을 더해 확인했다. 예를 들어 0xFFFFFF00이 돌아오면 256바이트를 요청한 것이다. 메모리 BAR의 하위 4비트는 유형과 프리페치 여부 등의 표시용이어서 최소 할당 크기는 16바이트이고, I/O BAR는 하위 2비트를 사용하므로 최소 4바이트다. BAR에 주소를 할당하고 PCI 명령 레지스터에서 해당 메모리 또는 I/O 접근을 활성화했다.
PCI 메모리 접근은 더블워드 경계에 맞추고 바이트 활성화 신호를 쓰지만, 레거시 I/O는 AD0와 AD1에도 정확한 주소를 제공해야 한다. BAR이 할당되지 않은 레거시 VGA 장치처럼 정렬 규칙을 따르지 않는 카드가 있기 때문이다. FPGA는 68000의 A1과 LDS#/UDS#를 이용해 이 주소 비트를 만들었다. 각 CPU 버스 사이클은 별도의 PCI 전송이며, 버스트 기능은 구현하지 않았다. PCI 상태 기계는 68000의 S6에서 시작한다. IRDY#는 즉시 활성화하고 대상의 TRDY#를 처리하며, FPGA 자체는 대기 상태를 추가하지 않는다. 몇 클록 안에 DEVSEL#이 내려오지 않으면 Master Abort로 판단해 모두 1을 반환한다. 대상 Abort와 재시도는 지원하지 않아 이 경우에도 모두 1을 반환한다. 핵심 PCI 논리를 만드는 데 약 이틀이 걸렸다. 이 메모리·I/O 공간에는 주소 보존 방식을 써서 16·32비트 레지스터의 바이트 순서는 소프트웨어가 바꿔야 하지만, 문자열과 픽셀 배열은 연속된 주소에 그대로 놓인다.
첫 실제 장치로는 Moschip NM9835 직렬 카드를 사용했다. 카드의 첫 I/O BAR를 표준 PC 주소인 0x3F8에 할당하고, 68000 주소에서는 0x8003F8로 접근해 16C550 호환 UART를 초기화했다. 처음에는 출력이 없었지만 카드의 GD75232 직렬 드라이버에 필요한 -12V와 +12V가 없다는 점을 확인했다. 보관 중이던 승압·벅 모듈을 달아 단일 전원에서 ±12V를 만들자 직렬 터미널에 문자가 출력됐다.
PCI 직렬 카드의 인터럽트도 시험했다. 슬롯 하나의 INTA#~INTD#를 함께 묶고 시스템 인터럽트 하나에 연결했으며, 슬롯마다 별도 시스템 인터럽트를 배정했다. 오픈 드레인 방식의 신호에는 풀업 저항을 달았다. CONFIG_MISC의 두 번째 비트를 CPLD의 PCI_GATE에 연결해 소프트웨어에서 PCI 인터럽트를 막거나 허용할 수 있게 했다. 16C550이 문자를 받을 때 인터럽트를 발생시키도록 설정하고, 핸들러가 바이트를 읽어 인터럽트를 해제한 뒤 다시 보내도록 했다. 터미널에서 입력한 문자가 즉시 되돌아오는 것을 확인했다.
그래픽과 네트워크
PCI VGA 카드는 보통 x86 어셈블리로 작성된 Video BIOS(VBIOS)를 실행해 표준 VGA 모드로 초기화한다. 68000에서는 이를 실행할 수 없어, 제작자는 초기화가 비교적 단순하고 문서와 에뮬레이터 자료가 있는 Cirrus Logic GD5440을 골랐다. 카드가 레거시 VGA 모드로 들어가도록 설정하는 잠금 해제 순서는 I/O 쓰기 두 번이었다.
3C4h index 6 (R/W): Unlock ALL Extensions
bit 0-2,4 Writing 12h to this register enables extensions.
Read back 0Fh if locked.
Bits 3,5-7 are ignored on write.
출처는 CIRRUS.TXT다.
pci_outb(0x3C4, 0x06);
pci_outb(0x3C5, 0x12);
레거시 VGA 메모리는 1MB 아래의 0xA0000~0xBFFFF에 있다. 이를 위해 CONFIG_MISC의 비트 3을 추가해 CPU의 0x810000~0x8FFFFF 접근을 PCI의 0x010000~0x0FFFFF로 변환했다. 나머지 0x900000~0xFFFFFF는 그대로 매핑했다. AI를 이용해 표준 VGA 초기화용 C 코드를 만들고 시퀀서, 출력 레지스터, VGA 레지스터 블록, DAC, 글꼴을 설정했다. 그 결과 80×25, 16색 텍스트 모드(03h)에서 “Hello World!”를 출력했다.
68000은 빅엔디안이므로 x86에서 흔히 쓰는 문자·속성 결합 매크로를 그대로 쓰면 VGA가 문자와 속성을 뒤바꿔 표시한다. 제작자는 16비트 값의 바이트 순서가 반대가 되도록 매크로를 고쳤다.
#define VGA_ENTRY(ch, attr) ((uint16_t)(ch) | ((uint16_t)(attr) << 8))
주소 보존 방식에서는 위 식이 문자와 속성을 뒤집는다.
#define VGA_ENTRY(ch, attr) ((uint16_t)(attr) | ((uint16_t)(ch) << 8)) // reverse order
이후 320×200, 256색 그래픽 모드(13h)도 작동했다. 화면을 채우는 데 약 300ms가 걸렸고, 64,000바이트 프레임버퍼를 기준으로 한 약 200KB/s라는 전송률은 화면 녹화에서 추산한 값이다. 제작자는 별도의 성능 측정 코드를 작성하지 않았다고 밝혔다.
소스 코드를 다시 정리해 주변 장치 초기화 코드를 별도 파일로 옮기고, PCI 검색 결과에 따라 등록된 드라이버를 불러오게 했다. 인터럽트 하위 시스템은 공유 인터럽트를 지원하도록 바꿨으며, 드라이버에 PCI 장치 정보와 인터럽트 정보를 전달했다. VGA 카드별 초기화와 일반 VGA 초기화도 분리했다. 추가로 S3 Trio64V2/DX(S3 86C775)는 인터넷에서 찾은 초기화 순서를 이용해 작동시켰다. 정보가 적은 IGS IGA 1680_A는 VBIOS를 역어셈블해 I/O 쓰기를 찾아 80×25 텍스트 모드에서 표시하는 데 성공했지만, 320×200 그래픽 모드에서는 주소 지정이 깨져 완전히 작동시키지는 못했다. 마지막에는 FPGA에 더미 PCI 장치인 호스트 브리지도 추가했다. 다만 PCI 상태 비트를 통한 버스 오류 보고 같은 기능은 구현하지 않았다.
마지막으로 DMA 없이 작동하는 RTL8029 네트워크 카드를 시험했다. RTL8139 같은 다른 카드와 앞서 인식한 Intel PCI-X 광섬유 카드는 DMA를 요구한다. RTL8029는 NE2000 호환 장치에 PCI 인터페이스를 더한 카드여서 I/O BAR 할당과 I/O 접근 활성화로 사용할 수 있었다. 제작자는 AI 에이전트를 이용해 RTL8029 드라이버와 간단한 네트워크 스택을 작성했다. 인터럽트 연결 오류를 직접 수정한 뒤 코드를 올리자 Telnet 명령 제어 서버와 간단한 HTTP 서버가 작동했다고 밝혔다. 이 결과는 개념 검증을 위한 것이며, 제작자는 네트워킹을 깊이 배우는 일은 다음으로 미뤘다.
지원 범위와 제약
현재 브리지는 버스 마스터링과 DMA를 지원하지 않아 CPU가 전송 바이트를 직접 처리한다. 따라서 DMA가 필수인 고급 3D 그래픽 카드와 가속기, 대부분의 PCI 사운드 카드, USB 컨트롤러, TV 캡처 카드, SCSI 컨트롤러, 여러 네트워크 카드는 작동하지 않을 수 있다. 반면 표준 메모리 매핑 I/O나 레거시 포트 I/O를 이용하고 버스 제어권을 가져오지 않는 카드는 사용할 수 있다. PCI IDE 컨트롤러도 PIO 모드로 작동할 수 있다.
PCI 브리지 카드는 검색 결과에 나타나지만, 브리지 뒤쪽 장치에 접근하는 기능은 구현하지 않았다. 이를 지원하려면 FPGA가 Type 1 설정 사이클을 생성하고 소프트웨어가 보조 버스를 열거하도록 확장해야 한다. 제작자는 설계 변경이 필요하다고 설명했으며, 구현 난이도에 대해서는 가능성을 추정했다.
제작자는 이 프로젝트를 PCI 브리지 관점에서 저수준 동작을 배우기 위해 만들었다고 밝혔다. 버스 하드웨어와 VHDL, 드라이버를 공개해 구조와 주소 변환을 살펴보거나 코드 조각을 참고할 수 있도록 했다. 프로토타입 기판만으로 PCI를 완전히 작동시키는 자작 컴퓨터는 처음일 수 있다고 주장하지만, 이는 제작자의 판단이다. 이번 보드는 DMA 지원이 없는 대신 수많은 PCI 카드 가운데 PIO 방식으로 동작하는 장치를 연결할 수 있음을 보여준다. 부품을 보내준 친구 Shadowdestroyer777에게도 감사 인사를 전했다.
부록: 원문 예시
-- Interrupts
PROCESS(UART_IRQ_n, IDE_INTRQ, PCI_INT_S1_n, PCI_INT_S2_n, PCI_INT_EN)
BEGIN
IF UART_IRQ_n = '0' THEN
IPL <= "011"; -- Level 4
ELSIF IDE_INTRQ = '1' THEN
IPL <= "100"; -- Level 3
ELSIF (PCI_INT_S1_n = '0' AND PCI_INT_EN = '1') THEN
IPL <= "101"; -- Level 2
ELSIF (PCI_INT_S2_n = '0' AND PCI_INT_EN = '1') THEN
IPL <= "110"; -- Level 1
ELSE
IPL <= "111"; -- Level 0: none
END IF;
END PROCESS;
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요