산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

FPGA LED 블링커 만들기: VHDL/Verilog 단계별 튜토리얼

FPGA LED 블링커 제작 단계별 가이드

1부: VHDL 또는 Verilog 설계

이 튜토리얼에서는 사용자 지정 주파수로 LED를 구동하는 VHDL 및 Verilog 코드 작성법을 배웁니다. 작업 흐름에 맞는 언어를 선택하세요.

HDL 작성 시 설계가 의도대로 동작하는지 검증해야 합니다. 실수는 불가피하므로 시뮬레이션은 필수입니다. 이 튜토리얼은 두 가지 중요한 단계로 나뉩니다:

  1. HDL 설계
  2. HDL 시뮬레이션

시뮬레이션을 건너뛰면 하드웨어 디버깅에 큰 비용이 듭니다. 시뮬레이션을 필수 관문으로 여기세요.

프로젝트 요구사항

50% 듀티 사이클로 100Hz, 50Hz, 10Hz, 1Hz 중 하나로 LED를 점멸시키는 HDL을 작성하세요. 두 개의 스위스로 주파수를 선택하고, LED_EN 스위치가 하이(High)여야 LED가 활성화됩니다. FPGA는 25MHz 발진기로 동작합니다.

주파수 선택기 진리표:

Enable스위치 1스위치 2LED 구동 주파수
0––비활성화
100100 Hz
10150 Hz
11010 Hz
1111 Hz

신호 요약:

신호명방향설명
i_clock입력25 MHz 클럭
i_enable입력활성화 스위치 (로직 0 = LED 끔)
i_switch_1입력주파수 선택 스위치 1
i_switch_2입력주파수 선택 스위치 2
o_led_drive출력LED 구동 신호

네 개의 동시 카운터 프로세스가 25MHz 클럭을 모니터링하며 각 목표 주파수에 대한 토글 신호를 생성합니다. 특정 주파수가 선택되지 않더라도 해당 카운터는 계속 실행됩니다. 이는 하드웨어 동시성의 핵심 원리입니다.

스위치들은 멀티플렉서 역할을 하여 선택된 토글 신호를 LED 출력으로 라우팅합니다. 멀티플렉서는 순수 조합 논리이므로 클럭 없이 동작합니다.

아래는 아키텍처를 보여주는 블록 다이어그램입니다:

FPGA LED 블링커 만들기: VHDL/Verilog 단계별 튜토리얼

VHDL 구현

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity tutorial_led_blink is
    port (
        i_clock      : in  std_logic;
        i_enable     : in  std_logic;
        i_switch_1   : in  std_logic;
        i_switch_2   : in  std_logic;
        o_led_drive  : out std_logic
    );
end tutorial_led_blink;

architecture rtl of tutorial_led_blink is
    -- 필요한 주파수 생성을 위한 상수:
    -- 공식: (25 MHz / 100 Hz * 50% 듀티 사이클)
    -- 100 Hz: 25,000,000 / 100 * 0.5 = 125,000
    constant c_CNT_100HZ : natural := 125000;
    constant c_CNT_50HZ  : natural := 250000;
    constant c_CNT_10HZ  : natural := 1250000;
    constant c_CNT_1HZ   : natural := 12500000;

    -- 카운터 신호들
    signal r_CNT_100HZ : natural range 0 to c_CNT_100HZ;
    signal r_CNT_50HZ  : natural range 0 to c_CNT_50HZ;
    signal r_CNT_10HZ  : natural range 0 to c_CNT_10HZ;
    signal r_CNT_1HZ   : natural range 0 to c_CNT_1HZ;

    -- 각 주파수에서 토글될 신호들
    signal r_TOGGLE_100HZ : std_logic := '0';
    signal r_TOGGLE_50HZ  : std_logic := '0';
    signal r_TOGGLE_10HZ  : std_logic := '0';
    signal r_TOGGLE_1HZ   : std_logic := '0';

    -- 1비트 선택 신호
    signal w_LED_SELECT : std_logic;

begin
    -- 모든 프로세스는 서로 다른 주파수로 특정 신호를 토글합니다.
    -- 스위치가 해당 출력을 선택하지 않아도 계속 실행됩니다.

    p_100_HZ : process (i_clock) is
    begin
        if rising_edge(i_clock) then
            if r_CNT_100HZ = c_CNT_100HZ-1 then
                r_TOGGLE_100HZ <= not r_TOGGLE_100HZ;
                r_CNT_100HZ <= 0;
            else
                r_CNT_100HZ <= r_CNT_100HZ + 1;
            end if;
        end if;
    end process p_100_HZ;

    p_50_HZ : process (i_clock) is
    begin
        if rising_edge(i_clock) then
            if r_CNT_50HZ = c_CNT_50HZ-1 then
                r_TOGGLE_50HZ <= not r_TOGGLE_50HZ;
                r_CNT_50HZ <= 0;
            else
                r_CNT_50HZ <= r_CNT_50HZ + 1;
            end if;
        end if;
    end process p_50_HZ;

    p_10_HZ : process (i_clock) is
    begin
        if rising_edge(i_clock) then
            if r_CNT_10HZ = c_CNT_10HZ-1 then
                r_TOGGLE_10HZ <= not r_TOGGLE_10HZ;
                r_CNT_10HZ <= 0;
            else
                r_CNT_10HZ <= r_CNT_10HZ + 1;
            end if;
        end if;
    end process p_10_HZ;

    p_1_HZ : process (i_clock) is
    begin
        if rising_edge(i_clock) then
            if r_CNT_1HZ = c_CNT_1HZ-1 then
                r_TOGGLE_1HZ <= not r_TOGGLE_1HZ;
                r_CNT_1HZ <= 0;
            else
                r_CNT_1HZ <= r_CNT_1HZ + 1;
            end if;
        end if;
    end process p_1_HZ;

    -- 스위치 입력 기반 멀티플렉서 생성
    w_LED_SELECT <= r_TOGGLE_100HZ when (i_switch_1 = '0' and i_switch_2 = '0') else
                    r_TOGGLE_50HZ  when (i_switch_1 = '0' and i_switch_2 = '1') else
                    r_TOGGLE_10HZ  when (i_switch_1 = '1' and i_switch_2 = '0') else
                    r_TOGGLE_1HZ;

    -- i_enable이 하이일 때만 o_led_drive 출력 (AND 게이트)
    o_led_drive <= w_LED_SELECT and i_enable;

end rtl;

Verilog 구현

module tutorial_led_blink (
    i_clock,
    i_enable,
    i_switch_1,
    i_switch_2,
    o_led_drive
);
    input i_clock;
    input i_enable;
    input i_switch_1;
    input i_switch_2;
    output o_led_drive;

    // 상수(파라미터) - 주파수 생성용
    // 입력 클럭은 임의로 25 kHz로 설정
    // 공식: (25 kHz / 100 Hz * 50% 듀티 사이클)
    // 100 Hz: 25,000 / 100 * 0.5 = 125
    parameter c_CNT_100HZ = 125;
    parameter c_CNT_50HZ  = 250;
    parameter c_CNT_10HZ  = 1250;
    parameter c_CNT_1HZ   = 12500;

    // 카운터 신호들
    reg [31:0] r_CNT_100HZ = 0;
    reg [31:0] r_CNT_50HZ  = 0;
    reg [31:0] r_CNT_10HZ  = 0;
    reg [31:0] r_CNT_1HZ   = 0;

    // 토글 신호들
    reg r_TOGGLE_100HZ = 1'b0;
    reg r_TOGGLE_50HZ  = 1'b0;
    reg r_TOGGLE_10HZ  = 1'b0;
    reg r_TOGGLE_1HZ   = 1'b0;

    // 1비트 선택 신호
    reg r_LED_SELECT;
    wire w_LED_SELECT;

    // 모든 always 블록은 서로 다른 주파수로 특정 신호를 토글합니다.
    // 스위치가 해당 출력을 선택하지 않아도 계속 실행됩니다.
    always @ (posedge i_clock) begin
        if (r_CNT_100HZ == c_CNT_100HZ-1) begin
            r_TOGGLE_100HZ <= !r_TOGGLE_100HZ;
            r_CNT_100HZ <= 0;
        end else
            r_CNT_100HZ <= r_CNT_100HZ + 1;
    end

    always @ (posedge i_clock) begin
        if (r_CNT_50HZ == c_CNT_50HZ-1) begin
            r_TOGGLE_50HZ <= !r_TOGGLE_50HZ;
            r_CNT_50HZ <= 0;
        end else
            r_CNT_50HZ <= r_CNT_50HZ + 1;
    end

    always @ (posedge i_clock) begin
        if (r_CNT_10HZ == c_CNT_10HZ-1) begin
            r_TOGGLE_10HZ <= !r_TOGGLE_10HZ;
            r_CNT_10HZ <= 0;
        end else
            r_CNT_10HZ <= r_CNT_10HZ + 1;
    end

    always @ (posedge i_clock) begin
        if (r_CNT_1HZ == c_CNT_1HZ-1) begin
            r_TOGGLE_1HZ <= !r_TOGGLE_1HZ;
            r_CNT_1HZ <= 0;
        end else
            r_CNT_1HZ <= r_CNT_1HZ + 1;
    end

    // 스위치 입력 기반 멀티플렉서 (조합 논리)
    always @ (*) begin
        case ({i_switch_1, i_switch_2}) // 연결 연산자
            2'b11 : r_LED_SELECT <= r_TOGGLE_1HZ;
            2'b10 : r_LED_SELECT <= r_TOGGLE_10HZ;
            2'b01 : r_LED_SELECT <= r_TOGGLE_50HZ;
            2'b00 : r_LED_SELECT <= r_TOGGLE_100HZ;
        endcase
    end

    assign o_led_drive = r_LED_SELECT & i_enable;

    // 멀티플렉서 대체 구현 (동일하지만 초보자에게 읽기 어려움)
    // assign w_LED_SELECT = i_switch_1 ? (i_switch_2 ? r_TOGGLE_1HZ : r_TOGGLE_10HZ) :
    //                       (i_switch_2 ? r_TOGGLE_50HZ : r_TOGGLE_100HZ);
    // assign o_led_drive = w_LED_SELECT & i_enable;

endmodule

다음 단계: 배포 전 VHDL 또는 Verilog로 이 설계를 시뮬레이션하여 올바른 동작을 확인하세요.

VHDL

  1. VHDL Signed/Unsigned 타입 마스터하기: 실전 가이드
  2. VHDL TEXTIO 라이브러리로 텍스트 파일에서 FPGA 블록 RAM 초기화하기
  3. VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모
  4. 고급 VHDL 퀴즈 2부: HDL 전문성 테스트
  5. Ready/Valid 핸드셰이크로 블록 RAM에 AXI FIFO 구현하기
  6. VHDL 클록 트리거 프로세스 구축 실전 가이드
  7. VHDL Signed vs Unsigned 타입 마스터하기: 실전 인사이트
  8. VHDL Case-When 문 마스터하기: 효율적 멀티플렉서 설계
  9. VHDL에서 보호 타입과 액세스 포인터로 동적 링크드 리스트 구현하기
  10. VHDL 자가 검증 테스트벤치 구축 실전 가이드