FPGA(Field-Programmable Gate Array)는 SoC(System on Chip) 설계와 제품 개발에서 다양한 방식으로 활용될 수 있습니다. FPGA는 설계자가 직접 하드웨어 구조를 프로그래밍할 수 있어 유연성과 빠른 개발이 가능하다는 장점이 있습니다. 이를 바탕으로 제품 개발과 SoC 제작에 어떻게 사용될 수 있는지 몇 가지 중요한 활용 방법을 살펴보겠습니다.

1. FPGA의 제품 활용 방안

  • 프로토타이핑 및 검증: FPGA는 SoC의 하드웨어 설계를 실제 실리콘으로 구현하기 전에 검증하는 데 중요한 역할을 합니다. SoC 설계의 RTL 코드를 FPGA에 다운로드하여 실시간 테스트를 통해 오류를 조기에 발견할 수 있습니다. 이를 통해 설계 최적화와 실리콘 제작 전 하드웨어 검증을 효과적으로 수행할 수 있습니다.
  • 저비용, 소규모 양산 제품: 일부 제품에서는 ASIC(Application-Specific Integrated Circuit)으로 대체하기 전에 소량 생산 제품에 FPGA를 사용하기도 합니다. FPGA는 소량 생산이나 시장 검증 제품에서 비용 효율적이고 유연한 솔루션을 제공합니다.
  • 고속 데이터 처리 및 맞춤형 연산: FPGA는 병렬 처리를 통해 고속 연산이 필요한 분야에서 사용될 수 있습니다. 이미지 처리, 신호 처리, 통신 장비 등에서 특정 알고리즘을 하드웨어 가속기로 구현하여 높은 성능을 요구하는 애플리케이션에 적합합니다.
  • 업그레이드 가능한 하드웨어 플랫폼: FPGA의 재프로그램 가능성을 이용하여, 하드웨어 수준에서 기능을 추가하거나 성능을 개선할 수 있습니다. 이 방식은 IoT 기기나 통신 장비에서 새로운 프로토콜 지원이나 하드웨어 업그레이드를 용이하게 할 수 있습니다.

2. SoC 설계에서 FPGA의 활용

  • 초기 프로토타이핑: SoC 설계 초기 단계에서, FPGA는 시스템 검증과 성능 평가에 중요한 도구입니다. SoC의 하드웨어 설계를 FPGA에서 미리 구현하고, 이를 통해 시스템 통합 테스트를 수행할 수 있습니다. 실제 ASIC이나 SoC가 제작되기 전에 성능과 기능을 확인할 수 있는 효과적인 방법입니다.
  • IP 검증 및 통합: FPGA는 SoC 설계 시 사용되는 IP(Intellectual Property) 블록들을 통합하여 검증하는 과정에서도 활용됩니다. 예를 들어, 메모리 제어기나 통신 프로토콜 IP를 FPGA에 구현하여 소프트웨어와 하드웨어 간 상호작용을 사전에 테스트할 수 있습니다.
  • SoC의 가속기 역할: FPGA는 SoC 설계에서 하드웨어 가속기로 활용될 수 있습니다. SoC 내부에서 FPGA를 협력 처리 장치로 사용하여 특정 작업을 가속화하고, SoC의 성능을 극대화하는 데 기여할 수 있습니다. 예를 들어, 머신러닝, 신호 처리, 암호화 연산 등을 FPGA로 구현하여 CPU의 부담을 줄이고 성능을 개선할 수 있습니다.
  • 칩 설계 검증 환경: FPGA는 SoC 설계의 시스템 레벨 검증에서도 사용됩니다. SoC 설계에서 각종 인터페이스나 통신 프로토콜을 검증할 때, FPGA를 사용하여 실제 환경에서 동작하는지 확인할 수 있습니다.

> 비메모리 설계 엔지니어는 직접 메모리를 만들지는 않는 경우가 많습니다.

이미 만들어져 있는 메모리를 사용하여 메모리 컨트롤러 등을 설계하게 됩니다.

그래서, 상황에 필요한 적당한 메모리를 잘 고를 수 있는 능력이 설계 엔지니어의 역량이라고 생각합니다.

 

1. 1bit Size

  • SRAM (Static RAM): 1비트는 6개의 트랜지스터(6T)를 사용하여 저장됩니다. 셀 구조가 복잡하고 면적이 크지만, 데이터 저장이 전력 공급 시 지속적으로 이루어집니다. 셀 크기가 크기 때문에 고밀도 집적이 어렵습니다.
  • DRAM (Dynamic RAM): 1비트는 1개의 트랜지스터와 1개의 캐패시터(1T1C)를 사용해 저장됩니다. 캐패시터를 통해 데이터를 저장하는데, 시간이 지남에 따라 충전 상태가 변하므로 주기적인 리프레시가 필요합니다. DRAM의 셀 크기는 SRAM보다 작아 고밀도 집적이 가능합니다.
  • 레지스터 (Register): 레지스터는 1비트를 저장하기 위해 D 플립플롭(D Flip-Flop)을 사용합니다. 플립플롭은 4~6개의 트랜지스터로 구성되며, SRAM보다 크기는 작지만, 고속 데이터를 저장하는데 주로 사용됩니다. CPU 내에서 매우 가까운 위치에 있으며, 속도가 가장 빠릅니다. 실제 현업에서는 보통 D F/F gates == 10 gates

>> F/F만으로 설계를 할 경우 AREA의 손해를 많이 볼 수 있습니다. 여러 메모리는 사용하여 직접도를 높혀야합니다.

2. Data Access

  • SRAM: 데이터를 읽고 쓰는 과정이 매우 빠릅니다. 별도의 리프레시 과정이 필요 없으며, 클럭 사이클 동안 데이터를 유지합니다. 메모리 셀에 직접 접근할 수 있는 구조를 가지고 있습니다.
  • DRAM: DRAM은 데이터를 캐패시터에 저장하므로, 데이터를 읽기 전에 리프레시가 필요할 수 있습니다. 메모리에 접근하기 위해선 캐패시터의 충전 상태를 확인하는 과정을 거치며, 이로 인해 SRAM보다 데이터 접근 시간이 상대적으로 깁니다.
  • 레지스터: 레지스터는 CPU 내에서 매우 가까운 위치에 있으며, 데이터 접근 시간이 거의 실시간에 가깝습니다. 매우 짧은 대기 시간으로 인해 레지스터에서 데이터 접근이 가장 빠릅니다.

3. Latency

  • SRAM: 대기 시간이 매우 짧습니다. 전기 신호가 바로 메모리 셀에 전달되기 때문에 데이터 접근 속도가 빠릅니다.
  • DRAM: DRAM은 리프레시 과정과 셀에 접근하는 추가적인 단계가 있어, SRAM보다 대기 시간이 길지만 여전히 빠른 응답을 제공합니다.
  • 레지스터: 레지스터의 대기 시간은 SRAM과 DRAM보다 훨씬 짧습니다. CPU 바로 옆에서 데이터 접근이 이루어지므로, 명령 실행 시 즉각적으로 데이터를 가져올 수 있습니다.

4. Random Access Performance

  • SRAM: 랜덤 접근 성능이 매우 뛰어납니다. 메모리 셀에 직접 접근할 수 있기 때문에 주소에 관계없이 빠른 랜덤 접근이 가능합니다.
  • DRAM: DRAM의 랜덤 접근 성능은 SRAM보다 떨어집니다. 메모리 뱅크 내에서 데이터 접근이 일어나며, 대기 시간이 있어 연속적인 데이터 접근에 유리합니다.
  • 레지스터: 레지스터는 CPU 내에서 동작하는 가장 빠른 메모리이므로, 랜덤 접근 성능도 매우 뛰어납니다. 데이터를 즉시 읽거나 쓸 수 있습니다.

5. Interface

  • SRAM: SRAM은 일반적으로 고속 캐시 메모리나 버퍼로 사용됩니다. CPU와 메모리 사이의 인터페이스는 매우 빠르고, 별도의 복잡한 제어 없이 동작할 수 있습니다.
  • DRAM: DRAM은 메모리 컨트롤러와 함께 동작하며, 외부 인터페이스를 통해 데이터를 교환합니다. 리프레시, 프리차지, 접근 타이밍을 제어하는 복잡한 인터페이스를 필요로 합니다.
  • 레지스터: 레지스터는 CPU 내부에 직접 연결된 가장 가까운 메모리로, 데이터 인터페이스가 매우 단순합니다. CPU의 연산 과정 중에 바로 접근하여 사용됩니다.

요약

  • SRAM: 빠른 속도, 낮은 대기 시간, 높은 랜덤 접근 성능, 그러나 큰 셀 크기와 낮은 집적도.
  • DRAM: 고밀도, 리프레시 필요, 상대적으로 긴 대기 시간, 연속적 데이터 접근에 유리.
  • 레지스터: CPU 내에서 가장 빠르고 직접적인 데이터 접근이 가능하지만, 용량이 매우 작고 고가.

각 메모리는 성능, 비용, 용도에 따라 선택이 달라지며, SRAM은 캐시 메모리, DRAM은 주 메모리, 레지스터는 CPU 내부의 임시 저장 공간으로 사용됩니다.

FSM + Counter

  1. Core가 IDLE인지 확인합니다.
  2. i_run신호와 counting 할  숫자를 core에 전달합니다.
  3. DONE이 될때까지 기다립니다.

 

 

- Verilog Code

* https://github.com/Vamosssss/Basic/tree/main/07.%20FSM/02.%20FSM%20%2B%20Counter


FSM(Traffic Light)

  1. RED will go to YELLOW after 30 cycles.
  2. YELLOW will go to GREEN after 5 cycles.
  3. GREEN will go RED after 20 cycles.
  4. The light color will be output.

 

- Verilog Code

* https://github.com/Vamosssss/Basic/tree/main/07.%20FSM/03.%20FSM(Traffic%20Light)

FSM(Finite State Machine) 로직에서 삼항 연산자(ternary operator)의 중요성은 가독성과 간결함, 효율성을 제공하는 데 있습니다. 삼항 연산자는 특히 상태 변화나 출력 로직을 간결하게 표현할 수 있어 FSM 설계에서 자주 활용됩니다.

 

삼항 연산자(ternary operator)는 세 개의 피연산자를 가지는 연산자로, 주로 조건에 따라 다른 값을 선택할 때 사용됩니다. 조건식 ? 참일 때 값 : 거짓일 때 값 의 형태로 쓰이며, 조건이 참일 때는 첫 번째 값을 반환하고, 거짓일 때는 두 번째 값을 반환합니다. 삼항 연산자는 간단한 조건부 로직을 한 줄로 표현할 수 있어 코드의 간결함과 가독성을 높이는 데 유용합니다.

삼항 연산자의 구조

삼항 연산자는 다음과 같은 형태로 작성됩니다:

- verilog
 
조건식 ? 참일 때의 값 : 거짓일 때의 값;

Verilog에서의 삼항 연산자 예시

-verilog
 
assign result = (a > b) ? a : b;
 

위 코드에서 a가 b보다 클 경우 result는 a의 값을 가지게 되고, 그렇지 않으면 b의 값을 가집니다. 즉, 조건 a > b가 참이면 a가 선택되고, 거짓이면 b가 선택되는 것입니다.

주요 특징

  1. 간결성: if-else 구문으로 표현할 수 있는 조건부 논리를 한 줄로 간결하게 표현할 수 있습니다.
    • if-else 버전:
      - verilog
       
      if (a > b) begin
         result = a;
      end else begin
         result = b;
      end
       
    • 삼항 연산자 사용:
      - verilog
       
      assign result = (a > b) ? a : b;
  2. 가독성: 간단한 조건일 경우 삼항 연산자를 사용하면 코드를 더 직관적이고 읽기 쉽게 만들 수 있습니다.
  3. 효율성: 짧은 논리를 처리할 때는 삼항 연산자가 더 효율적일 수 있으며, 이를 통해 리소스를 절약하고 하드웨어 회로 최적화에도 도움을 줄 수 있습니다.

 

위 그림 처럼 여러 state가 있는 경우에 case문을 활용한 삼항연산자가 if-else문을 활용한 것 보다 유용 할  수 있습니다.

 

-  Verilog Code

https://github.com/Vamosssss/HDLbits_Solutions/blob/main/3.%20Circuit/2.Sequential%20Logic/05.%20FSM/12.%20Lemmings3.v

  1. CLK (Clock)
    • CLK는 SRAM의 모든 동작을 동기화하는 클럭 신호입니다. 읽기 및 쓰기 연산은 클럭의 상승 또는 하강 에지에서 발생하며, 대부분의 동기식 SRAM은 클럭의 상승 에지에서 동작합니다.
  2. ADDR (Address)
    • ADDR는 접근할 메모리 셀의 주소를 지정하는 신호입니다. 이 신호는 SRAM의 특정 위치에서 데이터를 읽거나 쓰기 위해 사용됩니다.
  3. DIN (Data Input)
    • DIN은 쓰기 연산 시 입력되는 데이터 버스입니다. ADDR로 지정된 메모리 셀에 기록할 데이터를 담고 있습니다.
  4. DOUT (Data Output)
    • DOUT은 읽기 연산 시 출력되는 데이터 버스입니다. ADDR로 지정된 메모리 셀에서 읽어온 데이터를 출력합니다.
  5. EN (Enable)
    • EN은 SRAM을 활성화하는 신호입니다. EN이 활성화되면 SRAM이 동작할 준비가 되며, 비활성화 상태에서는 모든 동작이 중지되고 SRAM은 대기 상태에 들어갑니다. 읽기 및 쓰기 연산을 실행하려면 EN이 반드시 활성화되어야 합니다.
  6. WE (Write Enable)
    • WE는 쓰기 연산을 제어하는 신호입니다. WE가 활성화되면 쓰기 모드로 동작하여 SRAM에 데이터를 기록할 수 있으며, WE가 비활성화된 경우 SRAM은 읽기 모드로 동작합니다.

Write Operation (쓰기 연산 과정)

  1. ADDR 설정: 쓰기할 메모리 위치를 선택하기 위해 ADDR 버스에 주소를 설정합니다.
  2. DIN 설정: 기록할 데이터를 DIN 버스에 입력합니다.
  3. EN 활성화: EN 신호를 활성화하여 SRAM을 동작 가능한 상태로 만듭니다.
  4. WE 활성화: WE 신호를 활성화하여 쓰기 모드를 설정합니다.
  5. CLK 상승 에지: 클럭 신호가 상승 에지에 도달하면, ADDR로 지정된 메모리 위치에 DIN 값이 기록됩니다.
  6. WE 비활성화: 쓰기 작업이 끝난 후 WE 신호를 비활성화하여 쓰기 작업을 종료합니다.

Read Operation (읽기 연산 과정)

  1. ADDR 설정: 읽고자 하는 메모리 위치를 선택하기 위해 ADDR 버스에 주소를 설정합니다.
  2. EN 활성화: EN 신호를 활성화하여 SRAM을 동작 가능한 상태로 만듭니다.
  3. WE 비활성화: WE 신호를 비활성화하여 읽기 모드로 전환합니다.
  4. CLK 상승 에지: 클럭 신호가 상승 에지에 도달하면, ADDR로 지정된 메모리 위치에서 데이터가 DOUT 버스를 통해 출력됩니다.
  5. DOUT 출력: ADDR에 저장된 데이터가 DOUT으로 읽혀집니다.

> Address0번지의 Data를 Read하고 싶을땐

en = 1, we = 0 >> Read Setting, Addr = 0 > dout에 Read Data가 올라옵니다.

 

> Address2번지에 Data를 Write하고 싶을땐

en = 1, we = 1 >> Write Setting, Addr = 2 >> din에 Write하고 싶은 data를 만들어줍니다.

 

 

 


실습 ) BRAM에 Data를 Write/Read하기.

  1. IDLE상태를 확인하고, i_run신호와 num_cnt에 숫자를 입력합니다.
  2. 0~99까지의 Address에 data를 Write합니다.
  3. Address 0~99까지의 data를 Read합니다.
  4. Read가 끝난 후, DONE을 띄우고, 다시 IDLE로 돌아갑니다.

1. Reset 입력 후 Core는 IDLE상태로 진입.

 

2. i_run신호와 Core의 입력값을 넣어주게 되면 State는 Write가 된다.(ce,we = 1, Write operation)
3. 0~99Addr까지 Write한 후, we = 0으로 내려오고 Read operation 시작.

 

4. 1cycle뒤에 Valid신호와 함께 Read 종료, o_done신호 1cycle후 다시 i_idle신호

 

 

- Verilog Code

* https://github.com/Vamosssss/FPGA-Project/tree/main/01.%20BRAM%20Controller

 

AT First.

1. ROM (Read-Only Memory)

  • 읽기 전용 메모리로, 데이터를 한 번 기록하면 이후에는 읽기만 가능합니다.
  • 전원이 꺼져도 데이터가 유지되는 비휘발성 메모리입니다.
  • 주로 펌웨어, 부팅 프로그램(BIOS), 디바이스 설정 값 등 고정된 데이터를 저장하는 데 사용됩니다.
  • ROM의 종류에는 PROM, EPROM, EEPROM 등이 있으며, 각기 다른 방식으로 데이터를 한 번 쓰거나 수정할 수 있습니다.

2. RAM (Random Access Memory)

  • 읽기/쓰기 모두 가능한 메모리로, 프로그램 실행 시 데이터를 일시적으로 저장합니다.
  • 전원이 꺼지면 데이터가 사라지는 휘발성 메모리입니다.
  • SRAMDRAM으로 나뉘며, SRAM은 속도가 빠르고 DRAM은 더 많은 용량을 저장할 수 있습니다.
  • 임시 저장 공간으로, 운영체제와 실행 중인 프로그램에서 데이터를 빠르게 읽고 쓰기 위한 목적으로 사용됩니다.

 

Xililx FPGA에는 BRAM이라는 Component가 존재합니다.

BRAM은 Block RAM의 약어로 SRAM의 역할을 할 수 있도록 만든 Primitive Cell입니다.

BRAM의 사용법을 익힌다면, ASIC에서의 SRAM사용도 문제가 없습니다!

 

 

1. SPSRAM (Single-Port SRAM)

  • 하나의 포트만을 가지고 있어, 한 번에 하나의 접근(읽기 또는 쓰기)만 가능합니다.
  • 간단한 구조로, 비용전력 소모가 적지만, 동시에 여러 데이터에 접근할 수 없는 제약이 있습니다.
  • 일반적으로 캐시 메모리일반적인 임베디드 시스템에서 사용됩니다.

2. DPSRAM (Dual-Port SRAM)

  • 두 개의 독립적인 포트를 가지고 있어, 동시에 두 개의 데이터 접근(읽기/쓰기)을 지원합니다.
  • 복잡한 구조로 인해 비용전력 소모가 증가하지만, 병렬 처리고속 데이터 처리가 필요한 시스템에 유리합니다.
  • 주로 고속 버퍼FPGA, 통신 시스템에서 사용됩니다.

> DPRAM을 사용하게 될 경우 Control에서 유리한 부분이 있겠지만, Dual인 만큼 Area를 많이 차지하는 부분도 있습니다. 엔지니어는 항상 이러한 Trade-off를 고려하여 설계해야 합니다.

 


* https://dreamsailor.tistory.com/21

'Verilog HDL > FPGA' 카테고리의 다른 글

03. FPGA(Field Programmable Gate Array) Usage  (1) 2024.10.09
02. FPGA BRAM에 Write/Read해보기.  (0) 2024.10.08

1. 상태 전이를 분리한 코드

  • 상태 전이 로직이 별도의 always @(*) 블록에서 처리됩니다.
    • always @(*) 블록에서 상태 전이를 계산하고, 그 결과를 next_state에 저장한 후, 클럭 신호와 비동기 리셋 신호에 따라 state 값이 업데이트됩니다.

2. 상태 전이를 통합한 코드

  • 상태 전이 로직이 상태 저장 블록인 always @(posedge clk, posedge areset) 내부에서 처리됩니다.
    • state 값이 조건에 따라 직접 업데이트되며, 상태 전이와 상태 저장이 한 블록에서 이루어집니다.

3. 코드 구조 차이

  • 상태 전이를 분리한 코드에서는 상태 전이와 상태 저장이 각각의 블록에서 독립적으로 처리됩니다.
    • always @(*) 블록에서 상태 전이를 결정하고, 그 이후 클럭 신호에 따라 state가 업데이트되는 2단계 구조입니다.
  • 상태 전이를 통합한 코드는 상태 전이와 상태 저장이 하나의 블록에서 이루어집니다.
    • 전이 및 상태 저장이 동시에 처리되어 더 간결한 형태입니다.

4. 장단점 비교

  • 상태 전이를 분리한 코드의 장점은 상태 전이와 상태 저장이 분리되어 있어 가독성이 좋고, 복잡한 상태 전이 로직을 다룰 때 유지보수하기 용이하다는 점입니다. 상태 전이와 저장이 각각 독립적으로 이루어져 명확한 구조를 가지고 있습니다.
  • 상태 전이를 통합한 코드의 장점은 코드가 더 간단하고 짧다는 점입니다. 단순한 상태 전이를 표현할 때는 더 효율적이고, 필요 없는 복잡성을 줄여줍니다.

5. 어떤 코드가 더 나은가?

  • 복잡한 상태 전이 로직이 필요한 경우에는 상태 전이를 분리한 코드가 더 적합합니다. 상태 전이와 저장이 명확히 구분되어 있어 복잡한 FSM을 구현하거나 유지보수하기에 용이합니다.
  • 단순한 상태 전이 로직이 필요한 경우에는 상태 전이를 통합한 코드가 더 적합합니다. 코드가 간결해지고, 이해하기 쉬운 것이 장점입니다.

결론적으로, 상태 전이가 단순하다면 상태 전이를 통합한 코드, 복잡한 상태 전이를 처리해야 한다면 상태 전이를 분리한 코드가 더 적합합니다.

 


- Verilog Code

https://github.com/Vamosssss/HDLbits_Solutions/tree/main/3.%20Circuit/2.Sequential%20Logic/05.%20FSM

SM 로직 설계를 할 때 일반적으로 상태 선언, 상태 전이, 다음 상태 결정 로직, 출력 로직으로 나누어 설계합니다. 아래에서 각 부분을 설명하고, Verilog로 구현한 코드를 예시로 보여드리겠습니다.

1. 상태 선언 (State Declaration)

FSM에서 사용할 상태를 정의합니다. 상태는 보통 localparam으로 선언하여, 가독성과 유지보수성을 높입니다. 각 상태는 고유한 값을 가집니다.

localparam S0 = 2'b00, S1 = 2'b01, S2 = 2'b10;

2. 상태 전이 (State Transition)

현재 상태에서 다음 상태로의 전이를 클럭 신호에 맞추어 업데이트하는 부분입니다. 플립플롭(flip-flop)을 사용하여 현재 상태를 저장합니다.

 
always @(posedge clk or posedge reset) begin
if (reset) begin present_state <= S0; // 리셋 시 초기 상태로 설정
end else begin present_state <= next_state; // 다음 상태로 전이
end
end

3. 다음 상태 결정 로직 (Next State Logic)

현재 상태와 입력에 따라 다음 상태를 결정하는 조합 논리입니다. always @(*) 블록을 사용하여 현재 상태와 입력 신호에 따라 다음 상태를 계산합니다.

 
always @(*) begin
case (present_state)
S0: if (in) next_state = S1; else next_state = S0;
S1: if (in) next_state = S2; else next_state = S0;
S2: if (in) next_state = S0; else next_state = S1;
default: next_state = S0; // 기본 상태
endcase
end

4. 출력 로직 (Output Logic)

출력 로직은 Moore FSM과 Mealy FSM에 따라 달라집니다. 여기서는 Moore FSM을 기준으로, 출력은 현재 상태에만 의존합니다.

 
always @(*) begin
case (present_state)
S0: out = 0;
S1: out = 1;
S2: out = 0;
default: out = 0;
endcase
end
 
  • 상태 선언: S0, S1, S2 세 가지 상태가 localparam으로 선언되었습니다.
  • 상태 전이: 현재 상태는 클럭 신호에 맞추어 업데이트됩니다. 리셋 신호가 들어오면 FSM은 기본 상태(S0)로 돌아갑니다.
  • 다음 상태 결정 로직: 현재 상태와 입력 신호 in에 따라 다음 상태를 결정합니다.
  • 출력 로직: 출력은 현재 상태에 따라 결정됩니다. Moore FSM에서는 출력이 상태에만 의존하므로, 상태에 따른 출력값을 정의합니다.

+ Recent posts