Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> VHDL

Tutorial:Seu primeiro programa FPGA:um LED piscando

Parte 1:Design de VHDL ou Verilog


Este tutorial mostra a construção do código VHDL e Verilog que pisca um LED em uma frequência especificada. Ambos VHDL e Verilog são mostrados, e você pode escolher qual deseja aprender primeiro. Sempre que o código de projeto é escrito, o projetista do FPGA precisa garantir que ele funcione da maneira que foi planejado. Apesar de seus melhores esforços, sempre haverá erros em seu projeto inicial. A melhor maneira de encontrar esses erros é em um ambiente de simulação. Este tutorial é dividido em 2 etapas:
  1. Design de HDL
  2. Simulação de HDL

Ambas as etapas são cruciais para o desenvolvimento bem-sucedido de FPGA. Às vezes, os designers de FPGA que estão com pressa tentarão pular a etapa dois, a simulação de seu código. No entanto, este é um passo extremamente importante! Sem a simulação adequada, você será forçado a depurar seu código no hardware, o que pode ser um esforço muito difícil e demorado.

Requisitos do projeto:

Projete o código HDL que piscará um LED em uma frequência especificada de 100 Hz, 50 Hz, 10 Hz ou 1 Hz. Para cada uma das frequências de intermitência, o LED será definido para 50% do ciclo de trabalho (ficará aceso metade do tempo). A frequência do LED será escolhida através de dois interruptores que são entradas para o FPGA. Há uma chave adicional chamada LED_EN que precisa ser '1' para ligar o LED. O FPGA será acionado por um oscilador de 25 MHz.

Vamos primeiro desenhar a tabela verdade para o seletor de frequência:
Ativar Alternar 1 Alternar 2 Frequência da unidade de LED 0 - - (desativado) 1 0 0 100 Hz 1 0 1 50 Hz 1 1 0 10 Hz 1 1 1 1 Hz

Para que isso funcione corretamente, serão 4 entradas e 1 saída. Os sinais serão:
Nome do sinal Direção Descrição Entrada i_clock 25 MHz Clock Entrada i_enable A Chave de habilitação (Lógica 0 =Sem unidade de LED) i_switch_1 Chave de entrada 1 na Tabela de verdade acima de i_switch_2 Chave de entrada 2 na Tabela de verdade acima de o_led_drive Saída O sinal que aciona o LED

Para o design, existem quatro processos de contador que são executados simultaneamente. Isso significa que todos eles estão sendo executados exatamente ao mesmo tempo. Seu trabalho é acompanhar o número de pulsos de clock vistos para cada uma das diferentes frequências. Mesmo que os interruptores não estejam selecionando essa frequência específica, os contadores ainda estão funcionando! Essa é a beleza do design de hardware e da simultaneidade. Tudo corre o tempo todo! Pode ser um desafio entender isso inicialmente, mas é o conceito central que você precisa dominar.

Os interruptores servem apenas para selecionar qual saída usar. Eles criam o que é conhecido como multiplexador. Um multiplexador ou mux para abreviar é um seletor que selecionará uma das várias entradas para propagar ou passar para a saída. É uma peça de lógica combinatória, o que significa que não requer um relógio para operar. Abaixo está um diagrama de blocos do projeto. Passe algum tempo pensando em como você pode implementar esse design. Tente escrever o código você mesmo. A maneira que eu escolhi fazer pode ser encontrada abaixo.
Diagrama de bloco - Programa de piscar de LED


Código VHDL para o design, 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;


Código Verilog para o design, 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 - Seu primeiro programa em C#
  2. Design integrado com FPGAs:Construindo um projeto
  3. Simplificando o design com a tecnologia FPGA incorporada
  4. Como criar seu primeiro programa VHDL:Hello World!
  5. Maximize seu programa de análise de lubrificante
  6. Tutorial Verilog
  7. Como elaborar um programa de manutenção preventiva para seu equipamento
  8. 10 hacks para melhorar seu programa de PM
  9. Tutorial de design de placa de circuito impresso do Ultiboard
  10. Tutorial de design de PCB KiCAD