FPGA et Chaine de Developpement
Carte Icebreaker avec FPGA LATTICE ICE40UP5k
DOCUMENTATION
https://github.com/icebreaker-fpga
Installations ( sur vos PCs persos )
Les outils logiciels utilisés sont open source.
L’open source dans la synthèse logique est récente, le site de Fabien Marteau propose un tour d’horizon complet des possibilités logicielles et matérielles.
Installation de ghdl, yosys, …
Plusieurs logiciels doivent être installés ( yosys, nextpnr, iceprog ), cela peut se faire individuellement, mais il est plus pratique d’installer l’ensemble de ces outils avec oss-cad-suite :
- Récupérer l’archive à l’adresse : oss-cad-suite
Pour Linux :
- extraire l’archive et mettre à jour la variable d’environnement $PATH ( ligne à ajouter dans le fichier ~/.bashrc ) :
export PATH="<extracted_location>/oss-cad-suite/bin:$PATH"Créer le fichier :
sudo touch /etc/udev/rules.d/53-lattice-ftdi.rules et écrire dans ce fichier ( afin de donner les droits USB ) :
sudo echo "ACTION==\"add\", ATTR{idVendor}==\"0403\", ATTR{idProduct}==\"6010\", MODE:=\"666\"">/etc/udev/rules.d/53-lattice-ftdi.rulesChaîne de développement
Avec le logiciel de simulation ghdl, le forçage des signaux d’entrée d’un composant à tester nécessite l’utilisation d’un composant testbench, à savoir un composant incluant le composant à tester
Dans notre exemple, le composant à tester est le composant icebreaker, décrit dans le fichier vhdl icebreaker.vhd.
Le test nécessite un composant icebreaker_tb, décrit dans le fichier vhdl cicebreaker_tb.vhd, dans lequel on instancie icebreaker.
| Composants | Testbench |
|
|
Sources
unzip cmp_1bit.zip
cd cmp_1bitCOMPILATION
ghdl -a icebreaker.vhd
ghdl -a icebreaker_tb.vhdSIMULATION
bash simu.sh -t icebreaker_tb -s 5ms Dans gtkwave, sélectionner l’entité à tester de plus haut niveau ( icebreaker ), et faire clic droit –> Recursive Import –> Insert
REMARQUE : dans gtkwave, pour sauvegarder la configuration , faire File –> write save file –> layout.gtkw
SYNTHESE LOGIQUE
bash build_fpga.sh -e icebreaker -p broches.pcf Application : Chenillard
Objectif : allumer successivement led1, led2, led3, pendant 1s.
Le fonctionnement du système est échelonné dans le temps, on peut donc utiliser une machine à états :
Diagramme d’états :
Valeurs de comptage :
La fréquence de l’horloge de base de la carte icebreaker est f_CLK = 12MHz
T_CLK = 83.33ns
- Durée 1s : count = = x"0B71B00"
- Durée 2s : count = = x"16E3600"
- Durée 3s : count = = x"2255100"
En simulation, ces valeurs demandant un temps de calcul trop long, on pourra considérer une fréquence de 12kHz, et donc les valeurs de comptage suivantes :
- Durée 1s : count = = x"2EE0"
- Durée 2s : count = = x"5DC0"
- Durée 3s : count = = x"BB80"
Sources
Chenillard
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity compteur is
port(
clk, reset, ce, raz : in std_logic;
count : out std_logic_vector(27 downto 0)
);
end compteur;
architecture arch_compteur of compteur is
signal count_int : unsigned(27 downto 0);
begin
process(clk, reset)
begin
if reset = '1' then
count_int <= (others => '0');
elsif rising_edge(clk) then
if raz = '1' then count_int <= (others => '0');
elsif ( ce = '1' ) then
if count_int = x"FFFFFFF" then
count_int <= (others => '0'); -- fin de comptage
else
count_int <= count_int + 1; -- "+" (unsigned, int)
end if;
end if;
end if;
end process;
count <= std_logic_vector(count_int); -- copie de count_int
end arch_compteur;
library IEEE;
use IEEE.std_logic_1164.all;
entity me is
port(
clk, reset : in std_logic;
count : in std_logic_vector(27 downto 0);
led1, led2, led3, ce, raz : out std_logic
);
end me;
architecture arch_me of me is
type etat_me is (INIT, LED_1, LED_2, LED_3);
signal etat_cr, etat_sv : etat_me;
begin
process(clk,reset) -- registre synchrone, maj etat_cr
begin
if reset='1' then etat_cr <= LED_1;
elsif rising_edge(clk) then etat_cr <= etat_sv;
end if;
end process;
process(count, etat_cr)
begin
led1 <= '0'; led2 <= '0'; led3 <= '0'; ce <= '0'; raz <= '0'; etat_sv <= etat_cr;
case etat_cr is
when INIT => etat_sv <= LED_1;
raz <= '1';
when LED_1 => if count = x"0B71B00" then etat_sv <= LED_2; end if; --"0B71B00" "0002EE0"
led1 <= '1'; ce <= '1';
when LED_2 => if count = x"16E3600" then etat_sv <= LED_3; end if; --"16E3600" "0005DC0"
led2 <= '1'; ce <= '1';
when LED_3 => if count = x"2255100" then etat_sv <= INIT; end if; --"2255100" "0008CA0"
led3 <= '1'; ce <= '1';
end case;
end process;
end arch_me;
--======================================================================
library IEEE;
use IEEE.std_logic_1164.all;
use work.all;
entity icebreaker is
port( CLK, BTN_N : std_logic ;
BTN1, BTN2 : in std_logic;
LED1, LED2, LED3 : out std_logic
);
end icebreaker;
architecture arch_icebreaker of icebreaker is
signal reset, ce, raz : std_logic;
signal count : std_logic_vector(27 downto 0);
begin
reset <= not(BTN_N);
compteur0 : entity compteur port map (
clk => CLK,
reset => reset,
ce => ce,
raz => raz,
count => count
);
me0 : entity me port map (
clk => CLK,
reset => reset,
count => count,
led1 => LED1,
led2 => LED2,
led3 => LED3,
ce => ce,
raz => raz
);
end arch_icebreaker;