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:
- Ontwerp van HDL
- 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:
Om dit correct te laten werken, zijn er 4 ingangen en 1 uitgang. De signalen zijn:
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-knipperprogrammaVHDL-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
- C# Hello World - Uw eerste C#-programma
- Ingesloten ontwerp met FPGA's:een project bouwen
- Vereenvoudiging van het ontwerp met ingebouwde FPGA-technologie
- Hoe u uw eerste VHDL-programma maakt:Hello World!
- Hoe u uw PM-programma kunt optimaliseren
- Maximaliseer uw smeermiddelanalyseprogramma
- Verilog-zelfstudie
- Een preventief onderhoudsprogramma voor uw apparatuur ontwerpen?
- 10 hacks om uw PM-programma beter te maken
- Ultiboard PCB-ontwerphandleiding
- KiCAD PCB-ontwerphandleiding