Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Tutorial:je eerste FPGA-programma:een led-knipperlicht

Deel 1:Ontwerp van VHDL of Verilog

Deze tutorial toont de constructie van VHDL- en Verilog-code die een LED met een opgegeven frequentie knippert. Zowel VHDL als Verilog worden getoond en u kunt kiezen welke u eerst wilt leren. Telkens wanneer ontwerpcode wordt geschreven, moet de FPGA-ontwerper ervoor zorgen dat deze werkt zoals bedoeld. Ondanks je beste inspanningen, zullen er altijd fouten zijn in je eerste ontwerp. De beste manier om deze fouten te vinden is in een simulatieomgeving. Deze tutorial is opgedeeld in 2 fasen:

  1. Ontwerp van HDL
  2. Simulatie van HDL

Beide stappen zijn cruciaal voor een succesvolle FPGA-ontwikkeling. Soms proberen FPGA-ontwerpers die weinig tijd hebben, stap twee, de simulatie van hun code, over te slaan. Dit is echter een uiterst belangrijke stap! Zonder de juiste simulatie wordt u gedwongen om uw code op hardware te debuggen, wat een zeer moeilijke en tijdrovende onderneming kan zijn.

Projectvereisten:

Ontwerp HDL-code die een LED laat knipperen met een gespecificeerde frequentie van 100 Hz, 50 Hz, 10 Hz of 1 Hz. Voor elk van de knipperfrequenties wordt de LED ingesteld op 50% inschakelduur (hij brandt de helft van de tijd). De LED-frequentie wordt gekozen via twee schakelaars die ingangen zijn voor de FPGA. Er is een extra schakelaar genaamd LED_EN die '1' moet zijn om de LED in te schakelen. De FPGA wordt aangedreven door een 25 MHz-oscillator.

Laten we eerst de waarheidstabel voor de frequentiekiezer tekenen:

Inschakelen Switch 1 Switch 2 LED-aandrijffrequentie 0 - - (uitgeschakeld) 1 0 0 100 Hz 1 0 1 50 Hz 1 1 0 10 Hz 1 1 1 1 Hz

Om dit correct te laten werken, zijn er 4 ingangen en 1 uitgang. De signalen zijn:

Signaalnaam Richting Beschrijving i_clock Input 25 MHz Clock i_enable Input The Enable Switch (Logic 0 =Geen LED Drive) i_switch_1 Input Switch 1 in de Truth Table hierboven i_switch_2 Input Switch 2 in de Truth Table hierboven o_led_drive Output Het signaal dat de LED aanstuurt

Voor het ontwerp zijn er vier tegenprocessen die gelijktijdig lopen. Dit betekent dat ze allemaal op exact hetzelfde moment draaien. Het is hun taak om het aantal klokpulsen bij te houden dat voor elk van de verschillende frequenties wordt waargenomen. Zelfs als de schakelaars die specifieke frequentie niet selecteren, lopen de tellers nog steeds! Dit is het mooie van Hardware Design en gelijktijdigheid. Alles draait de hele tijd! Het kan een uitdaging zijn om dit in eerste instantie te begrijpen, maar het is het kernconcept dat u onder de knie moet krijgen.

De schakelaars dienen alleen om te selecteren welke uitgang te gebruiken. Ze creëren een zogenaamde multiplexer. Een multiplexer of kortweg mux is een selector die een van een aantal ingangen selecteert om te verspreiden of door te geven aan de uitgang. Het is een combinatorisch stukje logica, wat betekent dat er geen klok voor nodig is. Hieronder ziet u een blokschema van het ontwerp. Besteed wat tijd aan het nadenken over hoe u dit ontwerp zou kunnen implementeren. Probeer de code zelf te schrijven. De manier waarop ik heb gekozen om te doen, vind je hieronder.

Blokdiagram - LED-knipperprogramma

VHDL-code voor het ontwerp, 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-code voor het ontwerp, 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 - Uw eerste C#-programma
  2. Ingesloten ontwerp met FPGA's:een project bouwen
  3. Vereenvoudiging van het ontwerp met ingebouwde FPGA-technologie
  4. Hoe u uw eerste VHDL-programma maakt:Hello World!
  5. Hoe u uw PM-programma kunt optimaliseren
  6. Maximaliseer uw smeermiddelanalyseprogramma
  7. Verilog-zelfstudie
  8. Een preventief onderhoudsprogramma voor uw apparatuur ontwerpen?
  9. 10 hacks om uw PM-programma beter te maken
  10. Ultiboard PCB-ontwerphandleiding
  11. KiCAD PCB-ontwerphandleiding