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

튜토리얼:첫 번째 FPGA 프로그램:LED 깜박임

1부:VHDL 또는 Verilog 설계

이 튜토리얼은 지정된 주파수에서 LED를 깜박이는 VHDL 및 Verilog 코드의 구성을 보여줍니다. VHDL과 Verilog가 모두 표시되며 먼저 배우고 싶은 것을 선택할 수 있습니다. 설계 코드가 작성될 때마다 FPGA 설계자는 의도한 대로 작동하는지 확인해야 합니다. 최선의 노력에도 불구하고 초기 설계에는 항상 실수가 있습니다. 이러한 실수를 찾는 가장 좋은 방법은 시뮬레이션 환경입니다. 이 튜토리얼은 2단계로 나뉩니다:

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

이 두 단계는 성공적인 FPGA 개발에 매우 ​​중요합니다. 때때로 시간이 촉박한 FPGA 설계자는 코드 시뮬레이션인 2단계를 건너뛰려고 합니다. 그러나 이것은 매우 중요한 단계입니다! 적절한 시뮬레이션이 없으면 하드웨어에서 코드를 디버깅해야 하므로 매우 어렵고 시간이 많이 소요될 수 있습니다.

프로젝트 요구사항:

100Hz, 50Hz, 10Hz 또는 1Hz의 지정된 주파수에서 LED를 깜박이는 HDL 코드를 설계합니다. 각 깜박임 주파수에 대해 LED는 50% 듀티 사이클로 설정됩니다(시간의 절반이 켜짐). LED 주파수는 FPGA에 대한 입력인 두 개의 스위치를 통해 선택됩니다. LED를 켜려면 '1'이 되어야 하는 LED_EN이라는 추가 스위치가 있습니다. FPGA는 25MHz 발진기에 의해 구동됩니다.

먼저 주파수 선택기에 대한 진리표를 그려보겠습니다.

활성화 스위치 1 스위치 2 LED 드라이브 주파수 0 - - (비활성화됨) 1 0 0 100Hz 1 0 1 50Hz 1 1 0 10Hz 1 1 1 1Hz

이것이 올바르게 작동하려면 4개의 입력과 1개의 출력이 있어야 합니다. 신호는 다음과 같습니다.

신호 이름 방향 설명 i_clock 입력 25MHz 클록 i_enable 입력 활성화 스위치(논리 0 =LED 드라이브 없음) i_switch_1 위 진리표의 입력 스위치 1 i_switch_2 위 진리표의 입력 스위치 2 o_led_drive 출력 LED를 구동하는 신호

설계를 위해 동시에 실행되는 4개의 카운터 프로세스가 있습니다. 이것은 그들이 모두 정확히 동시에 실행되고 있음을 의미합니다. 그들의 임무는 각기 다른 주파수에서 볼 수 있는 클록 펄스의 수를 추적하는 것입니다. 스위치가 특정 주파수를 선택하지 않더라도 카운터는 계속 실행됩니다! 이것이 하드웨어 디자인과 동시성의 아름다움입니다. 모든 것은 항상 실행됩니다! 처음에는 이것을 이해하는 것이 어려울 수 있지만 마스터해야 하는 핵심 개념입니다.

스위치는 사용할 출력을 선택하는 역할만 합니다. 그들은 멀티플렉서로 알려진 것을 만듭니다. 간단히 멀티플렉서 또는 먹스는 여러 입력 중 하나를 선택하여 출력으로 전달하거나 전달하는 선택기입니다. 이것은 작동하는 데 시계가 필요하지 않다는 것을 의미하는 조합 논리입니다. 아래는 디자인의 블록 다이어그램입니다. 이 디자인을 구현하는 방법에 대해 생각하는 데 시간을 할애하십시오. 코드를 직접 작성해 보십시오. 제가 선택한 방법은 아래에서 확인하실 수 있습니다.

블록 다이어그램 - LED 깜박임 프로그램

설계용 VHDL 코드, tutorial_led_blink.vhd:

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 코드, tutorial_led_blink.v:

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 ({i_switch_1, i_switch_2}) // 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

  1. C# Hello World - 첫 번째 C# 프로그램
  2. FPGA를 사용한 임베디드 디자인:프로젝트 구축
  3. 내장형 FPGA 기술로 설계 단순화
  4. 첫 번째 VHDL 프로그램을 만드는 방법:Hello World!
  5. 윤활유 분석 프로그램 최대화
  6. Verilog 튜토리얼
  7. 장비에 대한 예방 유지보수 프로그램을 설계하는 방법
  8. PM 프로그램을 개선하는 10가지 방법
  9. Ultiboard PCB 설계 튜토리얼
  10. KiCAD PCB 설계 튜토리얼