Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> VHDL

Tutoriel :Votre premier programme FPGA :un clignotant LED

Partie 1 :Conception de VHDL ou Verilog

Ce didacticiel montre la construction du code VHDL et Verilog qui fait clignoter une LED à une fréquence spécifiée. VHDL et Verilog sont affichés, et vous pouvez choisir celui que vous souhaitez apprendre en premier. Chaque fois que le code de conception est écrit, le concepteur de FPGA doit s'assurer qu'il fonctionne comme prévu. Malgré tous vos efforts, il y aura toujours des erreurs dans votre conception initiale. La meilleure façon de trouver ces erreurs est dans un environnement de simulation. Ce tutoriel se décompose en 2 étapes :

  1. Conception du HDL
  2. Simulation HDL

Ces deux étapes sont cruciales pour le développement réussi d'un FPGA. Parfois, les concepteurs de FPGA pressés par le temps essaient de sauter la deuxième étape, la simulation de leur code. Mais c'est une étape extrêmement importante ! Sans simulation appropriée, vous serez obligé de déboguer votre code sur le matériel, ce qui peut être une entreprise très difficile et longue.

Exigences du projet :

Concevez un code HDL qui fera clignoter une LED à une fréquence spécifiée de 100 Hz, 50 Hz, 10 Hz ou 1 Hz. Pour chacune des fréquences de clignotement, la LED sera réglée sur un rapport cyclique de 50 % (elle sera allumée la moitié du temps). La fréquence des LED sera choisie via deux commutateurs qui sont des entrées du FPGA. Il y a un interrupteur supplémentaire appelé LED_EN qui doit être "1" pour allumer la LED. Le FPGA sera piloté par un oscillateur 25 MHz.

Dessinons d'abord la table de vérité du sélecteur de fréquence :

Activer Commutateur 1 Commutateur 2 Fréquence de commande de LED 0 - - (désactivé) 1 0 0 100 Hz 1 0 1 50 Hz 1 1 0 10 Hz 1 1 1 1 Hz

Pour que cela fonctionne correctement, il y aura 4 entrées et 1 sortie. Les signaux seront :

Nom du signal Direction Description i_clock Input Horloge 25 MHz i_enable Input Le commutateur d'activation (Logic 0 =No LED Drive) i_switch_1 Input Switch 1 dans la table de vérité ci-dessus i_switch_2 Input Switch 2 dans la table de vérité ci-dessus o_led_drive Output Le signal qui pilote la LED

Pour la conception, il existe quatre processus de compteur qui s'exécutent simultanément. Cela signifie qu'ils fonctionnent tous exactement au même moment. Leur travail consiste à suivre le nombre d'impulsions d'horloge vues pour chacune des différentes fréquences. Même si les commutateurs ne sélectionnent pas cette fréquence particulière, les compteurs fonctionnent toujours ! C'est la beauté de la conception matérielle et de la concurrence. Tout tourne tout le temps ! Il peut être difficile de comprendre cela au départ, mais c'est le concept de base que vous devez maîtriser.

Les commutateurs servent uniquement à sélectionner la sortie à utiliser. Ils créent ce qu'on appelle un multiplexeur. Un multiplexeur ou mux en abrégé est un sélecteur qui sélectionnera l'une des nombreuses entrées à propager ou à transmettre à la sortie. C'est une logique combinatoire, ce qui signifie qu'elle ne nécessite pas d'horloge pour fonctionner. Vous trouverez ci-dessous un schéma fonctionnel de la conception. Passez un peu de temps à réfléchir à la manière dont vous pourriez mettre en œuvre cette conception. Essayez d'écrire le code vous-même. La façon dont j'ai choisi de faire se trouve ci-dessous.

Schéma fonctionnel - Programme de clignotement des voyants

Code VHDL pour la conception, 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;

Code Verilog pour la conception, 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 - Votre premier programme C#
  2. Conception embarquée avec FPGA :Construire un projet
  3. Simplification de la conception avec la technologie FPGA intégrée
  4. Optimisez votre programme d'analyse de lubrifiant
  5. Tutoriel Verilog
  6. Comment concevoir un programme de maintenance préventive pour votre équipement
  7. 10 astuces pour améliorer votre programme PM
  8. Tutoriel de conception de PCB Ultiboard
  9. Tutoriel de conception de PCB KiCAD