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 :
- Une brève description de l'adresse IP sélectionnée
- Étapes requises pour générer et associer les bibliothèques appropriées
- Vérification en utilisant VUnit et Modelsim
Exigences
- Quartus
- Télécharger Quartus Prime
- QSYS doit se trouver dans votre PATH pour l'ÉTAPE 2 (option CMD)
- Intel Modelsim
- Veuillez vous référer à cet article pour savoir comment installer ModelSim gratuitement
- ModelSim devrait être dans votre PATH
- VUnit
- Veuillez vous référer à cet article pour savoir comment installer VUnit gratuitement
- Python 3.6 ou supérieur
- Télécharger Python
- Python devrait être sur votre chemin
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 :
- Fichier :
given_ip_name.ip
- 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
- 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,
- 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 :
parallel_add_191
synth
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
- Qu'est-ce que SigFox ?
- Premiers pas avec VUnit
- Comment créer une liste de chaînes en VHDL
- Comment arrêter la simulation dans un testbench VHDL
- Comment créer un banc d'essai d'auto-vérification
- Comment la technologie fournit un lien crucial dans les chaînes d'approvisionnement éthiques
- Chain Link Fencing Machine :Comment ça marche et le bénéficiaire
- comment amorcer la pompe hydraulique à engrenages
- comment amorcer la pompe hydraulique d'un tracteur Ford