Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> VHDL

Como vincular bibliotecas IP do Quartus Prime ao VUnit


Você já quis executar uma simulação VHDL que inclui um núcleo Quartus IP por meio da estrutura de verificação VUnit?

Isso é o que o engenheiro da FPGA Konstantinos Paraskevopoulos tinha em mente, mas ele não conseguiu encontrar um tutorial adequado para isso. Felizmente, ele usou seu talento para descobrir como e teve a gentileza de compartilhá-lo com o VHDLwhiz por meio este artigo convidado .

Vamos dar a palavra a Konstantinos!

Muitas vezes, é desejável incorporar IPs predefinidos do Catálogo de IPs do Quartus em seu design ao simular seu sistema com o VUnit. Assim, o tutorial a seguir visa fornecer ao leitor o conhecimento de geração, incorporação e vinculação de bibliotecas IP externas do Quartus ao ambiente VUnit.

Novo no VUnit? Confira este tutorial:Introdução ao VUnit

Visão geral


Este tutorial consiste em três partes principais:
  1. Uma breve descrição do IP selecionado
  2. Etapas necessárias para gerar e vincular as bibliotecas apropriadas
  3. Verificação usando VUnit e Modelsim

Requisitos


Também pressupõe ter conhecimento básico de VHDL e habilidades do ModelSim.

Design em teste


Para nosso cenário, utilizamos o Parallel Adder IP da lista Quartus Integer Arithmetic IP.



Nosso projeto aceita três vetores de entrada de 16 bits e gera o resultado adicionado em um vetor de 17 bits.

Etapa 1:Gerar IP


Geramos nosso somador na janela do catálogo IP clicando duas vezes no componente somador paralelo em Biblioteca/Funções básicas/Aritmética.

Depois de fornecer um nome e personalizar nosso componente com base em nossas necessidades, clicamos no botão Gerar HDL no canto inferior direito.



Neste ponto, uma janela aparecerá, conforme ilustrado na figura a seguir.

Observação: Devemos definir o Create simulation model sob o Simulation seção para VHDL ou Verilog para gerar os arquivos de simulação, pois a opção padrão é none. Se não escolhermos um, o given_ip_name.spd arquivo não será gerado, fazendo com que a próxima etapa falhe.



O processo acima gera um arquivo e uma pasta em nosso quartus diretório:
  1. Arquivo:given_ip_name.ip
  2. Pasta:given_ip_name

A pasta envolve .vhd e .v arquivos que precisam ser adicionados posteriormente em nosso run.py roteiro.

Etapa 2:gerar arquivos de simulação de IP

  1. GUI: Selecione Tools ➤ Generate Simulator Setup Script for IP e especifique o diretório de saída na janela de prompt,
  2. CMD: Utilizando os comandos do Qsys, podemos gerar os mesmos arquivos digitando no terminal o seguinte comando:

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


Usando um dos dois métodos acima, instruímos o Quartus a gerar um diretório para cada simulador suportado que contém um script para criar e compilar as bibliotecas IP.

Etapa 3:gerar e compilar bibliotecas de IP para Modelsim


O próximo passo é encontrar o msim_setup.tcl script no mentor pasta criada pela etapa anterior e duplique-a com o nome setup.tcl . Em seguida, no setup.tcl arquivo, descomente os comandos ilustrados e defina o $QSYS_SIMDIR variável.

# # 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
# #


Após alterar e salvar o setup.tcl , podemos executar com segurança o arquivo Tcl usando o vsim comando.

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


Isso gera as bibliotecas compiladas no mentor pasta.

Etapa 4:link VUnit


Agora que as bibliotecas IP foram geradas, devemos vinculá-las usando o python run.py roteiro.

Confira a figura abaixo para entender melhor a estrutura de diretórios do nosso exemplo. A topologia inicial consistia na pasta raiz demo , o tb , vunit e quartus pastas. Todas as subpastas e arquivos em quartus são geradas por meio da estrutura do Quartus após criar um projeto e concluir as etapas 1 a 3.

Observação: O Quartus gera mais arquivos e pastas, mas a imagem abaixo mostra os que nos interessam.



Usando esta visão distinta da topologia como referência, podemos especificar nosso caminho ROOT e o(s) caminho(s) para as bibliotecas geradas, conforme mostrado abaixo.

Observe que sim_files é o diretório que especificamos na etapa 2 onde a pasta do mentor foi armazenada.

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



Depois de criar uma instância VUnit chamada vu , podemos especificar uma biblioteca de design para nosso código VHDL e vincular quaisquer bibliotecas externas necessárias:
# 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")

E, finalmente, adicione nossos arquivos de origem. Eles estão localizados em três subpastas em given_ip_name diretório:
  1. parallel_add_191
  2. synth
  3. sim

O synth e sim dirs contêm as mesmas informações, ou seja, o design de nível superior do nosso IP. Porém, a formatação desses arquivos no nosso caso é em VHDL. Eles podem estar em Verilog, e isso depende do idioma escolhido na etapa 1.

Caso nosso design de nível superior envolva subcomponentes, também devemos incluir seus arquivos de origem. Eles estão localizados em subpastas no given_ip_name diretório, como o parallel_add_191 componente no nosso 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 teste


Para começar, você pode conferir este link para aprender sobre os fundamentos da formação do testbench VUnit.

De volta ao nosso testbench, adicionamos as bibliotecas VUnit necessárias junto com qualquer outra biblioteca que gostaríamos de empregar e definir nossos sinais.

Observação: A execução do processo em nosso exemplo é sequencial. Assim, os sinais de controle (chamados de bandeiras ) são usados ​​para notificar um processo se ele deve começar ou terminar.
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;


Seguindo, instanciamos nosso UUT. O Quartus fornece exemplos de instanciação de componentes para VHDL e Verilog sob as convenções de nome de arquivo ip_name_inst.vhd e 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
); 

Os dois primeiros processos iniciados são clk_process e reset_rel . Enquanto o último está suspenso após redefinir e dirigir o reset_done sinalizar para true , o clk_process opera durante todo o tempo de simulação.
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;

Agora que a redefinição foi feita, podemos invocar o test_runner processo para executar nossos testes. Além disso, o executor de teste permanece ativo até o sim_done sinalizador é direcionado para true , que ocorre no último processo.
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;


Por fim, o data_generator processo executa várias adições atribuindo valores às três entradas do nosso somador paralelo utilizando um for ciclo.

Observação: Este processo é acionado quando o test_runner o processo o instrui configurando o start_sim bandeira. Enquanto no final deste processo, ele gera o sim_done sinalizador, comandando o executor de teste para pausar a simulação.
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;

Verificação


Para executar o caso de teste e verificar se tudo funciona conforme o esperado, podemos executar o run.py script do diretório em que está localizado simplesmente digitando no terminal o seguinte comando.

python ./run.py -v


Observação: Um registrador personalizado foi usado para melhor ilustração em nossa saída, que é visível ao fornecer o verboso -v opção. Além disso, como apenas um caso de teste é definido, não precisamos fornecer uma opção para especificá-lo.



Por fim, para verificar nossos resultados no ModelSim, podemos digitar o seguinte comando:
python ./run.py --gui



(Clique na imagem para ampliá-la)

Conclusão


Para concluir, aprendemos neste tutorial sobre como incorporar e testar IPs do Quartus que residem no catálogo de IP para o VUnit. Empregamos um IP predefinido. No entanto, também podemos integrar IPs personalizados empacotados dessa maneira em nosso ambiente VUnit.


Confira este tutorial VUnit se ainda não o fez:
Introdução ao VUnit


VHDL

  1. O que é SigFox?
  2. Introdução ao VUnit
  3. Como criar uma lista de strings em VHDL
  4. Como parar a simulação em um testbench VHDL
  5. Como criar um controlador PWM em VHDL
  6. Como criar um testbench de autoverificação
  7. Como a tecnologia fornece um elo crucial nas cadeias de suprimentos éticos
  8. Máquina de esgrima de elo de corrente:como funciona e o beneficiário
  9. como escorvar a bomba de engrenagem hidráulica
  10. como preparar a bomba hidráulica do trator ford