Cómo vincular las bibliotecas IP de Quartus Prime a VUnit
¿Alguna vez ha querido ejecutar una simulación VHDL que incluya un núcleo IP de Quartus a través del marco de verificación de VUnit?
Eso es lo que tenía en mente el ingeniero de FPGA Konstantinos Paraskevopoulos, pero no pudo encontrar un tutorial adecuado para ello. Afortunadamente, usó su talento para descubrir cómo hacerlo y tuvo la amabilidad de compartirlo con VHDLwhiz a través de este artículo invitado. .
¡Démosle la palabra a Konstantinos!
A menudo es deseable incorporar direcciones IP predefinidas del catálogo de direcciones IP de Quartus en su diseño al simular su sistema con VUnit. Por lo tanto, el siguiente tutorial tiene como objetivo proporcionar al lector conocimientos sobre cómo generar, incorporar y vincular bibliotecas IP de Quartus externas al entorno VUnit.
¿Nuevo en VUnit? Consulte este tutorial:Primeros pasos con VUnit
Resumen
Este tutorial consta de tres partes principales:
- Una breve descripción de la IP seleccionada
- Pasos necesarios para generar y vincular las bibliotecas adecuadas
- Verificación utilizando VUnit y Modelsim
Requisitos
- Cuarto
- Descarga Quartus Prime
- QSYS debe estar en su RUTA para el PASO 2 (opción CMD)
- Model Sim de Intel
- Consulte este artículo para saber cómo instalar ModelSim de forma gratuita
- ModelSim debe estar en tu RUTA
- Unidad V
- Consulte este artículo para saber cómo instalar VUnit de forma gratuita
- Python 3.6 o superior
- Descarga Python
- Python debería estar en tu camino
También supone tener conocimientos básicos de VHDL y habilidades de ModelSim.
Diseño bajo prueba
Para nuestro escenario, utilizamos la IP del sumador paralelo de la lista de IP aritmética de enteros de Quartus.
Nuestro diseño acepta tres vectores de entrada de 16 bits y genera el resultado agregado en un vector de 17 bits.
Paso 1:Generar IP
Generamos nuestro sumador en la ventana del catálogo de IP haciendo doble clic en el componente del sumador paralelo en Biblioteca/Funciones básicas/Aritmética.
Después de proporcionar un nombre y personalizar nuestro componente según nuestras necesidades, hacemos clic en el botón Generar HDL en la parte inferior derecha.
En este punto, aparecerá una ventana, como se muestra en la siguiente figura.
Create simulation model
bajo el Simulation
sección a VHDL o Verilog para generar los archivos de simulación ya que la opción predeterminada es ninguno. Si no elegimos uno, el given_ip_name.spd
no se generará el archivo, lo que provocará un error en el siguiente paso.
El proceso anterior genera un archivo y una carpeta bajo nuestro quartus
directorio:
- Archivo:
given_ip_name.ip
- Carpeta:
given_ip_name
La carpeta contiene .vhd
y .v
archivos que deben agregarse más tarde en nuestro run.py
guión.
Paso 2:generar archivos de simulación de IP
- GUI: Seleccione Herramientas ➤ Generar secuencia de comandos de configuración del simulador para IP y especifique el directorio de salida en la ventana de solicitud,
- CMD: Al utilizar los comandos de Qsys, podemos generar los mismos archivos escribiendo en la terminal el siguiente comando:
ip-setup-simulation --quartus-project= <project's_QPF_filepath> --output-directory= <my_dir>
Usando uno de los dos métodos anteriores, le indicamos a Quartus que genere un directorio para cada simulador compatible que contenga un script para crear y compilar las bibliotecas IP.
Paso 3:generar y compilar bibliotecas IP para Modelsim
El siguiente paso es encontrar el msim_setup.tcl
guión en el mentor
carpeta creada por el paso anterior y duplicarla con el nombre setup.tcl
. Luego, en el setup.tcl
archivo, elimine los comentarios de los comandos ilustrados y configure el $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 # #
Después de modificar y guardar el setup.tcl
, podemos ejecutar con seguridad el archivo Tcl usando el vsim
comando.
vsim -c -do "do setup.tcl; quit"
Eso genera las bibliotecas compiladas en el mentor
carpeta.
Paso 4:enlace de VUnit
Ahora que se han generado las bibliotecas de IP, debemos vincularlas mediante el run.py
de python guión.
Consulte la figura a continuación para comprender mejor la estructura de directorios de nuestro ejemplo. La topología inicial constaba de la carpeta raíz demo
, el tb
, vunit
y quartus
carpetas Todas las subcarpetas y archivos bajo el quartus
La carpeta se genera a través del marco Quartus después de crear un proyecto y completar los pasos 1 a 3.
Usando esta vista distinta de la topología como referencia, podemos especificar nuestra ruta ROOT y la(s) ruta(s) a las bibliotecas generadas, como se muestra a continuación.
Tenga en cuenta que sim_files
es el directorio que especificamos en el paso 2 donde se ha almacenado la carpeta del mentor.
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
Después de crear una instancia de VUnit llamada vu
, podemos especificar una biblioteca de diseño para nuestro código VHDL y vincular las bibliotecas externas requeridas:
# 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")
Y finalmente, agregue nuestros archivos fuente. Estos se encuentran en tres subcarpetas bajo el given_ip_name
directorio:
parallel_add_191
synth
sim
El synth
y sim
dirs contienen la misma información, es decir, el diseño de nivel superior de nuestra IP. Sin embargo, el formateo de estos archivos en nuestro caso es en VHDL. Podrían estar en Verilog, y esto depende del idioma elegido en el paso 1.
En caso de que nuestro diseño de nivel superior implique subcomponentes, también debemos incluir sus archivos fuente. Se encuentran en subcarpetas en el given_ip_name
directorio, como el parallel_add_191
componente en nuestro caso.
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()
Banco de pruebas
Para empezar, puede consultar este enlace para conocer los conceptos básicos de la formación del banco de pruebas VUnit.
Volviendo a nuestro banco de pruebas, agregamos las bibliotecas VUnit necesarias junto con cualquier otra biblioteca que nos gustaría emplear y definir nuestras señales.
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;
A continuación, instanciamos nuestra UUT. Quartus proporciona ejemplos de creación de instancias de componentes para VHDL y Verilog bajo las convenciones de nombre de archivo ip_name_inst.vhd
y 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 );
Los primeros dos procesos que comienzan son clk_process
y reset_rel
. Mientras que este último se suspende después de reiniciar y conducir el reset_done
marcar a true
, el clk_process
opera durante todo el tiempo de simulación.
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;
Ahora que se ha realizado el reinicio, podemos invocar el test_runner
proceso para ejecutar nuestras pruebas. Además, el corredor de prueba permanece activo hasta el sim_done
la bandera se conduce a true
, que tiene lugar en el último proceso.
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;
Finalmente, el data_generator
El proceso ejecuta varias sumas asignando valores a las tres entradas de nuestro sumador paralelo utilizando un for
bucle.
test_runner
proceso lo indica configurando el start_sim
bandera. Mientras que al final de este proceso, levanta el sim_done
marca, ordenando al corredor de prueba que pause la simulación.
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;
Verificación
Para ejecutar el caso de prueba y verificar que todo funciona como se esperaba, podemos ejecutar el run.py
script del directorio en el que se encuentra simplemente escribiendo en la terminal el siguiente comando.
python ./run.py -v
-v
detallado opción. Además, dado que solo se define un caso de prueba, no tenemos que proporcionar una opción para especificarlo.
Finalmente, para verificar nuestros resultados en ModelSim, podríamos escribir el siguiente comando:
python ./run.py --gui
(Click en la imagen para agrandarla)
Conclusión
Para concluir, aprendimos en este tutorial sobre cómo incorporar y probar las IP de Quartus que residen en el catálogo de IP a VUnit. Empleamos una IP predefinida. Sin embargo, también podemos integrar IP personalizadas empaquetadas de esta manera en nuestro entorno VUnit.
Mira este tutorial de VUnit si aún no lo has hecho:
Cómo empezar con VUnit
VHDL
- ¿Qué es SigFox?
- Primeros pasos con VUnit
- Cómo crear una lista de cadenas en VHDL
- Cómo detener la simulación en un banco de pruebas VHDL
- Cómo crear un controlador PWM en VHDL
- Cómo generar números aleatorios en VHDL
- Cómo crear un banco de pruebas de autocomprobación
- Cómo la tecnología proporciona un vínculo crucial en las cadenas de suministro éticas
- Máquina de esgrima de eslabones de cadena:cómo funciona y el beneficiario
- cómo cebar la bomba hidráulica de engranajes
- cómo cebar la bomba hidráulica de un tractor ford