Este tutorial ensina como incluir código C++ e Verilog-A em simulações no QSpice, abordando desde a criação dos blocos até a execução das simulações. Você aprenderá a integrar funcionalidades complexas, permitindo simulações de circuitos digitais e analógicos, independentemente da complexidade.

Objetivo
Instruir engenheiros e desenvolvedores na integração de módulos de código C++ e Verilog-A em simulações no QSpice, facilitando a criação de modelos de circuitos digitais e analógicos complexos.
Requisitos
- QSpice instalado.
- Conhecimento básico de programação em C++ e Verilog-A.

Passo 1: Desenhar o Bloco Inicial
Desenhe o Bloco Inicial:
Este bloco será configurado para representar uma DLL, com suporte a funções digitais e analógicas.
No QSpice, desenhe um bloco que conterá o código usando Draw Hierarchical Entry
.

Passo 2: Configuração do Bloco
Configuração do Bloco:
Clique com o botão direito no bloco desenhado no QSpice e selecione Show Symbol Properties
.
No campo Symbol Type
, altere para ∅
, indicando que o bloco será tratado como uma DLL.

Adicionar Portas
Identifique o tipo de dado da porta, como iremos lidar com valores analógicos selecione Float 64 bits.
Adicione as portas de entrada e saída organize de forma a ficar coerente com suas funções.
Nomeie cada porta, Entrada e Saída.
Selecione o tipo de porta.
É importante a ordem que se adiciona as portas, portanto comecei pela porta de entrada, e então a de saída.

Nomeação:
- Nomeie o bloco de forma clara, como “ModuloAnalise”.
Passo 3: Escrever e Compilar Código C++
Abertura da Interface C++
Se necessário, crie um template.
Clique com o botão direito no bloco e selecione C++ Interface > Open C++ Source
.
Ele irá te perguntar se deseja criar o arquivo com base num template padrão, neste caso responda sim.
Selecionando as Estruturas de código
Selecione as três primeiras opções.



Explicando o Código C++
Vamos explicar a estrutura do código C++ gerado para o QSpice e como ele interage com o circuito simulado.
- Struct
sMEUPRIMEIROCOMPONENTE
: Ostruct sMEUPRIMEIROCOMPONENTE
é uma estrutura de dados que serve como um contêiner para armazenar o estado interno do componente durante a simulação. Ele é usado para preservar informações entre as diferentes chamadas da funçãomeuprimeirocomponente
. Oopaque
, que é um ponteiro para esta estrutura, permite que a função mantenha e manipule o estado do componente entre as simulações. - Union
uData
: Aunion
uData
permite acessar diferentes tipos de dados usando a mesma área de memória. No QSpice,uData
mapeia as variáveis de simulação para os tipos corretos, comodouble
para valores de Entrada e Saída. - Função
meuprimeirocomponente
: Esta função avalia o módulo de simulação, recebendo um ponteiro parasMEUPRIMEIROCOMPONENTE
, o tempot
, e um arraydata
de tipouData
, que mapeia as portas:
cpp extern “C” __declspec(dllexport) void meuprimeirocomponente(struct sMEUPRIMEIROCOMPONENTE **opaque, double t, union uData *data) { double Entrada = data[0].d; double &Saida = data[1].d; - Uso de
uData
: Permite que o código C++ acesse as portas do componente independentemente do tipo de dado subjacente. - Inicialização de
opaque
: Seopaque
não estiver inicializado, ele é alocado e zerado usando a funçãobzero:
if(!*opaque) {
*opaque = (struct sMEUPRIMEIROCOMPONENTE *) malloc(sizeof(struct sMEUPRIMEIROCOMPONENTE));
bzero(*opaque, sizeof(struct sMEUPRIMEIROCOMPONENTE));
}
- Bloco de Inicialização com
bzero
: A funçãobzero
zera a memória alocada parasMEUPRIMEIROCOMPONENTE
, garantindo que todos os campos comecem com valores definidos.
Escrever o Código C++
Após a inicialização do ponteiro opaque
, o código que implementa a lógica do componente deve ser inserido logo após essa verificação e alocação. Este código representa a função principal do módulo, onde a lógica de simulação é implementada.
Por exemplo, se o módulo deve aplicar um ganho a um sinal de entrada, o código seria inserido da seguinte forma:
const float gain = 2.3; // Definindo o ganho internamente
Saida = Entrada * gain; // Aplicando o ganho à entrada
Neste trecho, o sinal de Entrada é multiplicado pelo valor fixo de gain para produzir o sinal de Saída. Esse código deve ser colocado logo após a inicialização do ponteiro opaque
, dentro da função meuprimeirocomponente
.
Compilar o Código
- Compile o código clicando com o botão direito no bloco e selecionando
Compile
.

Passo 4: Escrever e Compilar Código Verilog-A
Duplicar o Bloco:
- Copie o bloco criado no Passo 1 e renomeie-o para usá-lo com código Verilog-A.
Abertura da Interface Verilog-A:
- Clique com o botão direito no novo bloco e selecione
Verilog Interface > Open Verilog Source
. - Crie um template Verilog-A se necessário.
Declarar Parâmetros e Portas no Verilog-A:
- Ordem das Portas e Parâmetros: A ordem das portas no código Verilog-A deve coincidir com a ordem no esquemático do QSpice para garantir o correto mapeamento dos sinais.
- Parâmetros Internos: Parâmetros como
threshold
,high_value
, elow_value
são fixos durante a simulação. Para modificá-los, pare a simulação, ajuste os valores no código, recompile e reinicie:module analog_module(input real vin, output real vout);
parameter real threshold = 0.5;
parameter real high_value = 1.0;
parameter real low_value = 0.0;
always @(vin)
vout = (vin > threshold) ? high_value : low_value;endmodule
- Ajuste dos Parâmetros em Tempo de Simulação: Para ajustar os parâmetros durante a simulação, externalize-os através de portas:
module analog_module(input real vin, input real vthresh, output real vout);
real high_value = 1.0;
real low_value = 0.0;
always @(vin)
vout = (vin > vthresh) ? high_value : low_value; endmodule
Compilar o Código:
- Compile o código Verilog-A. Após corrigir eventuais erros, o QSpice confirmará a criação da DLL.
Passo 5: Configurar e Executar a Simulação
Configuração da Simulação:
- Conhecimento em SPICE: Para configurar a simulação corretamente, é necessário um entendimento básico do SPICE, pois o processo envolve a construção de um circuito utilizando fontes de tensão e elementos de interconexão, como resistores e capacitores.
- Adicionar Fontes de Tensão: Insira uma fonte de tensão no circuito, de preferência uma senoidal, arbitrária ou exponencial, que forneça um sinal variável. Este sinal deve ser conectado à porta de Entrada de cada bloco X1 e X2.
- Adicionar Ground: Conecte o terminal negativo da fonte de tensão a um nó de ground (terra). Este passo é fundamental, pois o SPICE exige a presença de um nó de ground como referência para realizar as simulações.
- Conexão das Portas de Saída: A porta de Saída de cada bloco deve ser conectada a um fio (wire) que não se conecta a lugar algum. Isso é necessário para que, durante a simulação, os valores nas portas de saída possam ser medidos corretamente.

Execução da Simulação:
- Execute a simulação e observe as formas de onda na Entrada e Saída dos blocos. Verifique se os resultados obtidos estão de acordo com o comportamento esperado do circuito.
Análise dos Resultados:
- Verifique se o comportamento do circuito está de acordo com as expectativas. Ajuste parâmetros e recompile, se necessário.
Exemplos Avançados
Explore o exemplo Practical Switch Mode Power Supply
no QSpice:
- Navegue até
File > Open Demo
. - Estude o exemplo para aprender como integrar modelos complexos com C++ e Verilog-A.
Dicas Avançadas
- Simulação Mista: Combine circuitos analógicos e digitais dentro do QSpice para criar simulações complexas.
- Automatização com Scripts: Use C++ para automatizar processos dentro das simulações, como detectar estados específicos e ajustar parâmetros dinamicamente.
Referências
- Engelhardt, M. (2023). How to Include C++ and Verilog in QSpice Simulations. YouTube.
- Accellera Systems Initiative. (2019). Verilog-AMS Language Reference Manual Version 2.4. Accellera.
Este tutorial foi elaborado para guiá-lo na integração de C++ e Verilog-A em suas simulações no QSpice. Se você quiser ver este tutorial em ação, convido você a assistir ao vídeo no YouTube. Não deixe de visitar o canal, inscrever-se, curtir o vídeo e comentar com suas dúvidas e sugestões. Sua participação é muito importante!
Sobre o Autor
Carlos Delfino
administrator
Um Eterno Aprendiz.
Professor de Introdução a Programação, programação com JavaScript, TypeScript, C/C++ e Python
Professor de Eletrônica Básica
Professor de programação de Microcontroladores.
Embarcatecher