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

첫 번째 FPGA LED 깜박이를 만드는 방법:단계별 튜토리얼

단계별 가이드:첫 번째 FPGA LED 깜박이 만들기

1부:VHDL 또는 Verilog 설계

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

HDL을 작성할 때 설계가 의도한 대로 작동하는지 확인해야 합니다. 실수는 피할 수 없으므로 시뮬레이션은 필수입니다. 이 튜토리얼은 두 가지 중요한 단계로 나누어져 있습니다:

  1. HDL 디자인
  2. HDL 시뮬레이션

시뮬레이션을 건너뛰면 하드웨어 디버깅에 비용이 많이 들 수 있습니다. 시뮬레이션을 필수 체크포인트로 삼으세요.

프로젝트 요구사항

50% 듀티 사이클로 100Hz, 50Hz, 10Hz 또는 1Hz에서 LED를 깜박이는 HDL을 작성하세요. 두 개의 스위치가 원하는 주파수를 선택하고 추가 LED_EN LED를 활성화하려면 스위치가 높아야 합니다. FPGA는 25MHz 발진기에서 실행됩니다.

주파수 선택기의 진리표:

활성화 스위치1 스위치2 LED 구동 주파수
0 - - 비활성화
1 0 0 100Hz
1 0 1 50Hz
1 1 0 10Hz
1 1 1 1Hz

신호 요약:

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

4개의 동시 카운터 프로세스는 25MHz 클록을 모니터링하고 각 대상 주파수에 대한 토글을 생성합니다. 특정 주파수를 선택하지 않은 경우에도 해당 카운터는 계속 실행됩니다. 이는 하드웨어 동시성의 핵심 원칙입니다.

스위치는 선택한 토글을 LED 출력으로 라우팅하는 멀티플렉서를 형성합니다. 멀티플렉서는 순전히 조합 논리이므로 클록 없이 작동합니다.

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

첫 번째 FPGA LED 깜박이를 만드는 방법:단계별 튜토리얼

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
 -- Constants to create the frequencies needed:
 -- Formula is: (25 MHz / 100 Hz * 50% duty cycle)
 -- So for 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;
 -- These signals will be the counters:
 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;
 
 -- These signals will toggle at the frequencies needed:
 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';
 -- One bit select wire.
 signal w_LED_SELECT : std_logic;
 
begin
 -- All processes toggle a specific signal at a different frequency.
 -- They all run continuously even if the switches are
 -- not selecting their particular output.
 
 p_100_HZ : process (i_clock) is
 begin
 if rising_edge(i_clock) then
 if r_CNT_100HZ = c_CNT_100HZ-1 then -- -1, since counter starts at 0
 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 -- -1, since counter starts at 0
 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 -- -1, since counter starts at 0
 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 -- -1, since counter starts at 0
 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;
 
 -- Create a multiplexor based on switch inputs
 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;
 
 -- Only allow o_led_drive to drive when i_enable is high (and gate).
 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;
 
 // Constants (parameters) to create the frequencies needed:
 // Input clock is 25 kHz, chosen arbitrarily.
 // Formula is: (25 kHz / 100 Hz * 50% duty cycle)
 // So for 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;
 // These signals will be the counters:
 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;
 
 // These signals will toggle at the frequencies needed:
 reg r_TOGGLE_100HZ = 1'b0;
 reg r_TOGGLE_50HZ = 1'b0;
 reg r_TOGGLE_10HZ = 1'b0;
 reg r_TOGGLE_1HZ = 1'b0;
 
 // One bit select
 reg r_LED_SELECT;
 wire w_LED_SELECT;
 

begin
 // All always blocks toggle a specific signal at a different frequency.
 // They all run continuously even if the switches are
 // not selecting their particular output.
 always @ (posedge i_clock)
 begin
 if (r_CNT_100HZ == c_CNT_100HZ-1) // -1, since counter starts at 0
 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) // -1, since counter starts at 0
 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) // -1, since counter starts at 0
 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) // -1, since counter starts at 0
 begin 
 r_TOGGLE_1HZ <= !r_TOGGLE_1HZ;
 r_CNT_1HZ <= 0;
 end
 else
 r_CNT_1HZ <= r_CNT_1HZ + 1;
 end
 // Create a multiplexer based on switch inputs
 always @ (*)
 begin
 case () // Concatenation Operator 
 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;
 // Alternative way to design multiplexer (same as above):
 // More compact, but harder to read, especially to those new to Verilog
 // 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;
 

end 

endmodule

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

VHDL

  1. 제한된 무작위 검증
  2. VHDL에서 동시 문을 만드는 방법
  3. 기본 VHDL 퀴즈 – 파트 4
  4. Pmod SSD용 VHDL 듀얼 7세그먼트 디스플레이 컨트롤러 - 손쉬운 FPGA 통합
  5. 기본 VHDL 퀴즈 – 파트 2
  6. TEXTIO를 사용하여 BMP 파일 비트맵 이미지 읽기
  7. 준비/유효한 핸드셰이크를 사용하여 블록 RAM에서 AXI FIFO를 만드는 방법
  8. VHDL에서 링 버퍼 FIFO를 만드는 방법
  9. PSL을 사용한 VHDL 형식 검증
  10. TEXTIO를 사용하여 파일에서 RAM을 초기화하는 방법