FPGA 임베디드 디자인 마스터하기: 실전 구현 가이드
더 강력한 FPGA와 더 효과적인 프로그래밍 환경의 등장으로 FPGA 구현이 널리 접근 가능해졌지만, FPGA 사용은 여전히 어렵게 느껴질 수 있습니다.

편집자 주: 스마트 제품 설계를 위한 첨단 알고리즘이 지속적으로 등장함에 따라, 개발자들은 종종 이러한 알고리즘의 관련 처리 요구사항을 충족할 수 있는 임베디드 시스템 구현에 어려움을 겪습니다. FPGA는 필요한 성능을 제공할 수 있지만, FPGA 설계는 오랫동안 FPGA 프로그래밍 전문가의 영역으로 여겨져 왔습니다. 그러나 오늘날 더 강력한 FPGA와 더 효과적인 개발 환경의 등장으로 FPGA 개발이 널리 접근 가능해졌습니다. 이 발췌문에서 Jim Ledin의 저서 'Architecting High-Performance Embedded Systems' 4장에서 저자는 FPGA 디바이스, 구현 언어, FPGA 개발 프로세스에 대한 포괄적인 검토와 함께 FPGA를 자체 설계에 구현하는 방법에 대한 자세한 연습을 제공합니다. 전체 발췌문은 다음 시리즈로 제공됩니다:
- 1: 하드웨어 리소스
- 2: 구현 언어
- 3: 개발 프로세스
- 4: 프로젝트 구축
- 5: 구현 (본 기사)
'Architecting High-Performance Embedded Systems' by Jim Ledin에서 발췌 및 각색.
로직 동작 테스트
FPGA에서 실행하기 전에 시뮬레이션을 사용하여 로직 동작을 테스트하는 것이 중요합니다. 시뮬레이션 환경에서 문제를 감지하고 수정하는 것이 FPGA 내부에서 실행되는 로직보다 훨씬 쉽기 때문입니다. Vivado 시뮬레이션 도구는 회로 동작을 매우 잘 표현합니다:
- Sources 서브 윈도우에서 Simulation Sources를 우클릭하고 Add Sources…를 선택합니다.

그림 4.18 – Simulation Sources에 대한 Add Sources… 메뉴 선택
- Add Sources 대화상자에서 Add or create simulation sources가 선택되었는지 확인하고 Next를 클릭합니다.
- Add or Create Simulation Sources 대화상자에서 Create File을 클릭합니다.
- 파일명으로 vhdl을 입력하고 OK를 클릭합니다.
- Finish를 클릭하여 Add or Create Simulation Sources 대화상자를 닫고, Define Module 대화상자에서 OK를 클릭한 후, 이를 사용할지 묻는 질문에 Yes를 클릭합니다.
- Simulation Sources 아래의 Adder4 TestBench (Behavioral) (Adder4TestBench.vhdl)를 더블클릭합니다. vhdl 편집기 창의 자동 생성된 내용을 삭제하고 다음 코드를 Adder4TestBench.vhdl 편집기에 입력합니다:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity ADDER4_TESTBENCH is end entity ADDER4_TESTBENCH; architecture BEHAVIORAL of ADDER4_TESTBENCH is component ADDER4 is port ( A4 : in std_logic_vector(3 downto 0); B4 : in std_logic_vector(3 downto 0); SUM4 : out std_logic_vector(3 downto 0); C_OUT4 : out std_logic ); end component; signal a : std_logic_vector(3 downto 0); signal b : std_logic_vector(3 downto 0); signal s : std_logic_vector(3 downto 0); signal c_out : std_logic; signal expected_sum5: unsigned(4 downto 0); signal expected_sum4: unsigned(3 downto 0); signal expected_c : std_logic; signal error : std_logic; begin TESTED_DEVICE: ADDER4 port map ( A4 => a, B4 => b, SUM4 => s, C_OUT4 => c_out ); TEST: process begin -- 두 4비트 가수의 모든 조합 테스트 (총 256 테스트) for a_val in 0 to 15 loop for b_val in 0 to 15 loop -- ADDER4 컴포넌트의 입력 설정 a <= std_logic_vector(to_unsigned(a_val, a'length)); b <= std_logic_vector(to_unsigned(b_val, b'length)); wait for 1 ns; -- 두 4비트 값의 5비트 합 계산 expected_sum5 <= unsigned('0' & a) + unsigned('0' & b); wait for 1 ns; -- 합을 4비트 출력과 캐리 비트로 분리 expected_sum4 <= expected_sum5(3 downto 0); expected_c <= expected_sum5(4); wait for 1 ns; -- 'error' 신호는 오류 발생 시에만 1로 설정 if ((unsigned(s) = unsigned(expected_sum4)) and (c_out = expected_c)) then error <= '0'; else error <= '1'; end if; -- 내부 루프의 각 패스는 10ns 소요 wait for 7 ns; end loop; end loop; wait; end process TEST; end architecture BEHAVIORAL;
이 코드는 Adder4 컴포넌트의 A4와 B4 입력에 모든 4비트 숫자 조합(256개)을 제시하여 4비트 가산기 기능을 검증합니다. Adder4 컴포넌트의 SUM4와 C_OUT4 출력을 동일한 입력에 대해 독립적으로 계산된 기대값과 비교합니다. 각 덧셈 연산 후, Adder4 출력이 기대값과 일치하면 error 신호는 0으로, 불일치하면 1로 설정됩니다.
Adder4TestBench.vhdl의 코드는 중첩된 for 루프를 사용하여 테스트 중인 Adder4 컴포넌트에 모든 테스트 입력 조합을 적용하는 방식에서 전통적인 소프트웨어 코드와 유사합니다. 시뮬레이션 모드에서 테스트를 실행하는 코드는 합성 불가능(non-synthesizable)하며, 순수한 하드웨어 로직 회로를 나타내지 않고 for 루프의 반복 실행 같은 전통적인 소프트웨어 같은 연산이 가능합니다.
그러나 물리적 회로와 마찬가지로, 테스트벤치 코드에서 <= 연산자로 값이 할당되는 신호는 이후 표현식에서 같은 순간에 사용할 수 없습니다. 이는 시뮬레이션 환경이 미세한 FPGA 디바이스 내에서도 중요한 실제 전파 지연 효과를 표현하기 때문입니다. 테스트벤치 코드의 세 wait for 1 ns 문은 방금 계산된 신호 값이 전파되어 다음 문에서 사용될 수 있도록 회로 동작을 일시 정지시킵니다. 내부 루프의 마지막 wait for 7 ns 문은 시뮬레이션 루프의 각 반복 결과를 신호 트레이스 디스플레이에서 명확히 볼 수 있도록 하는 일시 정지입니다.
- Simulation Sources 아래의 Adder4 TestBench (Behavioral) (Adder4TestBench.vhdl)을 우클릭하고 Automatic Update and Compile Order를 선택합니다. 이는 시뮬레이션 실행을 위해 ADDER4_TESTBENCH를 최상위 객체로 설정합니다.

그림 4.19 – Automatic Update and Compile Order 설정 메뉴 선택
- Run Simulation을 클릭한 후 Flow Navigator 창에서 Run Behavioral Simulation을 클릭하여 시뮬레이션 모드로 진입합니다. 에디터 파일을 아직 저장하지 않았다면 저장하라는 메시지가 나타납니다. Save를 클릭하면 시뮬레이션이 실행됩니다.

그림 4.20 – Run Behavioral Simulation 메뉴 선택
- SIMULATION 창이 열리면, Untitled 1이라는 제목의 시뮬레이션 출력 창에서 최대화 버튼을 클릭합니다.

그림 4.21 – 시뮬레이션 결과 창
내부 루프의 각 패스 총 시뮬레이션 시간은 10ns입니다. Adder4TestBench.vhdl에서 루프를 256번 통과하므로 시뮬레이션 실행 시간은 2560ns입니다.
- 상단 툴바에서 시뮬레이션 실행 시간을 2560ns로 설정(1단계), 왼쪽 방향 재시작 버튼(2단계)을 누른 다음, 2560ns 동안 시뮬레이션을 실행하는 오른쪽 방향 버튼(3단계)을 누르고, 마지막으로 Zoom Fit 버튼(4단계)을 눌러 시뮬레이션 출력 데이터 범위를 창에 맞게 조정합니다.

그림 4.22 – 실행 시작부터 끝까지의 시뮬레이션 결과
돋보기 아이콘을 사용하여 트레이스의 임의 지점을 확대하고 테스트 중에 수행된 각 덧셈 연산의 결과를 관찰할 수 있습니다. 예를 들어, 다음 그림은 10진수 6과 2를 더해 결과 8과 캐리 0을 생성한 것을 보여줍니다. 이 값들은 기대값과 일치하여 error가 0으로 설정되었습니다. error 신호는 모든 256 테스트 케이스에서 0으로, 우리 로직 회로가 모든 테스트를 통과했음을 나타냅니다.

그림 4.23 – 시뮬레이션 결과 확대 보기
- 데이터 트레이스 위의 파란 SIMULATION 바의 X를 클릭하여 시뮬레이션 모드를 종료합니다. 시뮬레이션을 닫을지 묻는 질문에 OK를 클릭합니다.
행동 테스트를 통과했으므로, 이제 설계에 사용될 I/O 신호를 정의하겠습니다.
I/O 신호 정의
다음 단계는 우리 회로의 입력과 출력을 Arty 보드의 하드웨어 디바이스에 연결하는 것입니다. 입력은 보드 스위치와 푸시버튼이 되고, 출력은 LED가 됩니다.
다음 단계는 FPGA 디바이스에서 사용할 I/O 핀과 그 핀에 연결된 보드 상의 기능을 설명하는 제약 파일을 생성합니다. 제약 파일의 확장자는 xdc입니다:
- Sources 서브 윈도우에서 Constraints를 우클릭하고 Add Sources…를 선택합니다.
- Add Sources 대화상자에서 Add or create constraints가 선택되었는지 확인하고 Next를 클릭합니다.
- Add or Create Constraints 대화상자에서 Create File을 클릭합니다.
- 파일명으로 Arty-A7-100.xdc를 입력하고 OK를 클릭합니다. (디바이스에 따라 Arty-A7-35.xdc가 적절할 수 있습니다.)
- Finish를 클릭하여 Add or Create Constraints 대화상자를 닫습니다.
- Constraints 소스 트리를 확장하고 Arty-A7-35.xdc를 더블클릭합니다.
- Digilent는 Arty A7 보드용으로 미리 채워진 제약 파일을 제공합니다. https://raw.githubusercontent.com/Digilent/digilent-xdc/master/Arty-A7-35-Master.xdc를 방문하여 브라우저 창의 전체 내용을 Vivado의 Arty-A7-35.xdc 편집기 창에 복사합니다. 디바이스에 적절한 경우 https://raw.githubusercontent.com/Digilent/digilent-xdc/master/Arty-A7-100-Master.xdc 파일을 대신 사용합니다.
- 제약 파일의 모든 I/O 핀은 줄 앞의 # 문자로 주석 처리되어 있습니다. 각 줄 앞의 # 문자를 제거하여 파일에서 적절한 줄의 주석을 해제합니다. 우리는 Arty-A7-100.xdc 파일에서 다음 섹션에 나열된 핀을 사용할 것입니다: Switches, RGB LEDs (첫 번째 녹색 LED인 led0_g만), LEDs, Buttons. 다음 그림은 주석이 해제된 후의 이 줄들을 보여줍니다.

그림 4.24 – 제약 편집기 창
다음 섹션에서는 가산기 코드를 I/O 디바이스와 연결하는 최상위 VHDL 파일을 생성합니다.
최상위 VHDL 파일 생성
이제 4비트 가산기 컴포넌트를 해당 보드 I/O 신호에 연결하는 최상위 VHDL 파일을 생성합니다:
- Sources 서브 윈도우에서 Design Sources를 우클릭하고 Add Sources…를 선택합니다.
- Add Sources 대화상자에서 Add or create design sources가 선택되었는지 확인하고 Next를 클릭합니다.
- Add or Create Design Sources 대화상자에서 Create File을 클릭합니다.
- 파일명으로 vhdl을 입력하고 OK를 클릭합니다.
- Finish를 클릭하여 Add or Create Design Sources 대화상자를 닫고, Define Module 대화상자에서 OK를 클릭한 후, 이를 사용할지 묻는 질문에 Yes를 클릭합니다.
- Design Sources 아래의 vhdl을 더블클릭합니다. ArtyAdder.vhdl 편집기 창의 자동 생성된 내용을 삭제하고 다음 코드를 ArtyAdder.vhdl 편집기에 입력합니다:
-- 표준 라이브러리 로드 library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity ARTY_ADDER is port ( sw : in STD_LOGIC_VECTOR (3 downto 0); btn : in STD_LOGIC_VECTOR (3 downto 0); led : out STD_LOGIC_VECTOR (3 downto 0); led0_g : out STD_LOGIC ); end entity ARTY_ADDER; architecture BEHAVIORAL of ARTY_ADDER is -- 이전 4비트 가산기 컴포넌트 정의 참조 ADDER4 is port ( A4 : in std_logic_vector(3 downto 0); B4 : in std_logic_vector(3 downto 0); SUM4 : out std_logic_vector(3 downto 0); C_OUT4 : out std_logic ); end component; begin ADDER : ADDER4 port map ( A4 => sw, B4 => btn, SUM4 => led, C_OUT4 => led0_g ); end architecture BEHAVIORAL;
이 코드는 Arty-A7-100.xdc에서 명명된 I/O 디바이스의 신호 이름인 sw (4개 스위치), btn (4개 푸시버튼), led (4개 단색 LED), led0_g (첫 번째 다색 LED의 녹색 채널)를 ADDER4의 입력과 출력에 매핑합니다.
VHDL은 대소문자를 구분하지 않지만, Vivado에서 xdc 제약 파일 처리는 대소문자를 구분합니다. xdc 파일에 정의된 I/O 디바이스 이름의 대소문자는 VHDL 파일에서 참조할 때 동일해야 합니다. 구체적으로, 이 파일의 VHDL I/O 신호 이름은 제약 파일에서 소문자이므로 소문자여야 합니다.
이제 우리 설계를 Arty 보드용으로 합성, 구현, 프로그래밍할 준비가 되었습니다.
FPGA 비트스트림 합성 및 구현
또는 Generate Bitstream을 선택하면 Vivado가 사용자 추가 개입 없이 합성, 구현, 비트스트림 생성을 포함한 모든 필수 단계를 수행합니다. 치명적인 오류가 발생하면 프로세스가 중단되고 오류 메시지가 표시됩니다. 비트스트림을 생성하려면 다음 단계를 수행하세요:
- Generate Bitstream을 클릭하여 빌드를 시작합니다. 텍스트 에디터를 저장할지 묻는 메시지가 나타날 수 있습니다. Save를 클릭합니다. 구현 결과가 없어 합성과 구현을 시작해도 되는지 묻는 메시지가 나타날 수 있습니다. Yes를 클릭합니다.

그림 4.25 – Generate Bitstream 메뉴 선택
- Launch Runs 대화상자가 나타납니다. 컴퓨터의 프로세서 코어 수까지 Number of jobs 값을 선택할 수 있습니다. 더 많은 코어를 사용하면 프로세스가 빨라지지만, 긴 빌드 과정 동안 컴퓨터를 계속 사용하려면 속도가 느려질 수 있습니다. OK를 클릭하여 빌드를 시작합니다.

그림 4.26 – Launch Runs 대화상자
- 빌드 과정 중 Vivado는 메인 창 오른쪽 상단에 상태를 표시합니다. 필요한 경우 상태 표시 옆의 Cancel을 클릭하여 빌드 프로세스를 취소할 수 있습니다.

그림 4.27 – 컴파일 상태 표시
- 빌드 프로세스가 완료되면, 치명적인 오류가 없었다고 가정할 때 Bitstream Generation Completed 대화상자가 나타납니다. 다른 옵션도 제공되지만, 우리는 비트스트림을 Arty 보드에 다운로드하는 것으로 바로 진행합니다. Open Hardware Manager를 선택하고 OK를 클릭합니다.

그림 4.28 – Bitstream Generation Completed 대화상자
이제 비트스트림을 FPGA에 다운로드하겠습니다.
보드에 비트스트림 다운로드
Arty A7 보드에 비트스트림을 다운로드하려면 다음 단계를 수행하세요:
- HARDWARE MANAGER 대화상자가 나타나며 No hardware target is open이라고 표시됩니다.
- Arty A7-35 또는 A7-100 보드를 USB로 컴퓨터에 연결합니다. 보드가 인식될 때까지 몇 초 기다린 후 Open target, Auto Connect를 차례로 클릭합니다.

그림 4.29 – Open target 및 Auto Connect 선택
- 몇 초 후 Vivado가 보드 연결을 표시해야 합니다. Program device를 클릭하여 FPGA 비트스트림을 Arty 보드에 다운로드합니다. 비트스트림 파일을 선택하라는 메시지가 나타납니다. 이 예제와 동일한 디렉토리 구조를 사용했다면 파일은 C:/Projects/ArtyAdder/ArtyAdder.runs/impl_1/ARTY_ADDER.bit에 위치합니다.

그림 4.30 – Program Device 대화상자
- Program을 클릭하여 프로그램을 FPGA 디바이스에 다운로드하고 시작합니다.
- 이제 Arty I/O로 프로그램 동작을 테스트할 수 있습니다. 4개 스위치를 모두 off 위치로 두고(스위치를 인접한 보드 가장자리로 이동), 4개 푸시버튼 중 어느 것도 누르지 않습니다. 4개 녹색 LED가 모두 꺼져 있어야 합니다.
- 개별 스위치를 켜거나 푸시버튼 중 하나를 누르면 해당 녹색 LED가 켜져야 합니다. 스위치 조합을 켜면서 푸시버튼을 조합하여 누르면 해당 4비트 숫자가 더해져 LED에 결과가 표시됩니다. 캐리가 발생하면(예: SW3을 켜고 동시에 BTN3을 누르면), 녹색 캐리 LED가 점등됩니다.
여기서 수행한 프로그래밍 과정은 프로그램을 FPGA RAM에 저장했습니다. FPGA 보드 전원을 껐다 켜면 프로그램을 다시 로드하기 위해 프로그래밍 과정을 반복해야 합니다. 또는 다음 섹션에서 설명하는 대로 FPGA 구성 파일을 온보드 플래시 메모리에 저장할 수 있습니다.
비트스트림을 온보드 플래시 메모리에 프로그래밍
Arty 보드에 전원이 인가될 때마다 FPGA를 구성하려면 FPGA 구성 파일을 보드의 플래시 메모리에 저장해야 합니다. MODE 점퍼가 설치되어 있으면 FPGA는 전원 투입 시 온보드 플래시 메모리에서 구성 파일을 다운로드하려고 시도합니다. 이 메모리는 Artix-7 FPGA 인접한 별도 칩에 있습니다. 플래시 메모리에 구성 파일을 프로그래밍하려면 다음 단계를 따르세요:
- Arty 보드에 MODE 점퍼가 없으면 설치합니다.
- Generate Bitstream을 우클릭하고 Bitstream Settings…를 선택합니다.
- Settings 대화상자에서 -bin_file 옆의 체크박스를 선택하고 OK를 클릭합니다.

그림 4.31 – Bitstream settings 대화상자
- 메인 Vivado 대화상자에서 Generate Bitstream을 클릭하고 비트스트림 생성 과정을 반복합니다. Bitstream Generation Completed 대화상자가 나타나면 Cancel을 클릭합니다.
- Hardware 대화상자에서 FPGA 부품 번호(xc7a100t_0)를 우클릭하고 Add Configuration Memory Device…를 선택합니다.

그림 4.32 – Add Configuration Memory Device… 메뉴 선택
- Search에 s25fl127을 입력합니다. 일치하는 부품 번호 하나가 나타납니다. 해당 부품을 선택하고 OK를 클릭합니다.

그림 4.33 – Add Configuration Memory Device 대화상자
- Do you want to program the configuration memory device now?라는 대화상자가 나타납니다. OK를 클릭합니다.
- Program Configuration Memory Device 대화상자가 나타나며 구성 파일 이름을 요청합니다. Configuration file 오른쪽의 … 버튼을 클릭하고 C:/Projects/ArtyAdder/ArtyAdder.runs/impl_1/ARTY_ADDER.bin을 선택합니다. OK를 클릭합니다.

그림 4.34 – Program Configuration Memory Device 대화상자
- 프로그래밍 과정은 몇 초가 걸립니다. 파일이 보드 플래시 메모리에 프로그래밍된 후 성공 메시지를 받아야 합니다.

그림 4.35 – Program Flash 완료 대화상자
이후 보드 전원을 껐다 켤 때마다 4비트 가산기 프로그램이 로드되어 실행됩니다. 우리가 구성 파일 로드에 사용한 설정으로는 프로그램이 로드되는 데 오랜 시간이 걸립니다. FPGA가 프로그램을 로드하는 대기를 피하려면 다음 단계를 수행하여 구성 파일 로드 속도를 개선할 수 있습니다:
- Flow Navigator에서 Open Synthesized Design을 선택합니다.
- Vivado 메인 메뉴에서 Tools/Edit Device Properties…를 선택합니다.
- General 탭에서 Enable Bitstream Compression을 TRUE로 설정합니다.
- Configuration 탭에서 Configuration Rate (MHz)를 33으로 설정하고 OK를 클릭합니다.
- 비트스트림을 다시 생성하고, 앞에서 설명한 대로 플래시 메모리를 프로그래밍합니다. 구성 메모리 디바이스를 제거하고 다시 추가하여 재프로그래밍 옵션을 표시해야 합니다.
- Hardware Manager를 닫습니다.
- Arty 보드 USB 케이블을 뽑았다가 다시 꽂습니다. 프로그램이 전원 투입 시 거의 즉시 실행되기 시작해야 합니다.
이 섹션에서는 FPGA I/O 핀의 신호와 상호작용하는 간단한 조합 로직의 예를 제시했습니다. 여기의 의도는 Vivado 도구 제품군에 익숙해지고 도구들이 완전한 FPGA 개발 사이클을 수행하는 데 어떻게 사용되는지 보여주는 것이었습니다.
요약
이 장은 실시간 임베디드 시스템 아키텍처에서 FPGA의 효과적인 활용에 대한 논의로 시작하여 표준 FPGA 디바이스와 그 내부의 저수준 구성 요소에 대한 설명으로 이어졌습니다. HDL, 블록 다이어그램 방법, C/C++ 같은 인기 있는 소프트웨어 프로그래밍 언어를 포함한 FPGA 설계 언어의 범위가 소개되었습니다. FPGA 개발 프로세스의 개요가 제시되었습니다. 이 장은 요구사항 진술로 시작하여 저비용 FPGA 개발 보드에 구현된 기능적 시스템으로 끝나는 완전한 FPGA 개발 사이클의 예로 마무리되었습니다.
이 장을 완료하면 FPGA가 실시간 임베디드 시스템 아키텍처에서 어떻게 효과적으로 적용될 수 있는지 알고, FPGA 집적 회로 내부의 구성 요소를 이해하게 됩니다. FPGA 알고리즘 설계에 사용되는 프로그래밍 언어, FPGA 개발 사이클의 단계, FPGA 개발 프로세스의 단계 순서를 이해하게 됩니다.
다음 장에서는 FPGA 개발 프로세스를 확장하여 FPGA를 포함하는 실시간 임베디드 시스템 아키텍처에 대한 완전한 접근법을 제공할 것입니다. 또한 이후 장들의 예제가 될 프로토타입 고성능 임베디드 시스템인 디지털 오실로스코프 개발을 시작할 것입니다.
Packt Publishing의 허가를 받아 재인쇄. Copyright © 2021 Packt Publishing
Jim Ledin은 Ledin Engineering, Inc.의 CEO입니다. Jim은 임베디드 소프트웨어 및 하드웨어 설계, 개발, 테스트 전문가입니다. 또한 임베디드 시스템 사이버보안 평가 및 침투 테스트에도 능숙합니다. 아이오와 주립대학교 항공우주공학 학사, 조지아 공과대학 전기컴퓨터공학 석사 학위를 보유하고 있습니다. 캘리포니아 주 등록 전문 전기 엔지니어, CISSP, CEH, CPT 자격을 갖추고 있습니다.
관련 콘텐츠:
- FPGA를 활용한 임베디드 설계: 하드웨어 리소스
- FPGA를 활용한 임베디드 설계: 구현 언어
- FPGA를 활용한 임베디드 설계: 개발 프로세스
- 오픈소스 도구로 FPGA 프로그래밍 단순화
- FPGA 또는 ASIC에서 부동소수점 알고리즘 구현
- FPGA를 활용한 딥러닝
- GPU 코드를 FPGA로 마이그레이션하여 AI 애플리케이션에 활용하는 소프트웨어 도구
더 많은 Embedded 콘텐츠를 위해 Embedded 주간 이메일 뉴스레터를 구독하세요.