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

Comment lier les bibliothèques IP Quartus Prime à VUnit

Avez-vous déjà souhaité exécuter une simulation VHDL incluant un cœur IP Quartus via le cadre de vérification VUnit ?

C'est ce que l'ingénieur FPGA Konstantinos Paraskevopoulos avait en tête, mais il n'a pas trouvé de tutoriel adapté. Heureusement, il a utilisé son talent pour comprendre comment et a eu la gentillesse de le partager avec VHDLwhiz via cet article invité .

Laissons la parole à Konstantinos !

Il est souvent souhaitable d'incorporer des adresses IP prédéfinies du catalogue d'adresses IP Quartus dans votre conception lors de la simulation de votre système avec VUnit. Ainsi, le didacticiel suivant vise à fournir au lecteur des connaissances sur la génération, l'incorporation et la liaison de bibliothèques IP Quartus externes à l'environnement VUnit.

Nouveau sur VUnit ? Consultez ce didacticiel :Premiers pas avec VUnit

Aperçu

Ce tutoriel se compose de trois parties principales :

  1. Une brève description de l'adresse IP sélectionnée
  2. Étapes requises pour générer et associer les bibliothèques appropriées
  3. Vérification en utilisant VUnit et Modelsim

Exigences

Cela suppose également d'avoir des connaissances de base en VHDL et des compétences ModelSim.

Conception en cours de test

Pour notre scénario, nous utilisons l'IP Parallel Adder de la liste Quartus Integer Arithmetic IP.

Notre conception accepte trois vecteurs d'entrée 16 bits et génère le résultat ajouté dans un vecteur 17 bits.

Étape 1 :Générer une adresse IP

Nous générons notre additionneur dans la fenêtre du catalogue IP en double-cliquant sur le composant additionneur parallèle sous Bibliothèque/Fonctions de base/Arithmétique.

Après avoir fourni un nom et personnalisé notre composant en fonction de nos besoins, nous cliquons sur le bouton Générer HDL en bas à droite.

À ce stade, une fenêtre apparaîtra, comme illustré dans la figure suivante.

Remarque : Il faut mettre le Create simulation model sous le Simulation section vers VHDL ou Verilog pour générer les fichiers de simulation puisque l'option par défaut est none. Si nous n'en choisissons pas, le given_ip_name.spd le fichier ne sera pas généré, ce qui entraînera l'échec de l'étape suivante.

Le processus ci-dessus génère un fichier et un dossier sous notre quartus répertoire :

  1. Fichier :given_ip_name.ip
  2. Dossier :given_ip_name

Le dossier contient .vhd et .v les fichiers qui doivent être ajoutés plus tard dans notre run.py script.

Étape 2 :Générer des fichiers de simulation IP

  1. IUG : Sélectionnez Outils ➤ Générer le script de configuration du simulateur pour IP et spécifiez le répertoire de sortie dans la fenêtre d'invite,
  2. CMD : En utilisant les commandes Qsys, nous pouvons générer les mêmes fichiers en tapant dans le terminal la commande suivante :

ip-setup-simulation --quartus-project= <project's_QPF_filepath>
--output-directory= <my_dir>

En utilisant l'une des deux méthodes ci-dessus, nous demandons à Quartus de générer un répertoire pour chaque simulateur pris en charge contenant un script pour créer et compiler les bibliothèques IP.

Étape 3 :Générer et compiler des bibliothèques IP pour Modelsim

L'étape suivante consiste à trouver le msim_setup.tcl script dans le mentor dossier créé par l'étape précédente et dupliquez-le avec le nom setup.tcl . Puis, dans le setup.tcl fichier, décommentez les commandes illustrées et définissez le $QSYS_SIMDIR variables.


# # QSYS_SIMDIR is used in the Quartus-generated IP simulation script to
# # construct paths to the files required to simulate the IP in your Quartus
# # project. By default, the IP script assumes that you are launching the
# # simulator from the IP script location. If launching from another
# # location, set QSYS_SIMDIR to the output directory you specified when you
# # generated the IP script, relative to the directory from which you launch
# # the simulator.
# #
 set QSYS_SIMDIR <script generation output directory>
# #
# # Source the generated IP simulation script.
 source $QSYS_SIMDIR/mentor/msim_setup.tcl
# #
# # Set any compilation options you require (this is unusual).
# set USER_DEFINED_COMPILE_OPTIONS <compilation options>
# set USER_DEFINED_VHDL_COMPILE_OPTIONS <compilation options for VHDL>
# set USER_DEFINED_VERILOG_COMPILE_OPTIONS <compilation options for Verilog>
# #
# # Call command to compile the Quartus EDA simulation library.
 dev_com
# #
# # Call command to compile the Quartus-generated IP simulation files.
 com
# #

Après avoir modifié et enregistré le setup.tcl , nous pouvons exécuter en toute sécurité le fichier Tcl en utilisant le vsim commande.


vsim -c -do "do setup.tcl; quit"

Cela génère les bibliothèques compilées dans le mentor dossier.

Étape 4 :Liaison VUnit

Maintenant que les bibliothèques IP ont été générées, nous devons les lier en utilisant le python run.py script.

Consultez la figure ci-dessous pour mieux comprendre la structure de répertoires de notre exemple. La topologie initiale était constituée du dossier racine demo , le tb , vunit , et quartus Dossiers. Tous les sous-dossiers et fichiers sous le quartus dossier sont générés via le framework Quartus après avoir créé un projet et effectué les étapes 1 à 3.

Remarque : Quartus génère plus de fichiers et de dossiers, mais l'image ci-dessous montre ceux qui nous intéressent.

En utilisant cette vue distincte de la topologie comme référence, nous pouvons spécifier notre chemin ROOT et le ou les chemins vers les bibliothèques générées, comme indiqué ci-dessous.

Notez que sim_files est le répertoire que nous avons spécifié à l'étape 2 où le dossier mentor a été stocké.


from vunit import VUnit
from os.path 
import join, dirname, abspath
# ROOT
root = join(dirname(__file__), '../')
# Path to generated libraries
path_2_lib = '/quartus/sim_files/mentor/libraries/'
# ROOT


Après avoir créé une instance VUnit appelée vu , nous pouvons spécifier une bibliothèque de conception pour notre code VHDL et lier toutes les bibliothèques externes requises :

# Create VUnit instance by parsing command line arguments
vu = VUnit.from_argv()
# create design's library
my_lib = vu.add_library('my_lib')
# Link external library
vu.add_external_library("parallel_adder", root + path_2_lib + "parallel_adder")

Et enfin, ajoutez nos fichiers source. Ceux-ci se trouvent dans trois sous-dossiers sous le given_ip_name répertoire :

  1. parallel_add_191
  2. synth
  3. sim

Le synth et sim dirs contiennent les mêmes informations, à savoir la conception de haut niveau de notre IP. Cependant, le formatage de ces fichiers dans notre cas est en VHDL. Ils pourraient être en Verilog, et cela dépend de la langue choisie à l'étape 1.

Dans le cas où notre conception de haut niveau implique des sous-composants, nous devons également inclure leurs fichiers source. Ils sont situés dans des sous-dossiers dans le given_ip_name répertoire, tel que le parallel_add_191 composant dans notre cas.

 
my_lib.add_source_files(join(root,'quartus','parallel_adder','sim','parallel_adder.vhd'))
my_lib.add_source_files(join(root,'quartus','parallel_adder','parallel_add_191','sim','parallel_adder_parallel_add_191_oh4guxa.vhd'))
my_lib.add_source_files(join(root,'tb','tb_demo.vhd'))
testbench = my_lib.entity("tb_demo") 
vu.main()

Banc de test

Pour commencer, vous pouvez consulter ce lien pour en savoir plus sur les bases de la formation de testbench VUnit.

De retour à notre banc d'essai, nous ajoutons les bibliothèques VUnit nécessaires ainsi que toute autre bibliothèque que nous aimerions utiliser et définir nos signaux.

Remarque : L'exécution du processus dans notre exemple est séquentielle. Ainsi, les signaux de contrôle (appelés drapeaux ) sont utilisés pour indiquer à un processus s'il doit commencer ou se terminer.

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
library vunit_lib;
context vunit_lib.vunit_context;

entity tb_demo is 
generic ( runner_cfg : string:= runner_cfg_default); 
end tb_demo;
architecture sim of tb_demo is
constant clk_period : time := 10 ns;
signal clk : std_logic := '0';
signal rst : std_logic := '0';
-- INPUTS
signal data_a : std_logic_vector(0 to 15):= (others => '0');
signal data_b : std_logic_vector(0 to 15):= (others => '0');
signal data_c : std_logic_vector(0 to 15):= (others => '0');
-- OUTPUTS
signal result : std_logic_vector(0 to 16);
-- CONTROL FLAGS
signal reset_done :boolean := false;
signal sim_done   :boolean := false;
signal start_sim  :boolean := false;

Ensuite, nous instancions notre UUT. Quartus fournit des exemples d'instanciation de composants pour VHDL et Verilog sous les conventions de nom de fichier ip_name_inst.vhd et ip_name_inst.v .

begin 
-- Unit Under Test 
UUT : entity work.parallel_adder
port map ( 
data0x => data_a, -- parallel_add_input.data0x 
data1x => data_b, --                   .data1x 
data2x => data_c, --                   .data2x 
result => result  -- parallel_add_output.result
); 

Les deux premiers processus qui commencent sont clk_process et reset_rel . Alors que ce dernier est suspendu après réinitialisation et pilotage du reset_done indicateur à true , le clk_process fonctionne pendant toute la durée de la simulation.

clk_process : process
begin 
  clk <= '1';
  wait for clk_period/2;
  clk <= '0'; 
  wait for clk_period/2; 
end process clk_process;

reset_rel : process
begin
  rst <= '1'; 
  wait for clk_period*2; 
  wait until rising_edge(clk); 
  rst <= not rst; 
  reset_done <= true; 
  wait; 
end process reset_rel;

Maintenant que la réinitialisation est terminée, nous pouvons invoquer le test_runner processus d'exécution de nos tests. De plus, le testeur reste actif jusqu'au sim_done l'indicateur est conduit à true , qui a lieu dans le dernier processus.

test_runner : process
begin
  test_runner_setup(runner, runner_cfg);
  wait until reset_done and rising_edge(clk);

  iterate : while test_suite loop
    start_sim <= true;
    if run("test_case_1") then
      info ("Start");
      info (running_test_case);
      wait until sim_done;
    end if;
  end loop;
  test_runner_cleanup(runner);
end process test_runner;

Enfin, le data_generator le processus exécute plusieurs ajouts en attribuant des valeurs aux trois entrées de notre additionneur parallèle en utilisant un for boucle.

Remarque : Ce processus est déclenché lorsque le test_runner le processus l'ordonne en configurant le start_sim drapeau. Alors qu'à la fin de ce processus, il lève le sim_done drapeau, ordonnant au testeur de mettre la simulation en pause.

data_generator : process 
  constant tag2 : log_level_t := new_log_level("INFO", fg => blue, bg => black, style => bright);
  variable a,b,c,d : integer; 
begin 
  wait until start_sim;
   wait until rising_edge(clk); 
   show(display_handler, tag2);
   if running_test_case = "test_case_1" then
     for i in 0 to 10 loop
       data_a <= std_logic_vector(to_unsigned(i+10,data_a'length));
       data_b <= std_logic_vector(to_unsigned(i+20,data_a'length));
       data_c <= std_logic_vector(to_unsigned(i+30,data_a'length)); 
       wait until rising_edge(clk); 
       a := to_integer(unsigned(data_a)); 
       b := to_integer(unsigned(data_b)); 
       c := to_integer(unsigned(data_c)); 
       d := to_integer(unsigned(result)); 
       log( integer'image(a) &" + "& integer'image(b) &" + "& integer'image(c) 
          &" = "& integer'image(d), tag2); 
     end loop;
   end if; 
   sim_done <= true;
end process data_generator;

Vérification

Pour exécuter le cas de test et vérifier que tout fonctionne comme prévu, nous pouvons exécuter le run.py script depuis le répertoire où il se trouve en tapant simplement dans le terminal la commande suivante.


python ./run.py -v

Remarque : Un enregistreur personnalisé a été utilisé pour une meilleure illustration dans notre sortie qui est visible en fournissant le verbeux -v option. De plus, comme un seul cas de test est défini, nous n'avons pas à fournir d'option pour le spécifier.

Enfin, pour vérifier nos résultats dans ModelSim, nous pourrions taper la commande suivante :

python ./run.py --gui

(Cliquez sur l'image pour l'agrandir)

Conclusion

Pour conclure, nous avons appris dans ce didacticiel comment incorporer et tester les IP Quartus qui résident dans le catalogue IP vers VUnit. Nous avons utilisé une adresse IP prédéfinie. Cependant, nous pouvons également intégrer des IP personnalisées packagées de cette manière dans notre environnement VUnit.


Consultez ce didacticiel VUnit si vous ne l'avez pas déjà :
Démarrer avec VUnit


VHDL

  1. Qu'est-ce que SigFox ?
  2. Premiers pas avec VUnit
  3. Comment créer une liste de chaînes en VHDL
  4. Comment arrêter la simulation dans un testbench VHDL
  5. Comment créer un banc d'essai d'auto-vérification
  6. Comment la technologie fournit un lien crucial dans les chaînes d'approvisionnement éthiques
  7. Chain Link Fencing Machine :Comment ça marche et le bénéficiaire
  8. comment amorcer la pompe hydraulique à engrenages
  9. comment amorcer la pompe hydraulique d'un tracteur Ford