Projeto VLSI - Guia Rápido

A integração em grande escala (VLSI) é o processo de criação de um integrated circuit (IC) combinando milhares de transistorsem um único chip. VLSI começou na década de 1970, quando complexosemiconductor e communicationtecnologias estavam sendo desenvolvidas. omicroprocessor é um dispositivo VLSI.

Antes da introdução da tecnologia VLSI, a maioria dos ICs tinha um conjunto limitado de funções que podiam executar. Aelectronic circuit pode consistir em um CPU, ROM, RAM e outro glue logic. O VLSI permite que os designers de IC adicionem tudo isso em um único chip.

A indústria eletrônica alcançou um crescimento fenomenal nas últimas décadas, principalmente devido aos rápidos avanços em tecnologias de integração em grande escala e aplicações de design de sistemas. Com o advento dos designs de integração de muito grande escala (VLSI), o número de aplicações de circuitos integrados (ICs) em computação de alto desempenho, controles, telecomunicações, processamento de imagem e vídeo e eletrônicos de consumo tem aumentado em um ritmo muito rápido.

As tecnologias de ponta atuais, como vídeo de alta resolução e baixa taxa de bits e comunicações celulares, fornecem aos usuários finais uma quantidade maravilhosa de aplicativos, poder de processamento e portabilidade. Espera-se que essa tendência cresça rapidamente, com implicações muito importantes no projeto de VLSI e no projeto de sistemas.

Fluxo de Projeto VLSI

O fluxo do projeto dos circuitos VLSI IC é mostrado na figura abaixo. Os vários níveis de design são numerados e os blocos mostram processos no fluxo de design.

As especificações vêm primeiro, elas descrevem de forma abstrata a funcionalidade, a interface e a arquitetura do circuito IC digital a ser projetado.

A descrição comportamental é então criada para analisar o projeto em termos de funcionalidade, desempenho, conformidade com determinados padrões e outras especificações.

A descrição RTL é feita usando HDLs. Esta descrição RTL é simulada para testar a funcionalidade. A partir daqui, precisamos da ajuda das ferramentas EDA.

A descrição RTL é então convertida em uma netlist de nível de porta usando ferramentas de síntese lógica. Uma netlist gatelevel é uma descrição do circuito em termos de portas e conexões entre eles, que são feitas de forma que atendam às especificações de tempo, potência e área.

Por fim, é feito um layout físico, que será verificado e enviado para fabricação.

Y Chart

O gráfico Y de Gajski-Kuhn é um modelo que captura as considerações no projeto de dispositivos semicondutores.

Os três domínios do gráfico Y de Gajski-Kuhn estão em eixos radiais. Cada um dos domínios pode ser dividido em níveis de abstração, usando anéis concêntricos.

No nível superior (anel externo), consideramos a arquitetura do chip; nos níveis inferiores (anéis internos), refinamos sucessivamente o design em uma implementação mais detalhada -

A criação de uma descrição estrutural a partir de uma descrição comportamental é obtida por meio de processos de síntese de alto nível ou síntese lógica.

A criação de uma descrição física a partir de uma estrutural é obtida por meio da síntese do layout.

Hierarquia de projeto - estrutural

A hierarquia de design envolve o princípio de "Dividir para conquistar". Nada mais é do que dividir a tarefa em tarefas menores até que ela atinja seu nível mais simples. Este processo é mais adequado porque a última evolução do design se tornou tão simples que sua fabricação se tornou mais fácil.

Podemos projetar a tarefa dada no domínio do processo de fluxo de projeto (comportamental, estrutural e geométrico). Para entender isso, vamos dar um exemplo de projeto de um somador de 16 bits, conforme mostrado na figura abaixo.

Aqui, todo o chip do somador de 16 bits é dividido em quatro módulos de somadores de 4 bits. Além disso, dividindo o somador de 4 bits em somador de 1 bit ou meio somador. A adição de 1 bit é o processo de design mais simples e seu circuito interno também é fácil de fabricar no chip. Agora, conectando todos os últimos quatro somadores, podemos projetar um somador de 4 bits e, seguindo em frente, podemos projetar um somador de 16 bits.

FPGA - Introdução

A forma completa de FPGA é "Field Programmable Gate Array”. Ele contém de dez mil a mais de um milhão de portas lógicas com interconexão programável. As interconexões programáveis ​​estão disponíveis para usuários ou projetistas executarem determinadas funções facilmente. Um chip FPGA de modelo típico é mostrado na figura fornecida. Existem blocos de E / S, que são projetados e numerados de acordo com a função. Para cada módulo de composição de nível lógico, existemCLB’s (Configurable Logic Blocks).

CLB executa a operação lógica dada ao módulo. A interconexão entre CLB e blocos de E / S é feita com a ajuda de canais de roteamento horizontal, canais de roteamento vertical e PSM (Multiplexadores Programáveis).

O número de CLB que ele contém decide apenas a complexidade do FPGA. A funcionalidade de CLBs e PSMs são projetadas por VHDL ou qualquer outra linguagem descritiva de hardware. Após a programação, CLB e PSM são colocados no chip e conectados entre si com canais de roteamento.

Vantagens

  • Requer muito pouco tempo; começando do processo de design ao chip funcional.
  • Nenhuma etapa de fabricação física está envolvida nisso.
  • A única desvantagem é que é mais caro do que outros estilos.

Projeto de matriz de portão

o gate array (GA)ocupa o segundo lugar depois do FPGA, em termos de capacidade de prototipagem rápida. Embora a programação do usuário seja importante para a implementação do design do chip FPGA, o design e o processamento da máscara de metal são usados ​​para GA. A implementação da matriz de portas requer um processo de fabricação de duas etapas.

A primeira fase resulta em uma série de transistores não comprometidos em cada chip GA. Esses chips não confirmados podem ser armazenados para personalização posterior, que é concluída definindo as interconexões de metal entre os transistores do conjunto. A padronização das interconexões metálicas é feita no final do processo de fabricação do chip, de forma que o tempo de retorno ainda possa ser curto, de alguns dias a algumas semanas. A figura abaixo mostra as etapas básicas de processamento para a implementação do array de portas.

Plataformas de gate array típicas usam áreas dedicadas chamadas canais, para roteamento entre células entre linhas ou colunas de transistores MOS. Eles simplificam as interconexões. Os padrões de interconexão que executam portas lógicas básicas são armazenados em uma biblioteca, que pode então ser usada para personalizar linhas de transistores não confirmados de acordo com a netlist.

Na maioria dos GAs modernos, várias camadas de metal são usadas para o roteamento do canal. Com o uso de várias camadas interconectadas, o roteamento pode ser realizado nas áreas de células ativas; para que os canais de roteamento possam ser removidos como nos chips Sea-of-Gates (SOG). Aqui, toda a superfície do chip é coberta com transistores nMOS e pMOS não comprometidos. Os transistores vizinhos podem ser personalizados usando uma máscara de metal para formar portas lógicas básicas.

Para roteamento entre células, alguns dos transistores não comprometidos devem ser sacrificados. Este estilo de design resulta em mais flexibilidade para interconexões e geralmente em uma densidade mais alta. O fator de utilização do chip GA é medido pela área do chip usada dividida pela área total do chip. É mais alto do que o FPGA e também a velocidade do chip.

Design baseado em células padrão

Um design baseado em célula padrão requer o desenvolvimento de um conjunto de máscara totalmente personalizado. A célula padrão também é conhecida como polycell. Nesta abordagem, todas as células lógicas comumente usadas são desenvolvidas, caracterizadas e armazenadas em uma biblioteca de células padrão.

Uma biblioteca pode conter algumas centenas de células, incluindo inversores, portas NAND, portas NOR, AOI complexo, portas OAI, travas D e flip-flops. Cada tipo de portão pode ser implementado em várias versões para fornecer capacidade de acionamento adequada para diferentes fan-outs. A porta do inversor pode ter tamanho padrão, tamanho duplo e tamanho quádruplo para que o projetista do chip possa selecionar o tamanho adequado para obter alta velocidade de circuito e densidade de layout.

Cada célula é caracterizada de acordo com várias categorias de caracterização diferentes, como,

  • Tempo de atraso versus capacitância de carga
  • Modelo de simulação de circuito
  • Modelo de simulação de tempo
  • Modelo de simulação de falha
  • Dados de celular para local e rota
  • Dados de máscara

Para posicionamento automatizado das células e roteamento, cada layout de célula é projetado com uma altura fixa, de modo que várias células possam ser delimitadas lado a lado para formar linhas. Os trilhos de alimentação e de aterramento correm paralelos aos limites superior e inferior da célula. Assim, as células vizinhas compartilham um barramento de força comum e um barramento de aterramento comum. A figura mostrada abaixo é uma planta baixa para design baseado em células padrão.

Design totalmente personalizado

Em um design totalmente personalizado, todo o design da máscara é feito novo, sem o uso de qualquer biblioteca. O custo de desenvolvimento deste estilo de design está aumentando. Assim, o conceito de reutilização de design está se tornando famoso para reduzir o tempo do ciclo de design e o custo de desenvolvimento.

O design personalizado completo mais difícil pode ser o design de uma célula de memória, seja ela estática ou dinâmica. Para design de chip lógico, uma boa negociação pode ser obtida usando uma combinação de diferentes estilos de design no mesmo chip, ou seja, células padrão, células de caminho de dados eprogrammable logic arrays (PLAs).

Na prática, o designer faz o layout personalizado completo, ou seja, a geometria, orientação e colocação de cada transistor. A produtividade do projeto geralmente é muito baixa; normalmente algumas dezenas de transistores por dia, por designer. No CMOS VLSI digital, o design totalmente personalizado dificilmente é usado devido ao alto custo de mão de obra. Esses estilos de design incluem o design de produtos de alto volume, como chips de memória, microprocessadores de alto desempenho e FPGA.

A tecnologia MOSFET complementar (CMOS) é amplamente usada hoje para formar circuitos em inúmeras e variadas aplicações. Os computadores, CPUs e telefones celulares de hoje fazem uso do CMOS devido a várias vantagens importantes. O CMOS oferece baixa dissipação de energia, velocidade relativamente alta, altas margens de ruído em ambos os estados e operará em uma ampla gama de tensões de fonte e entrada (desde que a tensão da fonte seja fixa)

Para os processos que discutiremos, o tipo de transistor disponível é o Transistor de efeito de campo semicondutor de óxido de metal (MOSFET). Esses transistores são formadosas a ‘sandwich’consistindo em uma camada semicondutora, geralmente uma fatia, ou wafer, de um único cristal de silício; uma camada de dióxido de silício (o óxido) e uma camada de metal.

Estrutura de um MOSFET

Conforme mostrado na figura, a estrutura do MOS contém três camadas -

  • The Metal Gate Electrode

  • The Insulating Oxide Layer (SiO2)

  • P – type Semiconductor (Substrate)

A estrutura do MOS forma um capacitor, com a porta e o substrato são como duas placas e a camada de óxido como o material dielétrico. A espessura do material dielétrico (SiO 2 ) é geralmente entre 10 nm e 50 nm. A concentração e distribuição do portador dentro do substrato podem ser manipuladas por voltagem externa aplicada à porta e ao terminal do substrato. Agora, para entender a estrutura do MOS, primeiro considere as propriedades elétricas básicas do substrato semicondutor do tipo P.

A concentração do portador no material semicondutor está sempre seguindo o Mass Action Law. A Lei de Ação em Massa é dada por -

$$n.p=n_{i}^{2}$$

Onde,

  • n é a concentração de portadores de elétrons

  • p é a concentração de portadores de buracos

  • ni é a concentração intrínseca de portador de silício

Agora vamos supor que o substrato é igualmente dopado com aceitador (boro) concentração N Uma . Portanto, a concentração de elétrons e lacunas no substrato tipo p é

$$n_{po}=\frac{n_{i}^{2}}{N_{A}}$$

$$p_{po}=N_{A}$$

Aqui, concentração de doping NAé (10 15 a 10 16 cm −3 ) maior do que a concentração intrínseca ni. Agora, para entender a estrutura do MOS, considere o diagrama de nível de energia do substrato de silício do tipo p.

Conforme mostrado na figura, o gap entre a banda de condução e a banda de valência é 1,1eV. Aqui, o potencial de Fermi Φ F é a diferença entre o nível de Fermi intrínseco (E i ) e o nível de Fermi (E FP ).

Onde Fermi nível E F depende da concentração de dopagem. O potencial de Fermi Φ F é a diferença entre o nível de Fermi intrínseco (E i ) e o nível de Fermi (E FP ).

Matematicamente,

$$\Phi_{Fp}=\frac{E_{F}-E_{i}}{q}$$

A diferença de potencial entre a banda de condução e o espaço livre é chamada de afinidade eletrônica e é denotada por qx.

Então, a energia necessária para um elétron se mover do nível de Fermi para o espaço livre é chamada de função de trabalho (qΦ S ) e é dada por

$$q\Phi _{s}=(E_{c}-E_{F})+qx$$

A figura a seguir mostra o diagrama da banda de energia dos componentes que compõem o MOS.

Conforme mostrado na figura acima, a camada isolante de SiO 2 tem um grande gap de energia de 8eV e a função de trabalho é de 0,95 eV. O portão de metal tem função de trabalho de 4.1eV. Aqui, as funções de trabalho são diferentes, portanto, haverá queda de tensão no sistema MOS. A figura abaixo mostra o diagrama da banda de energia combinada do sistema MOS.

Como mostrado nesta figura, o nível de potencial fermi da porta metálica e do semicondutor (Si) estão no mesmo potencial. O potencial de Fermi na superfície é chamado de potencial de superfície Φ S e é menor do que o potencial de Fermi Φ F em magnitude.

Trabalho de um MOSFET

O MOSFET consiste em um capacitor MOS com duas junções pn colocadas fechadas para a região do canal e esta região é controlada pela tensão da porta. Para tornar a polarização reversa da junção pn, o potencial do substrato é mantido mais baixo do que o potencial dos outros três terminais.

Se a tensão da porta for aumentada além da tensão limite (V GS > V TO ), a camada de inversão será estabelecida na superfície e o canal do tipo n será formado entre a fonte e o dreno. Este canal do tipo n transportará a corrente de drenagem de acordo com o valor de V DS .

Para diferentes valores de V DS , o MOSFET pode ser operado em diferentes regiões, conforme explicado abaixo.

Região Linear

Em V DS = 0, o equilíbrio térmico existe na região do canal invertido e a corrente de dreno I D = 0. Agora, se a pequena tensão de dreno, V DS > 0 for aplicada, uma corrente de dreno proporcional ao V DS começará a fluir da fonte para drenar através do canal.

O canal fornece um caminho contínuo para o fluxo de corrente da fonte ao dreno. Este modo de operação é chamadolinear region. A vista em corte transversal de um MOSFET de canal n, operando na região linear, é mostrada na figura abaixo.

No limite da região de saturação

Agora, se o V DS é aumentado, as cargas no canal e a profundidade do canal diminuem no final do dreno. Para V DS = V DSAT , as cargas no canal são reduzidas a zero, o que é chamadopinch – off point. A vista em corte transversal do MOSFET de canal n operando na borda da região de saturação é mostrada na figura abaixo.

Região de Saturação

Para V DS > V DSAT , uma superfície esgotada se forma perto do dreno e, ao aumentar a tensão de drenagem, essa região esgotada se estende até a fonte.

Este modo de operação é chamado Saturation region. Os elétrons vindos da fonte para a extremidade do canal, entram na região de drenagem - depleção e são acelerados em direção ao dreno em alto campo elétrico.

Corrente MOSFET - Características de Tensão

Para entender a característica corrente - tensão do MOSFET, é feita uma aproximação para o canal. Sem esta aproximação, a análise tridimensional do sistema MOS torna-se complexa. oGradual Channel Approximation (GCA) para corrente - característica de tensão reduzirá o problema de análise.

Aproximação Gradual de Canal (GCA)

Considere a vista em seção transversal do MOSFET do canal n operando no modo linear. Aqui, a fonte e o substrato são conectados ao solo. V S = V B = 0. A porta - a - fonte (V GS ) e de dreno - a - fonte de tensão (V DS ) de tensão são os parâmetros externos que controlam o dreno de corrente I D .

A tensão, V GS, é definida como uma tensão maior do que a tensão limite V TO , para criar um canal entre a fonte e o dreno. Conforme mostrado na figura, a direção x é perpendicular à superfície ey a direção y é paralela à superfície.

Aqui, y = 0 na extremidade da fonte, conforme mostrado na figura. A tensão do canal, em relação à fonte, é representada porVC(Y). Suponha que a tensão limite VTO seja constante ao longo da região do canal, entre y = 0 a y = L. A condição de contorno para a tensão do canal V C é -

$$V_{c}\left ( y = 0 \right ) = V_{s} = 0 \,and\,V_{c}\left ( y = L \right ) = V_{DS}$$

Também podemos assumir que

$$V_{GS}\geq V_{TO}$$ e

$$V_{GD} = V_{GS}-V_{DS}\geq V_{TO}$$

Seja Q1 (y) a carga total de elétrons móveis na camada de inversão de superfície. Esta carga do elétron pode ser expressa como -

$$Q1(y)=-C_{ox}.[V_{GS}-V_{C(Y)}-V_{TO}]$$

A figura abaixo mostra a geometria espacial da camada de inversão de superfície e indica suas dimensões. A camada de inversão diminui à medida que nos movemos do dreno para a fonte. Agora, se considerarmos a pequena região dy do comprimento do canal L, então a resistência incremental dR oferecida por esta região pode ser expressa como -

$$dR=-\frac{dy}{w.\mu _{n}.Q1(y)}$$

Aqui, o sinal negativo é devido à polaridade negativa da carga da camada de inversão Q1 e μ n é a mobilidade de superfície, que é constante. Agora, substitua o valor de Q1 (y) na equação dR -

$$dR=-\frac{dy}{w.\mu _{n}.\left \{ -C_{ox}\left [ V_{GS}-V_{C\left ( Y \right )} \right ]-V_{TO} \right \}}$$

$$dR=\frac{dy}{w.\mu _{n}.C_{ox}\left [ V_{GS}-V_{C\left ( Y \right )} \right ]-V_{TO}}$$

Agora, a queda de tensão na pequena região dy pode ser dada por

$$dV_{c}=I_{D}.dR$$

Coloque o valor de dR na equação acima

$$dV_{C}=I_{D}.\frac{dy}{w.\mu_{n}.C_{ox}\left [ V_{GS}-V_{C(Y)} \right ]-V_{TO}}$$

$$w.\mu _{n}.C_{ox}\left [ V_{GS}-V_{C(Y)}-V_{TO} \right ].dV_{C}=I_{D}.dy$$

Para obter o ID da corrente de drenagem em toda a região do canal, a equação acima pode ser integrada ao longo do canal de y = 0 a y = L e as tensões V C (y) = 0 a V C (y) = V DS ,

$$C_{ox}.w.\mu _{n}.\int_{V_{c}=0}^{V_{DS}} \left [ V_{GS}-V_{C\left ( Y \right )}-V_{TO} \right ].dV_{C} = \int_{Y=0}^{L}I_{D}.dy$$

$$\frac{C_{ox}.w.\mu _{n}}{2}\left ( 2\left [ V_{GS}-V_{TO} \right ] V_{DS}-V_{DS}^{2}\right ) = I_{D}\left [ L-0 \right ]$$

$$I_{D} = \frac{C_{ox}.\mu _{n}}{2}.\frac{w}{L}\left ( 2\left [ V_{GS}-V_{TO} \right ]V_{DS}-V_{DS}^{2} \right )$$

Para região linear V DS <V GS - V TO . Para a região de saturação, o valor de V DS é maior do que (V GS - V TO ). Portanto, para a região de saturação V DS = (V GS - V TO ).

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{\left [ 2V_{DS} \right ]V_{DS}-V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{2V_{DS}^{2}-V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{\left [ V_{GS}-V_{TO} \right ]^{2}}{L} \right )$$

O inversor é verdadeiramente o núcleo de todos os designs digitais. Uma vez que sua operação e propriedades são claramente compreendidas, o projeto de estruturas mais complexas, como portas NAND, somadores, multiplicadores e microprocessadores, é bastante simplificado. O comportamento elétrico desses circuitos complexos pode ser quase completamente derivado extrapolando os resultados obtidos para os inversores.

A análise de inversores pode ser estendida para explicar o comportamento de portas mais complexas como NAND, NOR ou XOR, que por sua vez formam os blocos de construção para módulos como multiplicadores e processadores. Neste capítulo, nos concentramos em uma única encarnação da porta do inversor, sendo o inversor CMOS estático - ou, em resumo, o inversor CMOS. Este é certamente o mais popular atualmente e, portanto, merece nossa atenção especial.

Princípio da Operação

O símbolo lógico e a tabela verdade do inversor ideal são mostrados na figura abaixo. Aqui, A é a entrada e B é a saída invertida representada por suas tensões de nó. Usando a lógica positiva, o valor booleano da lógica 1 é representado por V dd e a lógica 0 é representada por 0. V th é a tensão limite do inversor, que é V dd / 2, onde V dd é a tensão de saída.

A saída é comutada de 0 para V dd quando a entrada é menor que Vth . Assim, para 0 <V em <V, a saída é igual à entrada lógica 0 e V th <V em <V dd é igual à entrada lógica 1 do inversor.

As características mostradas na figura são ideais. A estrutura generalizada do circuito de um inversor nMOS é mostrada na figura abaixo.

A partir da figura dada, podemos ver que a tensão de entrada do inversor é igual à tensão da porta para a fonte do transistor nMOS e a tensão de saída do inversor é igual à tensão do dreno para a fonte do transistor nMOS. A tensão da fonte para o substrato do nMOS também é chamada de driver para transistor que é aterrado; então V SS = 0. O nó de saída é conectado com uma capacitância concentrada usada para VTC.

Inversor de carga resistiva

A estrutura básica de um inversor de carga resistiva é mostrada na figura abaixo. Aqui, o tipo de aprimoramento nMOS atua como o transistor de driver. A carga é constituída por uma simples resistência R linear L . A fonte de alimentação do circuito é V DD e a corrente de dreno que D é igual à corrente de carga I R .

Operação de Circuito

Quando a entrada do transistor driver é menor do que a tensão limite V TH (V in <V TH ), o transistor driver está na região de corte e não conduz nenhuma corrente. Portanto, a queda de tensão no resistor de carga é ZERO e a tensão de saída é igual a V DD . Agora, quando a tensão de entrada aumenta ainda mais, o transistor do driver começará a conduzir a corrente diferente de zero e o nMOS vai para a região de saturação.

Matematicamente,

$$I_{D} = \frac{K_{n}}{2}\left [ V_{GS}-V_{TO} \right ]^{2}$$

Aumentando ainda mais a tensão de entrada, o transistor driver entrará na região linear e a saída do transistor driver diminui.

$$I_{D} = \frac{K_{n}}{2}2\left [ V_{GS}-V_{TO} \right ]V_{DS}-V_{DS}^{2}$$

O VTC do inversor de carga resistiva, mostrado abaixo, indica o modo de operação do transistor do driver e pontos de tensão.

Inversor com Carga MOSFET tipo N

A principal vantagem de usar o MOSFET como dispositivo de carga é que a área de silício ocupada pelo transistor é menor do que a área ocupada pela carga resistiva. Aqui, o MOSFET é carga ativa e o inversor com carga ativa oferece um melhor desempenho do que o inversor com carga resistiva.

Enhancement Load NMOS

Dois inversores com dispositivo de carga do tipo aprimoramento são mostrados na figura. O transistor de carga pode ser operado tanto na região de saturação quanto na região linear, dependendo da tensão de polarização aplicada ao seu terminal de porta. O inversor de carga de reforço saturado é mostrado na fig. (uma). Ela exige uma única alimentação de tensão e processo de fabricação simples e de modo V OH está limitado ao V DD - V T .

O inversor de carga de realce linear é mostrado na fig. (b). Sempre opera em região linear; então o nível V OH é igual a V DD .

O inversor de carga linear tem maior margem de ruído em comparação com o inversor de aprimoramento saturado. Mas, a desvantagem do inversor de realce linear é que ele requer duas fontes de alimentação separadas e ambos os circuitos sofrem de alta dissipação de energia. Portanto, os inversores de aprimoramento não são usados ​​em nenhuma aplicação digital de grande escala.

NMOS de carga de esgotamento

As desvantagens do inversor de carga de aprimoramento podem ser superadas usando o inversor de carga de depleção. Comparado com o inversor de carga de reforço, o inversor de carga de depleção requer mais algumas etapas de fabricação para que o implante de canal ajuste a tensão limite de carga.

As vantagens do inversor de carga de esgotamento são - transição VTC nítida, melhor margem de ruído, fonte de alimentação única e área de layout geral menor.

Conforme mostrado na figura, o portão e o terminal de origem da carga estão conectados; Portanto, V GS = 0. Assim, a tensão limite da carga é negativa. Conseqüentemente,

$$V_{GS,load}> V_{T,load}$$ é satisfeito

Portanto, o dispositivo de carga sempre tem um canal de condução independente do nível de tensão de entrada e saída.

Quando o transistor de carga está na região de saturação, a corrente de carga é dada por

$$I_{D,load} = \frac{K_{n,load}}{2}\left [ -V_{T,load}\left ( V_{out} \right ) \right ]^{2}$$

Quando o transistor de carga está na região linear, a corrente de carga é dada por

$$I_{D,load} = \frac{K_{n,load}}{2}\left [ 2\left | V_{T,load}\left ( V_{out} \right ) \right |.\left ( V_{DD}-V_{out} \right )-\left ( V_{DD}-V_{out} \right )^{2} \right ]$$

As características de transferência de tensão do inversor de carga de depleção são mostradas na figura abaixo -

Inversor CMOS - Circuito, Operação e Descrição

O circuito inversor CMOS é mostrado na figura. Aqui, os transistores nMOS e pMOS funcionam como transistores de driver; quando um transistor está LIGADO, o outro está DESLIGADO.

Esta configuração é chamada complementary MOS (CMOS). A entrada é conectada ao terminal da porta de ambos os transistores de forma que ambos possam ser acionados diretamente com tensões de entrada. O substrato do nMOS é conectado ao aterramento e o substrato do pMOS é conectado à fonte de alimentação, V DD .

Portanto, V SB = 0 para ambos os transistores.

$$V_{GS,n}=V_{in}$$

$$V_{DS,n}=V_{out}$$

E,

$$V_{GS,p}=V_{in}-V_{DD}$$

$$V_{DS,p}=V_{out}-V_{DD}$$

Quando a entrada de nMOS é menor que a tensão de limiar (V in <V TO, n ), o nMOS é cortado e o pMOS está na região linear. Portanto, a corrente de dreno de ambos os transistores é zero.

$$I_{D,n}=I_{D,p}=0$$

Portanto, a tensão de saída V OH é igual à tensão de alimentação.

$$V_{out}=V_{OH}=V_{DD}$$

Quando a tensão de entrada é maior que V DD + V TO, p , o transistor pMOS está na região de corte e o nMOS está na região linear, então a corrente de dreno de ambos os transistores é zero.

$$I_{D,n}=I_{D,p}=0$$

Portanto, a tensão de saída V OL é igual a zero.

$$V_{out}=V_{OL}=0$$

O nMOS opera na região de saturação se V em > V TO e se as seguintes condições forem satisfeitas.

$$V_{DS,n}\geq V_{GS,n}-V_{TO,n} $$

$$V_{out}\geq V_{in}-V_{TO,n} $$

O pMOS opera na região de saturação se V em <V DD + V TO, p e se as seguintes condições forem satisfeitas.

$$V_{DS,p}\leq V_{GS,p}-V_{TO,p} $$

$$V_{out}\leq V_{in}-V_{TO,p} $$

Para valores diferentes de tensões de entrada, as regiões de operação estão listadas abaixo para ambos os transistores.

Região V em V fora nMOS pMOS
UMA <V TO, n V OH Corte fora Linear
B V IL Alto ≈ V OH Saturação Linear
C V th V th Saturação Saturação
D V IH Baixo ≈ V OL Linear Saturação
E > (V DD + V TO, p ) V OL Linear Corte fora

O VTC do CMOS é mostrado na figura abaixo -

Circuitos ou portas lógicas combinacionais, que realizam operações booleanas em várias variáveis ​​de entrada e determinam as saídas como funções booleanas das entradas, são os blocos de construção básicos de todos os sistemas digitais. Examinaremos configurações de circuito simples, como portas NAND e NOR de duas entradas, e então expandiremos nossa análise para casos mais gerais de estruturas de circuito de entrada múltipla.

A seguir, os circuitos lógicos CMOS serão apresentados de forma semelhante. Vamos enfatizar as semelhanças e diferenças entre a lógica de depleção-carga nMOS e os circuitos lógicos CMOS e apontar as vantagens das portas CMOS com exemplos. Em sua forma mais geral, um circuito lógico combinacional, ou porta, executando uma função booleana pode ser representado como um sistema de múltiplas entradas e saídas simples, conforme ilustrado na figura.

As tensões do nó, referenciadas ao potencial de terra, representam todas as variáveis ​​de entrada. Usando a convenção de lógica positiva, o valor booleano (ou lógico) de "1" pode ser representado por uma alta tensão de VDD, e o valor booleano (ou lógico) de "0" pode ser representado por uma baixa tensão de 0. A saída O nó é carregado com uma capacitância C L , que representa as capacitâncias combinadas do dispositivo parasita no circuito.

Circuitos lógicos CMOS

Porta NOR CMOS de duas entradas

O circuito consiste em uma rede n conectada em paralelo e uma rede p complementar conectada em série. As tensões de entrada V X e V Y são aplicadas às portas de um transistor nMOS e um transistor pMOS.

Quando uma ou ambas as entradas são altas, ou seja, quando a n-rede cria um caminho condutor entre o nó de saída e o solo, a p-rede é cortada. Se ambas as tensões de entrada são baixas, ou seja, a rede n é cortada, então a rede p cria um caminho condutor entre o nó de saída e a tensão de alimentação.

Para qualquer combinação de entrada, a estrutura do circuito complementar é tal que a saída é conectada ao V DD ou ao aterramento por meio de um caminho de baixa resistência e um caminho de corrente DC entre o V DD e o terra não é estabelecido para nenhuma combinação de entrada. A tensão de saída do CMOS, duas portas NOR de entrada obterá uma tensão lógica baixa de V OL = 0 e uma tensão lógica alta de V OH = V DD . A equação da tensão limiar de comutação Vth é dada por

$$V_{th}\left ( NOR2 \right ) = \frac{V_{T,n}+\frac{1}{2}\sqrt{\frac{k_{p}}{k_{n}}\left ( V_{DD}-\left | V_{T,p} \right | \right )}}{1+\frac{1}{2}\sqrt{\frac{k_{p}}{k_{n}}}}$$

Layout da porta NOR CMOS de 2 entradas

A figura mostra um layout de amostra de porta NOR CMOS de 2 entradas, usando metal de camada única e polissilício de camada única. Os recursos deste layout são -

  • Polilinhas verticais únicas para cada entrada
  • Formas ativas únicas para dispositivos N e P, respectivamente
  • Ônibus de metal na horizontal

O diagrama stick para a porta CMOS N0R2 é mostrado na figura abaixo; que corresponde diretamente ao layout, mas não contém informações W e L. As áreas de difusão são representadas por retângulos, as conexões metálicas e as linhas sólidas e os círculos, respectivamente, representam os contatos, e as tiras hachuradas representam as colunas de polissilício. O diagrama de bastão é útil para planejar a topologia de layout ideal.

Porta NAND CMOS de duas entradas

O diagrama de circuito da porta CMOS NAND de duas entradas é dado na figura abaixo.

O princípio de operação do circuito é exatamente duplo da operação NOR de duas entradas do CMOS. A n-net que consiste em dois transistores nMOS conectados em série cria um caminho condutor entre o nó de saída e o terra, se ambas as tensões de entrada forem lógicas altas. Ambos os transistores pMOS conectados paralelamente na p-net estarão desligados.

Para todas as outras combinações de entrada, um ou ambos os transistores pMOS serão LIGADOS, enquanto p-net é cortado, criando assim um caminho de corrente entre o nó de saída e a tensão da fonte de alimentação. O limite de comutação para esta porta é obtido como -

$$V_{th}\left ( NAND2 \right ) = \frac{V_{T,n}+2\sqrt{\frac{k_{p}}{k_{n}}\left ( V_{DD}-\left | V_{T,p} \right | \right )}}{1+2\sqrt{\frac{k_{p}}{k_{n}}}}$$

Os recursos deste layout são os seguintes -

  • Linhas de polissilício simples para entradas são executadas verticalmente em N e P regiões ativas.
  • Formas ativas únicas são usadas para construir dispositivos nMOS e ambos os dispositivos pMOS.
  • O barramento elétrico é executado horizontalmente na parte superior e inferior do layout.
  • Os fios de saída são horizontais para fácil conexão ao circuito vizinho.

Circuitos Lógicos Complexos

Portão lógico complexo de carga de esgotamento NMOS

Para realizar funções complexas de múltiplas variáveis ​​de entrada, as estruturas básicas de circuito e princípios de projeto desenvolvidos para NOR e NAND podem ser estendidos a portas lógicas complexas. A capacidade de realizar funções lógicas complexas, usando um pequeno número de transistores, é uma das características mais atraentes dos circuitos lógicos nMOS e CMOS. Considere a seguinte função booleana como exemplo.

$$\overline{Z=P\left ( S+T \right )+QR}$$

A porta lógica complexa de depleção-carga do nMOS usada para realizar essa função é mostrada na figura. Nesta figura, o ramo do driver nMOS esquerdo de três transistores do driver é usado para executar a função lógica P (S + T), enquanto o ramo do lado direito executa a função QR. Conectando as duas ramificações em paralelo e colocando o transistor de carga entre o nó de saída e a tensão de alimentaçãoVDD,obtemos a função complexa dada. Cada variável de entrada é atribuída a apenas um driver.

A inspeção da topologia do circuito fornece princípios de design simples da rede pull-down -

  • As operações OR são realizadas por drivers conectados em paralelo.
  • As operações AND são realizadas por drivers conectados em série.
  • A inversão é fornecida pela natureza da operação do circuito MOS.

Se todas as variáveis ​​de entrada são lógicas altas no circuito realizando a função, o driver equivalente (W/L) proporção da rede pull-down que consiste em cinco transistores nMOS é

$$\frac{W}{L}=\frac{1}{\frac{1}{\left ( W/L \right )Q}+\frac{1}{\left ( W/L \right )R}}+\frac{1}{\frac{1}{\left ( W/L \right )P}+\frac{1}{\left ( W/L \right )S+\left ( W/L \right )Q}}$$

Portas lógicas CMOS complexas

A realização da rede n, ou rede suspensa, é baseada nos mesmos princípios básicos de projeto examinados para a porta lógica complexa de esgotamento-carga nMOS. A rede pull-up pMOS deve ser a rede dupla da n-net.

Isso significa que todas as conexões paralelas na rede nMOS corresponderão a uma conexão em série na rede pMOS e todas as conexões em série na rede nMOS corresponderão a uma conexão paralela na rede pMOS. A figura mostra uma construção simples do gráfico dual p-net (pull-up) a partir do gráfico n-net (pull-down).

Cada transistor driver na rede pull-down é mostrado por ai e cada nó é mostrado por um vértice no gráfico pull-down. A seguir, um novo vértice é criado dentro de cada área confinada no gráfico pull-down e os vértices vizinhos são conectados por arestas que cruzam cada aresta no gráfico pull-down apenas uma vez. Este novo gráfico mostra a rede pull-up.

Técnica de layout usando o método de gráfico de Euler

A figura mostra a implementação CMOS de uma função complexa e seu diagrama stick feito com ordenação de porta arbitrária que fornece um layout muito não ideal para a porta CMOS.

Neste caso, a separação entre as colunas de polissilício deve permitir a separação difusão-difusão entre elas. Isso certamente consome uma quantidade considerável de área extra de silício.

Usando o caminho de Euler, podemos obter um layout ótimo. O caminho de Euler é definido como um caminho ininterrupto que atravessa cada aresta (ramo) do gráfico exatamente uma vez. Encontre o caminho de Euler no gráfico da árvore suspensa e no gráfico da árvore suspensa com ordenação idêntica das entradas.

Os circuitos lógicos são divididos em duas categorias - (a) Circuitos Combinacionais e (b) Circuitos Sequenciais.

Em circuitos combinacionais, a saída depende apenas da condição das últimas entradas.

Em circuitos sequenciais, a saída depende não apenas das entradas mais recentes, mas também da condição das entradas anteriores. Os circuitos sequenciais contêm elementos de memória.

Os circuitos sequenciais são de três tipos -

Bistable- Os circuitos biestáveis ​​têm dois pontos de operação estáveis ​​e estarão em qualquer um dos estados. Exemplo - células de memória, travas, flip-flops e registradores.

Monostable- Os circuitos monoestáveis ​​têm apenas um ponto de operação estável e, mesmo se forem temporariamente perturbados para o estado oposto, eles retornarão com o tempo ao seu ponto de operação estável. Exemplo: temporizadores, geradores de pulso.

Astable- os circuitos não têm ponto de operação estável e oscilam entre vários estados. Exemplo - oscilador em anel.

Circuitos lógicos CMOS

Trava SR baseada em Porta NOR

Se a entrada definida (S) for igual à lógica "1" e a entrada de reset é igual à lógica "0." então a saída Q será forçada a lógica "1". Enquanto$\overline{Q}$ é forçado a lógica "0". Isso significa que a trava SR será definida, independentemente de seu estado anterior.

Da mesma forma, se S é igual a "0" e R é igual a "1" então a saída Q será forçada a "0" enquanto $\overline{Q}$ é forçado a "1". Isso significa que a trava é redefinida, independentemente de seu estado mantido anteriormente. Finalmente, se ambas as entradas S e R são iguais à lógica"1" então ambas as saídas serão forçadas a lógica "0" que conflita com a complementaridade de Q e $\overline{Q}$.

Portanto, esta combinação de entrada não é permitida durante a operação normal. A tabela de verdade do Latch SR baseado em NOR é fornecida na tabela.

S R Q $\overline{Q}$ Operação
0 0 Q $\overline{Q}$ Aguarde
1 0 1 0 Conjunto
0 1 0 1 Redefinir
1 1 0 0 Não permitido

A trava SR CMOS com base na porta NOR é mostrada na figura abaixo.

Se S for igual a V OH e R for igual a V OL , ambos os transistores M1 e M2 conectados em paralelo estarão LIGADOS. A tensão no nó$\overline{Q}$assumirá um nível lógico baixo de V OL = 0.

Ao mesmo tempo, tanto M3 quanto M4 são desligados, o que resulta em uma tensão lógica de alta V OH no nó Q. Se o R for igual a V OH e o S for igual a V OL , M1 e M2 desligados e M3 e M4 ligados.

Trava SR baseada em NAND Gate

O diagrama de blocos e o esquema de nível de porta da trava SR baseada em NAND são mostrados na figura. Os pequenos círculos nos terminais de entrada S e R representam que o circuito responde aos sinais de entrada baixos ativos. A tabela verdade do latch SR baseado em NAND é fornecida na tabela

S R Q Q ′
0 0 NC NC Sem mudanças. Latch permaneceu no estado atual.
1 0 1 0 Latch SET.
0 1 0 1 Trave RESET.
1 1 0 0 Condição inválida.

Se S vai para 0 (enquanto R = 1), Q vai alto, puxando $\overline{Q}$ baixo e a trava entra no estado Set

S = 0 então Q = 1 (se R = 1)

Se R vai para 0 (enquanto S = 1), Q vai alto, puxando $\overline{Q}$ baixo e a trava é reiniciada

R = 0 então Q = 1 (se S = 1)

O estado de espera requer que S e R estejam altos. Se S = R = 0, a saída não é permitida, pois resultaria em um estado indeterminado. A trava SR CMOS com base na porta NAND é mostrada na figura.

A trava SR nMOS de carga de depleção baseada na porta NAND é mostrada na figura. A operação é semelhante à do latch CMOS NAND SR. A implementação do circuito CMOS tem baixa dissipação de energia estática e alta margem de ruído.

Circuitos lógicos CMOS

Trava SR sincronizada

A figura mostra uma trava SR baseada em NOR com um relógio adicionado. A trava responde às entradas S e R apenas quando CLK está alto.

Quando CLK está baixo, a trava mantém seu estado atual. Observe que Q muda de estado -

  • Quando S fica alto durante CLK positivo.
  • Na vanguarda CLK após mudanças em S e R durante o tempo baixo CLK.
  • Uma falha positiva em S enquanto CLK está alto
  • Quando R fica alto durante CLK positivo.

A implementação CMOS AOI de travamento SR baseado em NOR com clock é mostrada na figura. Observe que apenas 12 transistores são necessários.

  • Quando CLK é baixo, dois terminais em série na árvore N N estão abertos e dois transistores paralelos na árvore P estão LIGADOS, retendo assim o estado na célula de memória.

  • Quando o clock está alto, o circuito se torna simplesmente um latch CMOS baseado em NOR que responderá à entrada S e R.

Clocked SR Latch based on NAND Gate

O circuito é implementado com quatro portas NAND. Se este circuito for implementado com CMOS, ele requer 16 transistores.

  • A trava responde a S ou R apenas se CLK for alto.
  • Se ambos os sinais de entrada e os sinais CLK estiverem ativos alto: ou seja, a saída de trava Q será definida quando CLK = "1" S = "1" e R = "0"
  • Da mesma forma, a trava será reiniciada quando CLK = "1," S = "0" e

Quando CLK está baixo, a trava mantém seu estado atual.

Trava JK cronometrada

A figura acima mostra uma trava JK com clock, baseada em portas NAND. A desvantagem de uma trava SR é que quando S e R estão altos, seu estado de saída se torna indeterminado. A trava JK elimina esse problema usando feedback da saída para a entrada, de forma que todos os estados de entrada da tabela verdade sejam permitidos. Se J = K = 0, a trava manterá seu estado atual.

Se J = 1 e K = 0, a trava será definida na próxima transição positiva do relógio, ou seja, Q = 1, $\overline{Q}$ = 0

Se J = 0 e K = 1, a trava irá reiniciar na próxima transição positiva do relógio, ou seja, Q = 1 e $\overline{Q}$ = 0.

Se J = K = 1, a trava irá alternar na próxima transição positiva do relógio

A operação da trava JK com clock é resumida na tabela verdade fornecida na tabela.

J

K

Q

$\overline{Q}$

S

R

Q

$\overline{Q}$

Operation

0 0 0 1 1 1 0 1 Aguarde
1 0 1 1 1 0
0 1 0 1 1 1 0 1 Redefinir
1 0 1 0 0 1
1 0 0 1 0 1 1 0 Conjunto
1 0 1 1 1 0
1 1 0 1 0 1 1 0 alternancia
1 0 1 0 0 1

Implementação CMOS D Latch

A trava D é normalmente implementada com interruptores de porta de transmissão (TG), conforme mostrado na figura. A entrada TG é ativada com CLK enquanto o loop de feedback de trava TG é ativado com CLK. A entrada D é aceita quando CLK é alto. Quando CLK fica baixo, a entrada é aberta e a trava é definida com os dados D anteriores.

VHDL significa linguagem de descrição de hardware de circuito integrado de altíssima velocidade. É uma linguagem de programação usada para modelar um sistema digital por fluxo de dados, estilo de modelagem comportamental e estrutural. Esta linguagem foi introduzida pela primeira vez em 1981 para o departamento de Defesa (DoD) sob o programa VHSIC.

Descrevendo um Design

Em VHDL, uma entidade é usada para descrever um módulo de hardware. Uma entidade pode ser descrita usando,

  • Declaração de entidade
  • Architecture
  • Configuration
  • Declaração do pacote
  • Corpo da embalagem

Vamos ver o que é isso?

Declaração de Entidade

Ele define os nomes, sinais de entrada e saída e modos de um módulo de hardware.

Syntax -

entity entity_name is
   Port declaration;
end entity_name;

Uma declaração de entidade deve começar com 'entidade' e terminar com palavras-chave 'fim'. A direção será entrada, saída ou entrada.

Dentro A porta pode ser lida
Fora A porta pode ser escrita
Inout A porta pode ser lida e escrita
Amortecedor A porta pode ser lida e escrita, pode ter apenas uma fonte.

Architecture -

A arquitetura pode ser descrita usando um estilo estrutural, de fluxo de dados, comportamental ou misto.

Syntax -

architecture architecture_name of entity_name 
architecture_declarative_part;

begin
   Statements;
end architecture_name;

Aqui, devemos especificar o nome da entidade para a qual estamos escrevendo o corpo da arquitetura. As instruções de arquitetura devem estar dentro das palavras-chave 'begin' e 'énd'. A parte declarativa da arquitetura pode conter variáveis, constantes ou declaração do componente.

Modelagem de Fluxo de Dados

Neste estilo de modelagem, o fluxo de dados através da entidade é expresso usando sinal simultâneo (paralelo). As instruções simultâneas em VHDL são WHEN e GENERATE.

Além deles, atribuições usando apenas operadores (AND, NOT, +, *, sll, etc.) também podem ser usadas para construir o código.

Finalmente, um tipo especial de atribuição, chamado BLOCK, também pode ser empregado nesse tipo de código.

No código simultâneo, o seguinte pode ser usado -

  • Operators
  • A instrução WHEN (WHEN / ELSE ou WITH / SELECT / WHEN);
  • A instrução GENERATE;
  • A declaração BLOCK

Modelagem Comportamental

Neste estilo de modelagem, o comportamento de uma entidade como conjunto de instruções é executado sequencialmente na ordem especificada. Apenas as instruções colocadas dentro de PROCESS, FUNCTION ou PROCEDURE são sequenciais.

PROCESSOS, FUNCTIONS e PROCEDURES são as únicas seções de código que são executadas sequencialmente.

No entanto, como um todo, qualquer um desses blocos ainda é concorrente com quaisquer outras instruções colocadas fora dele.

Um aspecto importante do código de comportamento é que ele não se limita à lógica sequencial. Na verdade, com ele, podemos construir circuitos sequenciais, bem como circuitos combinacionais.

As declarações de comportamento são IF, WAIT, CASE e LOOP. VARIÁVEIS também são restritas e devem ser usadas apenas em código sequencial. VARIABLE nunca pode ser global, portanto, seu valor não pode ser transmitido diretamente.

Modelagem Estrutural

Nesta modelagem, uma entidade é descrita como um conjunto de componentes interconectados. Uma instrução de instanciação de componente é uma instrução simultânea. Portanto, a ordem dessas declarações não é importante. O estilo estrutural de modelagem descreve apenas uma interconexão de componentes (vistos como caixas pretas), sem implicar em nenhum comportamento dos próprios componentes nem da entidade que eles representam coletivamente.

Na modelagem estrutural, o corpo da arquitetura é composto de duas partes - a parte declarativa (antes do início da palavra-chave) e a parte da instrução (após o início da palavra-chave).

Operação lógica - E GATE

X Y Z
0 0 0
0 1 0
1 0 0
1 1 1

VHDL Code:
Library ieee;
use ieee.std_logic_1164.all;

entity and1 is
   port(x,y:in bit ; z:out bit);
end and1;

architecture virat of and1 is
begin
   z<=x and y; 
end virat;

Formas de onda

Operação lógica - OR Gate

X Y Z
0 0 0
0 1 1
1 0 1
1 1 1

VHDL Code: 
Library ieee; 
use ieee.std_logic_1164.all;  

entity or1 is
   port(x,y:in bit ; z:out bit); 
end or1; 
 
architecture virat of or1 is
begin
   z<=x or y; 
end virat;

Formas de onda

Operação lógica - NÃO Gate

X Y
0 1
1 0

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all; 
 
entity not1 is
   port(x:in bit ; y:out bit); 
end not1; 
 
architecture virat of not1 is
begin
   y<=not x;
end virat;

Formas de onda

Operação lógica - NAND Gate

X Y z
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all; 

entity nand1 is
   port(a,b:in bit ; c:out bit); 
end nand1; 
 
architecture virat of nand1 is
begin
   c<=a nand b; 
end virat;

Formas de onda

Operação lógica - Porta NOR

X Y z
0 0 1
0 1 0
1 0 0
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all; 
 
entity nor1 is
   port(a,b:in bit ; c:out bit); 
end nor1; 
 
architecture virat of nor1 is
begin
   c<=a nor b;
end virat;

Formas de onda

Operação lógica - XOR Gate

X Y Z
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all;
  
entity xor1 is
   port(a,b:in bit ; c:out bit); 
end xor1;
  
architecture virat of xor1 is
begin
   c<=a xor b; 
end virat;

Formas de onda

Operação lógica - X-NOR Gate

X Y Z
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all; 

entity xnor1 is
   port(a,b:in bit ; c:out bit); 
end xnor1; 
 
architecture virat of xnor1 is
begin
   c<=not(a xor b); 
end virat;

Formas de onda

Este capítulo explica a programação VHDL para circuitos combinacionais.

Código VHDL para um meio-somador

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all;
  
entity half_adder is
   port(a,b:in bit; sum,carry:out bit); 
end half_adder; 
 
architecture data of half_adder is
begin
   sum<= a xor b;  
   carry <= a and b;  
end data;

Formas de onda

Código VHDL para um Full Adder

Library ieee; 
use ieee.std_logic_1164.all;
 
entity full_adder is port(a,b,c:in bit; sum,carry:out bit); 
end full_adder;
  
architecture data of full_adder is
begin
   sum<= a xor b xor c; 
   carry <= ((a and b) or (b and c) or (a and c)); 
end data;

Formas de onda

Código VHDL para um meio subtrator

Library ieee;
use ieee.std_logic_1164.all;
  
entity half_sub is
   port(a,c:in bit; d,b:out bit);
end half_sub;  

architecture data of half_sub is
begin
   d<= a xor c;
   b<= (a and (not c));
end data;

Formas de onda

Código VHDL para um Subtrator Completo

Library ieee; 
use ieee.std_logic_1164.all;
  
entity full_sub is
   port(a,b,c:in bit; sub,borrow:out bit); 
end full_sub; 
 
architecture data of full_sub is
begin
   sub<= a xor b xor c; 
   borrow <= ((b xor c) and (not a)) or (b and c); 
end data;

Formas de onda

Código VHDL para um multiplexador

Library ieee; 
use ieee.std_logic_1164.all;
  
entity mux is
   port(S1,S0,D0,D1,D2,D3:in bit; Y:out bit);
end mux;
  
architecture data of mux is
begin 
   Y<= (not S0 and not S1 and D0) or 
      (S0 and not S1 and D1) or 
      (not S0 and S1 and D2) or
      (S0 and S1 and D3); 
end data;

Formas de onda

Código VHDL para um Demultiplexador

Library ieee; 
use ieee.std_logic_1164.all;
  
entity demux is
   port(S1,S0,D:in bit; Y0,Y1,Y2,Y3:out bit); 
end demux;
  
architecture data of demux is
begin 
   Y0<=  ((Not S0) and (Not S1) and D); 
   Y1<=  ((Not S0) and S1 and D); 
   Y2<=  (S0 and (Not S1) and D); 
   Y3<=  (S0 and S1 and D); 
end data;

Formas de onda

Código VHDL para um codificador 8 x 3

library ieee; 
use ieee.std_logic_1164.all; 
 
entity enc is
   port(i0,i1,i2,i3,i4,i5,i6,i7:in bit; o0,o1,o2: out bit); 
end enc; 
 
architecture vcgandhi of enc is
begin 
   o0<=i4 or i5 or i6 or i7; 
   o1<=i2 or i3 or i6 or i7; 
   o2<=i1 or i3 or i5 or i7; 
end vcgandhi;

Formas de onda

Código VHDL para um decodificador 3 x 8

library ieee; 
use ieee.std_logic_1164.all;

entity dec is
   port(i0,i1,i2:in bit; o0,o1,o2,o3,o4,o5,o6,o7: out bit); 
end dec; 
 
architecture vcgandhi of dec is
begin 
   o0<=(not i0) and (not i1) and (not i2); 
   o1<=(not i0) and (not i1) and i2; 
   o2<=(not i0) and i1 and (not i2); 
   o3<=(not i0) and i1 and i2; 
   o4<=i0 and (not i1) and (not i2); 
   o5<=i0 and (not i1) and i2; 
   o6<=i0 and i1 and (not i2); 
   o7<=i0 and i1 and i2; 
end vcgandhi;

Formas de onda

Código VHDL - somador paralelo de 4 bits

library IEEE; 
use IEEE.STD_LOGIC_1164.all;
  
entity pa is
   port(a : in STD_LOGIC_VECTOR(3 downto 0);
      b : in STD_LOGIC_VECTOR(3 downto 0);
      ca : out STD_LOGIC;
      sum : out STD_LOGIC_VECTOR(3 downto 0) 
   ); 
end pa; 
 
architecture vcgandhi of pa is
   Component fa is
      port (a : in STD_LOGIC; 
         b : in STD_LOGIC; 
         c : in STD_LOGIC; 
         sum : out STD_LOGIC; 
         ca : out STD_LOGIC
      ); 
   end component;         
   signal s : std_logic_vector (2 downto 0); 
   signal temp: std_logic;
begin 
   temp<='0'; 
   u0 : fa port map (a(0),b(0),temp,sum(0),s(0)); 
   u1 : fa port map (a(1),b(1),s(0),sum(1),s(1)); 
   u2 : fa port map (a(2),b(2),s(1),sum(2),s(2));
   ue : fa port map (a(3),b(3),s(2),sum(3),ca);  
end vcgandhi;

Formas de onda

Código VHDL - Verificador de Paridade de 4 bits

library ieee; 
use ieee.std_logic_1164.all; 
 
entity parity_checker is 
   port (a0,a1,a2,a3 : in std_logic; 
      p : out std_logic); 
end parity_checker;  

architecture vcgandhi of parity_checker is 
begin    
   p <= (((a0 xor a1) xor a2) xor a3); 
end vcgandhi;

Formas de onda

Código VHDL - Gerador de Paridade de 4 bits

library ieee;
use ieee.std_logic_1164.all;

entity paritygen is
   port (a0, a1, a2, a3: in std_logic; p_odd, p_even: out std_logic);
end paritygen;  

architecture vcgandhi of paritygen is
begin
   process (a0, a1, a2, a3)
   
	if (a0 ='0' and a1 ='0' and a2 ='0' and a3 =’0’)
      then odd_out <= "0";
      even_out <= "0";
   else
      p_odd <= (((a0 xor a1) xor a2) xor a3);
      p_even <= not(((a0 xor a1) xor a2) xor a3);  
end vcgandhi

Formas de onda

Este capítulo explica como fazer a programação VHDL para circuitos sequenciais.

Código VHDL para uma trava SR

library ieee; 
use ieee.std_logic_1164.all;
  
entity srl is 
   port(r,s:in bit; q,qbar:buffer bit); 
end srl;  

architecture virat of srl is 
   signal s1,r1:bit; 
begin 
   q<= s nand qbar; 
   qbar<= r nand q; 
end virat;

Formas de onda

Código VHDL para uma trava D

library ieee; 
use ieee.std_logic_1164.all;

entity Dl is 
   port(d:in bit; q,qbar:buffer bit); 
end Dl; 
 
architecture virat of Dl is 
   signal s1,r1:bit; 
begin 
   q<= d nand qbar; 
   qbar<= d nand q; 
end virat;

Formas de onda

Código VHDL para um SR Flip Flop

library ieee; 
use ieee.std_logic_1164.all;
  
entity srflip is 
   port(r,s,clk:in bit; q,qbar:buffer bit); 
end srflip;
  
architecture virat of srflip is 
   signal s1,r1:bit; 
begin 
   s1<=s nand clk; 
   r1<=r nand clk;
   q<= s1 nand qbar;
   qbar<= r1 nand q;
end virat;

Formas de onda

Código VHDL para um flip-flop JK

library IEEE; 
use IEEE.STD_LOGIC_1164.all;  

entity jk is 
   port(
      j : in STD_LOGIC; 
      k : in STD_LOGIC; 
      clk : in STD_LOGIC; 
      reset : in STD_LOGIC; 
      q : out STD_LOGIC; 
      qb : out STD_LOGIC 
   ); 
end jk;
  
architecture virat of jk is 
begin 
   jkff : process (j,k,clk,reset) is 
   variable m : std_logic := '0'; 
   
   begin 
      if (reset = '1') then 
         m : = '0'; 
      elsif (rising_edge (clk)) then 
         if (j/ = k) then
            m : = j; 
         elsif (j = '1' and k = '1') then 
            m : = not m; 
         end if; 
      end if; 
      
      q <= m; 
      qb <= not m; 
   end process jkff; 
end virat;

Formas de onda

Código VHDL para um D Flip Flop

Library ieee; 
use ieee.std_logic_1164.all;  

entity dflip is 
   port(d,clk:in bit; q,qbar:buffer bit); 
end dflip; 
 
architecture virat of dflip is 
   signal d1,d2:bit; 
begin 
   d1<=d nand clk; 
   d2<=(not d) nand clk; 
   q<= d1 nand qbar; 
   qbar<= d2 nand q; 
end virat;

Formas de onda

Código VHDL para um T Flip Flop

library IEEE; 
use IEEE.STD_LOGIC_1164.all;  

entity Toggle_flip_flop is 
   port( 
      t : in STD_LOGIC; 
      clk : in STD_LOGIC; 
      reset : in STD_LOGIC; 
      dout : out STD_LOGIC
   ); 
end Toggle_flip_flop;  

architecture virat of Toggle_flip_flop is 
begin 
   tff : process (t,clk,reset) is 
   variable m : std_logic : = '0'; 
   
   begin 
      if (reset = '1') then 
         m : = '0'; 
      elsif (rising_edge (clk)) then 
         if (t = '1') then 
            m : = not m;        
         end if; 
      end if; 
      dout < = m; 
   end process tff; 
end virat;

Formas de onda

Código VHDL para um contador ascendente de 4 bits

library IEEE; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all;
  
entity counter is 
   port(Clock, CLR : in std_logic; 
      Q : out std_logic_vector(3 downto 0)
   ); 
end counter;  

architecture virat of counter is 
   signal tmp: std_logic_vector(3 downto 0); 
begin 
   process (Clock, CLR) 
   
   begin 
      if (CLR = '1') then 
         tmp < = "0000"; 
      elsif (Clock'event and Clock = '1') then 
         mp <= tmp + 1; 
      end if; 
   end process; 
   Q <= tmp; 
end virat;

Formas de onda

Código VHDL para um contador inferior de 4 bits

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all;
  
entity dcounter is 
   port(Clock, CLR : in std_logic; 
      Q : out std_logic_vector(3 downto 0)); 
end dcounter; 
 
architecture virat of dcounter is 
   signal tmp: std_logic_vector(3 downto 0); 

begin 
   process (Clock, CLR) 
   begin 
      if (CLR = '1') then 
         tmp <= "1111"; 
      elsif (Clock'event and Clock = '1') then 
         tmp <= tmp - 1; 
      end if; 
   end process; 
   Q <= tmp; 
end virat;

Formas de onda

Verilog é uma LINGUAGEM DE DESCRIÇÃO DE HARDWARE (HDL). É uma linguagem usada para descrever um sistema digital como um switch de rede ou um microprocessador ou uma memória ou um flip-flop. Isso significa que, ao usar um HDL, podemos descrever qualquer hardware digital em qualquer nível. Os projetos, que são descritos em HDL, são independentes da tecnologia, muito fáceis de projetar e depurar e normalmente são mais úteis do que os esquemas, especialmente para grandes circuitos.

Verilog oferece suporte a um design em vários níveis de abstração. Os três principais são -

  • Nível comportamental
  • Nível de transferência de registro
  • Nível do portão

Nível comportamental

Este nível descreve um sistema por algoritmos concorrentes (comportamentais). Todo algoritmo é sequencial, o que significa que consiste em um conjunto de instruções que são executadas uma a uma. Funções, tarefas e blocos são os elementos principais. Não há consideração pela realização estrutural do projeto.

Nível de Registro-Transferência

Projetos usando o nível de transferência de registro especificam as características de um circuito usando operações e a transferência de dados entre os registros. A definição moderna de um código RTL é "Qualquer código sintetizável é chamado de código RTL".

Nível do portão

No nível lógico, as características de um sistema são descritas por links lógicos e suas propriedades de temporização. Todos os sinais são sinais discretos. Eles só podem ter valores lógicos definidos (`0 ',` 1', `X ',` Z`). As operações utilizáveis ​​são primitivas lógicas predefinidas (portas básicas). A modelagem de nível de porta pode não ser uma ideia certa para o projeto lógico. O código de nível de portão é gerado usando ferramentas como ferramentas de síntese e sua netlist é usada para simulação de nível de portão e backend.

Tokens lexicais

Os arquivos de texto de origem do idioma Verilog são um fluxo de tokens lexicais. Um token consiste em um ou mais caracteres e cada caractere está em exatamente um token.

Os tokens lexicais básicos usados ​​pelo Verilog HDL são semelhantes aos da linguagem de programação C. Verilog diferencia maiúsculas de minúsculas. Todas as palavras-chave estão em minúsculas.

Espaço em Branco

Os espaços em branco podem conter caracteres para espaços, tabulações, novas linhas e avanços de formulário. Esses caracteres são ignorados, exceto quando servem para separar tokens.

Os caracteres de espaço em branco são Espaço em branco, Tabulações, Retornos de carro, Nova linha e Avanços de formulário.

Comentários

Existem duas formas de representar os comentários

  • 1) Comentários de linha única começam com o token // e terminam com retorno de carro.

Ex .: // esta é uma sintaxe de linha única

  • 2) Os comentários de várias linhas começam com o token / * e terminam com o token * /

Ex .: / * esta é uma sintaxe multilinha * /

Números

Você pode especificar um número em formato binário, octal, decimal ou hexadecimal. Os números negativos são representados em números de complemento de 2. Verilog permite números inteiros, números reais e números com sinal e sem sinal.

A sintaxe é fornecida por - <size> <radix> <value>

O tamanho ou número não dimensionado pode ser definido em <Size> e <radix> define se é binário, octal, hexadecimal ou decimal.

Identificadores

Identificador é o nome usado para definir o objeto, como uma função, módulo ou registro. Os identificadores devem começar com caracteres alfabéticos ou sublinhados. Ex. A_Z, a_z, _

Os identificadores são uma combinação de caracteres alfabéticos, numéricos, sublinhados e $. Eles podem ter até 1.024 caracteres.

Operadores

Operadores são caracteres especiais usados ​​para colocar condições ou operar as variáveis. Existem um, dois e às vezes três caracteres usados ​​para realizar operações em variáveis.

Ex. >, +, ~, &! =

Palavras-chave Verilog

Palavras que têm significado especial em Verilog são chamadas de palavras-chave Verilog. Por exemplo, atribua, caso, enquanto, fio, reg, e, ou, nand e módulo. Eles não devem ser usados ​​como identificadores. As palavras-chave Verilog também incluem diretivas de compilador e tarefas e funções do sistema.

Modelagem de nível de portão

Verilog tem primitivas embutidas como portas lógicas, portas de transmissão e interruptores. Eles raramente são usados ​​para trabalhos de design, mas são usados ​​no mundo da pós-síntese para modelagem de células ASIC / FPGA.

A modelagem ao nível do portão exibe duas propriedades -

Drive strength- A força das portas de saída é definida pela força do drive. A saída é mais forte se houver uma conexão direta com a fonte. A força diminui se a conexão for por meio de um transistor condutor e, pelo menos, quando conectado por meio de um resistivo pull-up / down. A força da unidade geralmente não é especificada, caso em que a força é padronizada como forte1 e forte0.

Delays- Se os atrasos não forem especificados, as portas não terão atrasos de propagação; se dois atrasos forem especificados, o primeiro representa o atraso de subida e o segundo, o atraso de queda; se apenas um atraso for especificado, então ambos, aumento e queda são iguais. Atrasos podem ser ignorados na síntese.

Gate Primitivos

As portas lógicas básicas usando uma saída e muitas entradas são usadas em Verilog. GATE usa uma das palavras-chave - and, nand, or, nor, xor, xnor para uso em Verilog para um número de entradas e 1 saída.

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0)

Transmission Gate Primitivos

As primitivas de porta de transmissão incluem buffers e inversores. Eles têm uma única entrada e uma ou mais saídas. Na sintaxe de instanciação de porta mostrada abaixo, GATE significa a palavra-chave buf ou NOT gate.

Exemplo: Not, buf, bufif0, bufif1, notif0, notif1

Inversor de saída não - n

Buf - buffer de saída n

Bufifo - buffer tristate, ativo baixo habilitar

Bufif1 - buffer tristate, ativo alto habilitar

Notifo - inversor tristate, habilitação baixa ativa

Notif1 - inversor tristate, habilitar alto ativo

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0);

Tipos de dados

Conjunto de valores

Verilog consiste, principalmente, em quatro valores básicos. Todos os tipos de dados Verilog, que são usados ​​em Verilog, armazenam esses valores -

0 (zero lógico ou condição falsa)

1 (lógica um ou condição verdadeira)

x (valor lógico desconhecido)

z (estado de alta impedância)

o uso de x e z é muito limitado para síntese.

Fio

Um fio é usado para representar um fio físico em um circuito e é usado para conexão de portas ou módulos. O valor de um fio só pode ser lido e não atribuído em uma função ou bloco. Um fio não pode armazenar valor, mas é sempre conduzido por uma instrução de atribuição contínua ou conectando o fio à saída de um portão / módulo. Outros tipos específicos de fios são -

Wand (wired-AND) - aqui o valor de Wand depende do AND lógico de todos os drivers de dispositivo conectados a ele.

Wor (wired-OR) - aqui o valor de um Wor depende do OR lógico de todos os drivers de dispositivo conectados a ele.

Tri (three-state) - aqui todos os drivers conectados a um tri devem ser z, exceto apenas um (que determina o valor de tri).

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list;

Registro

Um reg (registro) é um objeto de dados, que mantém o valor de uma atribuição procedural para a próxima e é usado apenas em diferentes funções e blocos procedurais. Um reg é um Verilog simples, registrador de tipo variável e não pode implicar em um registro físico. Em registradores de vários bits, os dados são armazenados na forma de números sem sinal e a extensão do sinal não é usada.

Exemplo -

reg c; // única variável de registro de 1 bit

gema reg [5: 0]; // um vetor de 6 bits;

reg [6: 0] d, e; // duas variáveis ​​de 7 bits

Entrada, Saída, Entrada

Essas palavras-chave são usadas para declarar portas de entrada, saída e bidirecionais de uma tarefa ou módulo. Aqui, as portas de entrada e saída, que são do tipo fio, e a porta de saída, são configuradas para serem do tipo fio, reg, varinha, wor ou tri. Sempre, o padrão é o tipo de fio.

Example

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

Inteiro

Os inteiros são usados ​​em variáveis ​​de propósito geral. Eles são usados ​​principalmente em loops-indicies, constantes e parâmetros. Eles são do tipo de dados do tipo 'reg'. Eles armazenam dados como números assinados, enquanto os tipos reg declarados explicitamente os armazenam como dados não assinados. Se o número inteiro não for definido no momento da compilação, o tamanho padrão será 32 bits.

Se um inteiro contém uma constante, o sintetizador os ajusta para a largura mínima necessária no momento da compilação.

Example

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable.

Supply0, Supply1

Supply0 define os fios ligados à lógica 0 (terra) e a fonte1 define os fios ligados à lógica 1 (energia).

Example

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

Tempo

O tempo é uma quantidade de 64 bits que pode ser usada em conjunto com a tarefa do sistema $ time para manter o tempo de simulação. O tempo não é compatível com a síntese e, portanto, é usado apenas para fins de simulação.

Example

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

Parâmetro

Um parâmetro é definir uma constante que pode ser definida quando você usa um módulo, o que permite a personalização do módulo durante o processo de instanciação.

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end

Operadores

Operadores aritméticos

Esses operadores realizam operações aritméticas. Os + e −são usados ​​como operadores unários (x) ou binários (z − y).

Os operadores incluídos na operação aritmética são -

+ (adição), - (subtração), * (multiplicação), / (divisão),% (módulo)

Example -

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

Operadores Relacionais

Esses operadores comparam dois operandos e retornam o resultado em um único bit, 1 ou 0.

As variáveis ​​de fio e reg são positivas. Assim (−3'd001) = = 3'd111 e (−3b001)> 3b110.

Os operadores que estão incluídos na operação relacional são -

  • == (igual a)
  • ! = (diferente de)
  • > (maior que)
  • > = (maior ou igual a)
  • <(menos que)
  • <= (menor ou igual a)

Example

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

Operadores bit a bit

Operadores bit a bit que estão fazendo uma comparação bit a bit entre dois operandos.

Os operadores incluídos na operação bit a bit são -

  • & (bit a bit AND)
  • | (OR bit a bit)
  • ~ (NÃO bit a bit)
  • ^ (XOR bit a bit)
  • ~ ^ ou ^ ~ (XNOR bit a bit)

Example

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module

Operadores lógicos

Os operadores lógicos são operadores bit a bit e são usados ​​apenas para operandos de bit único. Eles retornam um único valor de bit, 0 ou 1. Eles podem trabalhar com inteiros ou grupos de bits, expressões e tratar todos os valores diferentes de zero como 1. Operadores lógicos geralmente são usados ​​em declarações condicionais, pois trabalham com expressões.

Os operadores que estão incluídos na operação lógica são -

  • ! (NÃO lógico)
  • && (AND lógico)
  • || (OU lógico)

Example

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

Operadores de redução

Operadores de redução são a forma unária dos operadores bit a bit e operam em todos os bits de um vetor operando. Eles também retornam um valor de bit único.

Os operadores incluídos na operação de redução são -

  • & (redução AND)
  • | (redução OU)
  • ~ & (redução NAND)
  • ~ | (redução NOR)
  • ^ (redução XOR)
  • ~ ^ ou ^ ~ (redução XNOR)

Example

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

Operadores de turno

Operadores de deslocamento, que estão deslocando o primeiro operando pelo número de bits especificado pelo segundo operando na sintaxe. As posições vagas são preenchidas com zeros para ambas as direções, deslocamentos para a esquerda e para a direita (não há extensão de sinal de uso).

Os operadores que estão incluídos na operação de turno são -

  • << (deslocar para a esquerda)
  • >> (deslocar para a direita)

Example

Assign z = c << 3; /* z = c shifted left 3 bits;

Os cargos vagos são preenchidos com 0's * /

Operador de concatenação

O operador de concatenação combina dois ou mais operandos para formar um vetor maior.

O operador incluído na operação de concatenação é - {} (concatenação)

Example

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result

Operador de replicação

O operador de replicação está fazendo várias cópias de um item.

O operador usado na operação de replicação é - {n {item}} (replicação n vezes de um item)

Example

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

Operador Condicional

O operador condicional é sintetizado em um multiplexador. É o mesmo tipo usado em C / C ++ e avalia uma das duas expressões com base na condição.

O operador usado na operação condicional é -

(Doença) ? (Resultado se a condição for verdadeira) -

(resultado se a condição for falsa)

Example

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */

Operandos

Literais

Literais são operandos de valor constante usados ​​em expressões Verilog. Os dois literais Verilog comumente usados ​​são -

  • String - Um operando literal de string é uma matriz unidimensional de caracteres, que são colocados entre aspas duplas ("").

  • Numeric - Um operando de número constante é especificado em número binário, octal, decimal ou hexadecimal.

Example

n - inteiro representando o número de bits

F - um dos quatro formatos de base possíveis -

b para binário, o para octal, d para decimal, h para hexadecimal.

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number

Fios, Regs e Parâmetros

Wires, regs e parâmetros são os tipos de dados usados ​​como operandos em expressões Verilog.

Seleção de bit “x [2]” e Seleção de parte “x [4: 2]”

Bit-selects e part-selects são usados ​​para selecionar um bit e vários bits, respectivamente, de um vetor de fio, reg ou parâmetro com o uso de colchetes “[]”. As seleções de bits e de partes também são usadas como operandos em expressões da mesma forma que seus objetos de dados principais são usados.

Example

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects

Chamadas de função

Nas chamadas de Função, o valor de retorno de uma função é usado diretamente em uma expressão sem a necessidade de primeiro atribuí-lo a um registrador ou fio. Basta colocar a chamada de função como um dos tipos de operandos. É necessário certificar-se de que você está sabendo a largura de bits do valor de retorno da chamada de função.

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function

Módulos

Declaração de Módulo

Em Verilog, um módulo é a principal entidade de design. Isso indica o nome e a lista de portas (argumentos). As próximas linhas especificam o tipo de entrada / saída (entrada, saída ou entrada) e a largura de cada porta. A largura padrão da porta é de apenas 1 bit. As variáveis ​​da porta devem ser declaradas por fio, varinha ,. . ., reg. A variável de porta padrão é fio. Normalmente, as entradas são conectadas porque seus dados estão travados fora do módulo. As saídas são do tipo reg se seus sinais forem armazenados internamente.

Example

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module

Atribuição Contínua

A atribuição contínua em um Módulo é usada para atribuir um valor a um fio, que é a atribuição normal usada fora de sempre ou dos blocos iniciais. Essa atribuição é feita com uma instrução de atribuição explícita ou para atribuir um valor a uma ligação durante sua declaração. A atribuição contínua é executada continuamente no momento da simulação. A ordem das instruções de atribuição não o afeta. Se você fizer qualquer alteração em qualquer um dos sinais de entrada do lado direito, ele mudará um sinal de saída do lado esquerdo.

Example

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */

Instanciações do Módulo

As declarações de módulo são modelos para a criação de objetos reais. Os módulos são instanciados dentro de outros módulos e cada instanciação está criando um único objeto a partir desse modelo. A exceção é o módulo de nível superior, que é sua própria instanciação. As portas do módulo devem corresponder àquelas definidas no modelo. É especificado -

  • By name, usando um ponto “.template nome da porta (nome do fio conectado à porta)”. Ou

  • By position, colocando as portas no mesmo lugar nas listas de portas do modelo e da instância.

Example

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module

Os modelos comportamentais em Verilog contêm instruções procedimentais, que controlam a simulação e manipulam variáveis ​​dos tipos de dados. Todas essas declarações estão contidas nos procedimentos. Cada um dos procedimentos possui um fluxo de atividades associado a ele.

Durante a simulação do modelo comportamental, todos os fluxos definidos pelas declarações 'sempre' e 'inicial' começam juntos no tempo de simulação 'zero'. As instruções iniciais são executadas uma vez e as instruções always são executadas repetidamente. Neste modelo, as variáveis ​​de registro a e b são inicializadas nos binários 1 e 0, respectivamente, no tempo de simulação 'zero'. A instrução inicial é então concluída e não é executada novamente durante a simulação. Esta instrução inicial contém um bloco de início e fim (também chamado de bloco sequencial) de instruções. Neste bloco de tipo começo-fim, a é inicializado primeiro seguido por b.

Exemplo de modelagem comportamental

module behave; 
reg [1:0]a,b; 

initial 
begin 
   a = ’b1; 
   b = ’b0; 
end 

always 
begin 
   #50 a = ~a; 
end 

always 
begin 
   #100 b = ~b; 
end 
End module

Atribuições Processuais

As atribuições procedurais são para atualizar as variáveis ​​reg, integer, time e memory. Há uma diferença significativa entre a atribuição procedimental e a atribuição contínua, conforme descrito abaixo -

As atribuições contínuas conduzem as variáveis ​​da rede e são avaliadas e atualizadas sempre que um operando de entrada muda de valor.

As atribuições procedurais atualizam o valor das variáveis ​​de registro sob o controle das construções de fluxo procedural que as cercam.

O lado direito de uma atribuição procedural pode ser qualquer expressão avaliada como um valor. No entanto, as seleções de parte do lado direito devem ter índices constantes. O lado esquerdo indica a variável que recebe a atribuição do lado direito. O lado esquerdo de uma atribuição procedimental pode assumir uma das seguintes formas -

  • variável de registro, inteiro, real ou de tempo - uma atribuição à referência de nome de um desses tipos de dados.

  • bit-seleção de um registro, inteiro, real ou variável de tempo - Uma atribuição a um único bit que deixa os outros bits intocados.

  • seleção parcial de um registrador, inteiro, real ou variável de tempo - Uma seleção parcial de dois ou mais bits contíguos que deixa o resto dos bits intocados. Para o formulário de seleção parcial, apenas expressões constantes são válidas.

  • elemento de memória - uma única palavra de uma memória. Observe que as seleções de bits e partes são ilegais em referências de elementos de memória.

  • concatenação de qualquer uma das opções acima - uma concatenação de qualquer uma das quatro formas anteriores pode ser especificada, o que particiona efetivamente o resultado da expressão do lado direito e atribui as partes da partição, em ordem, às várias partes da concatenação.

Atraso na Atribuição (não para síntese)

Em uma atribuição atrasada Δt unidades de tempo passam antes que a instrução seja executada e a atribuição à esquerda seja feita. Com o atraso intra-atribuição, o lado direito é avaliado imediatamente, mas há um atraso de Δt antes que o resultado seja colocado na atribuição à esquerda. Se outro procedimento alterar um sinal do lado direito durante Δt, ele não afetará a saída. Atrasos não são suportados por ferramentas de síntese.

Sintaxe

  • Procedural Assignmentvariável = expressão

  • Delayed assignment# Δt variável = expressão;

  • Intra-assignment delayvariável = # expressão Δt;

Exemplo

reg [6:0] sum; reg h, ziltch; 
sum[7] = b[7] ^ c[7]; // execute now. 
ziltch = #15 ckz&h; /* ckz&a evaluated now; ziltch changed 
after 15 time units. */ 

#10 hat = b&c; /* 10 units after ziltch changes, b&c is
evaluated and hat changes. */

Bloqueio de atribuições

Uma instrução de atribuição procedural de bloqueio deve ser executada antes da execução das instruções que a seguem em um bloco sequencial. Uma instrução de atribuição procedural de bloqueio não impede a execução de instruções que a seguem em um bloco paralelo.

Sintaxe

A sintaxe para uma atribuição de procedimento de bloqueio é a seguinte -

<lvalue> = <timing_control> <expression>

Onde, lvalue é um tipo de dados que é válido para uma instrução de atribuição procedural, = é o operador de atribuição e o controle de tempo é o atraso opcional intra-atribuição. O atraso de controle de tempo pode ser um controle de atraso (por exemplo, # 6) ou um controle de evento (por exemplo, @ (posedge clk)). A expressão é o valor do lado direito que o simulador atribui ao lado esquerdo. O operador de atribuição = usado para bloquear atribuições procedurais também é usado por atribuições contínuas procedurais e atribuições contínuas.

Exemplo

rega = 0; 
rega[3] = 1;            // a bit-select 
rega[3:5] = 7;          // a part-select 
mema[address] = 8’hff;  // assignment to a memory element 
{carry, acc} = rega + regb;  // a concatenation

Atribuições não bloqueadoras (RTL)

A atribuição procedural sem bloqueio permite que você agende atribuições sem bloquear o fluxo procedural. Você pode usar a instrução de procedimento sem bloqueio sempre que quiser fazer várias atribuições de registro dentro do mesmo intervalo de tempo, independentemente da ordem ou dependência umas das outras.

Sintaxe

A sintaxe para uma atribuição procedural sem bloqueio é a seguinte -

<lvalue> <= <timing_control> <expression>

Onde lvalue é um tipo de dados válido para uma instrução de atribuição procedural, <= é o operador de atribuição sem bloqueio e o controle de tempo é o controle de tempo opcional intra-atribuição. O atraso de controle de tempo pode ser um controle de atraso ou um controle de evento (por exemplo, @ (clk posedge)). A expressão é o valor do lado direito que o simulador atribui ao lado esquerdo. O operador de atribuição sem bloqueio é o mesmo operador que o simulador usa para o operador relacional menor que ou igual. O simulador interpreta o operador <= como um operador relacional quando você o usa em uma expressão, e interpreta o operador <= como um operador de atribuição quando você o usa em uma construção de atribuição procedural sem bloqueio.

Como o simulador avalia as atribuições de procedimento sem bloqueio Quando o simulador encontra uma atribuição de procedimento sem bloqueio, o simulador avalia e executa a atribuição de procedimento sem bloqueio em duas etapas, como segue -

  • O simulador avalia o lado direito e programa a atribuição do novo valor para ocorrer em um momento especificado por um controle de tempo procedural. O simulador avalia o lado direito e programa a atribuição do novo valor para ocorrer em um momento especificado por um controle de tempo procedural.

  • No final da etapa de tempo, na qual o atraso determinado expirou ou o evento apropriado ocorreu, o simulador executa a atribuição atribuindo o valor ao lado esquerdo.

Exemplo

module evaluates2(out); 
output out; 
reg a, b, c; 
initial 

begin 
   a = 0; 
   b = 1; 
   c = 0; 
end 
always c = #5 ~c; 
always @(posedge c) 

begin 
   a <= b; 
   b <= a; 
end 
endmodule

Condições

A instrução condicional (ou instrução if-else) é usada para decidir se uma instrução é executada ou não.

Formalmente, a sintaxe é a seguinte -

<statement> 
::= if ( <expression> ) <statement_or_null> 
||= if ( <expression> ) <statement_or_null> 
   else <statement_or_null> 
<statement_or_null> 

::= <statement> 
||= ;

A <expressão> é avaliada; se for verdadeiro (ou seja, tiver um valor conhecido diferente de zero), a primeira instrução será executada. Se for falso (tem valor zero ou o valor é x ou z), a primeira instrução não é executada. Se houver uma instrução else e <expression> for falsa, a instrução else é executada. Visto que o valor numérico da expressão if é testado para ser zero, certos atalhos são possíveis.

Por exemplo, as duas declarações a seguir expressam a mesma lógica -

if (expression) 
if (expression != 0)

Visto que a parte else de um if-else é opcional, pode haver confusão quando um else é omitido de uma sequência if aninhada. Isso é resolvido associando sempre o else ao anterior mais próximo, se esse não tiver um else.

Exemplo

if (index > 0) 
if (rega > regb) 
   result = rega; 
   else // else applies to preceding if 
   result = regb; 

If that association is not what you want, use a begin-end block statement 
to force the proper association 

if (index > 0) 
begin 

if (rega > regb) 
result = rega; 
end 
   else 
   result = regb;

Construção de: if- else- if

A seguinte construção ocorre com tanta freqüência que vale a pena uma breve discussão separada.

Example

if (<expression>) 
   <statement> 
   else if (<expression>) 
   <statement> 
   else if (<expression>) 
   <statement> 
   else  
   <statement>

Essa sequência de if (conhecida como construção if-else-if) é a maneira mais geral de escrever uma decisão de múltiplas vias. As expressões são avaliadas em ordem; se alguma expressão for verdadeira, a instrução associada a ela é executada e termina a cadeia inteira. Cada declaração é uma declaração única ou um bloco de declarações.

A última parte else da construção if-else-if lida com 'nenhuma das opções acima' ou caso padrão onde nenhuma das outras condições foi satisfeita. Às vezes, não há uma ação explícita para o padrão; nesse caso, o else à direita pode ser omitido ou pode ser usado para verificação de erro para capturar uma condição impossível.

Declaração do Caso

A declaração de caso é uma declaração de decisão multi-vias especial que testa se uma expressão corresponde a uma de várias outras expressões e se ramifica de acordo. A declaração de caso é útil para descrever, por exemplo, a decodificação de uma instrução de microprocessador. A instrução case tem a seguinte sintaxe -

Example

<statement> 
::= case ( <expression> ) <case_item>+ endcase 
||= casez ( <expression> ) <case_item>+ endcase 
||= casex ( <expression> ) <case_item>+ endcase 
<case_item> 
::= <expression> <,<expression>>* : <statement_or_null> 
||= default : <statement_or_null> 
||= default <statement_or_null>

As expressões de caso são avaliadas e comparadas na ordem exata em que são fornecidas. Durante a procura linear, se uma das expressões de item de caso corresponder à expressão entre parênteses, a instrução associada a esse item de caso será executada. Se todas as comparações falharem e o item padrão for fornecido, a instrução do item padrão será executada. Se a instrução padrão não for fornecida e todas as comparações falharem, nenhuma das instruções do item de caso será executada.

Além da sintaxe, a instrução case difere da construção if-else-if multi-way de duas maneiras importantes -

  • As expressões condicionais na construção if-else-if são mais gerais do que comparar uma expressão com várias outras, como na instrução case.

  • A instrução case fornece um resultado definitivo quando há valores x e z em uma expressão.

Demonstrações de Looping

Existem quatro tipos de instruções de loop. Eles fornecem um meio de controlar a execução de uma instrução zero, uma ou mais vezes.

  • para sempre executa continuamente uma instrução.

  • repeat executa uma instrução um número fixo de vezes.

  • while executa uma instrução até que uma expressão se torne falsa. Se a expressão começar com falsa, a instrução não será executada.

  • para a execução de controles de sua (s) declaração (ões) associada (s) por um processo de três etapas, como segue -

    • Executa uma atribuição normalmente usada para inicializar uma variável que controla o número de loops executados

    • Avalia uma expressão - se o resultado for zero, o loop for termina e, se não for zero, o loop for executa suas instruções associadas e, em seguida, executa a etapa 3

    • Executa uma atribuição normalmente usada para modificar o valor da variável loopcontrol e, em seguida, repete a etapa 2

A seguir estão as regras de sintaxe para as instruções de loop -

Example

<statement> 
::= forever <statement> 
||=forever 
begin 
   <statement>+ 
end  

<Statement> 
::= repeat ( <expression> ) <statement> 
||=repeat ( <expression> ) 
begin
   <statement>+ 
end  

<statement> 
::= while ( <expression> ) <statement> 
||=while ( <expression> ) 
begin 
   <statement>+ 
end  
<statement> 
::= for ( <assignment> ; <expression> ; <assignment> ) 
<statement> 
||=for ( <assignment> ; <expression> ; <assignment> ) 
begin 
   <statement>+ 
end

Controles de atraso

Controle de Atraso

A execução de uma instrução de procedimento pode ser controlada por atraso usando a seguinte sintaxe -

<statement> 
::= <delay_control> <statement_or_null> 
<delay_control> 
::= # <NUMBER> 
||= # <identifier> 
||= # ( <mintypmax_expression> )

O exemplo a seguir atrasa a execução da atribuição em 10 unidades de tempo -

# 10 rega = regb;

Os próximos três exemplos fornecem uma expressão após o sinal de número (#). A execução da atribuição atrasa pela quantidade de tempo de simulação especificada pelo valor da expressão.

Controle de Eventos

A execução de uma instrução procedural pode ser sincronizada com uma mudança de valor em uma rede ou registro, ou a ocorrência de um evento declarado, usando a seguinte sintaxe de controle de evento -

Example

<statement> 
::= <event_control> <statement_or_null> 

<event_control> 
::= @ <identifier> 
||= @ ( <event_expression> ) 

<event_expression> 
::= <expression> 
||= posedge <SCALAR_EVENT_EXPRESSION> 
||= negedge <SCALAR_EVENT_EXPRESSION> 
||= <event_expression> <or <event_expression>>

* <SCALAR_EVENT_EXPRESSION> é uma expressão que resolve para um valor de um bit.

As alterações de valor em redes e registradores podem ser usadas como eventos para acionar a execução de uma instrução. Isso é conhecido como detecção de um evento implícito. A sintaxe Verilog também permite detectar mudanças com base na direção da mudança - isto é, em direção ao valor 1 (posedge) ou em direção ao valor 0 (negedge). O comportamento de posedge e negedge para valores de expressão desconhecidos é o seguinte -

  • um negedge é detectado na transição de 1 para desconhecido e de desconhecido para 0
  • um posedge é detectado na transição de 0 para desconhecido e de desconhecido para 1

Procedimentos: Sempre e Blocos Iniciais

Todos os procedimentos em Verilog são especificados em um dos quatro blocos a seguir. 1) Blocos iniciais 2) Blocos sempre 3) Tarefa 4) Função

As instruções inicial e sempre são ativadas no início da simulação. Os blocos iniciais são executados apenas uma vez e sua atividade termina quando a instrução termina. Em contraste, os blocos always são executados repetidamente. Sua atividade morre apenas quando a simulação é encerrada. Não há limite para o número de blocos iniciais e sempre que podem ser definidos em um módulo. Tarefas e funções são procedimentos que são habilitados em um ou mais locais em outros procedimentos.

Blocos Iniciais

A sintaxe da instrução inicial é a seguinte -

<initial_statement> 
::= initial <statement>

O exemplo a seguir ilustra o uso da instrução inicial para inicialização de variáveis ​​no início da simulação.

Initial 
Begin 
   Areg = 0; // initialize a register 
   For (index = 0; index < size; index = index + 1) 
   Memory [index] = 0; //initialize a memory 
   Word 
End

Outro uso típico dos blocos iniciais é a especificação de descrições de forma de onda que são executadas uma vez para fornecer estímulo à parte principal do circuito que está sendo simulado.

Initial 
Begin 
   Inputs = ’b000000; 
   // initialize at time zero 
   #10 inputs = ’b011001; // first pattern 
   #10 inputs = ’b011011; // second pattern 
   #10 inputs = ’b011000; // third pattern 
   #10 inputs = ’b001000; // last pattern 
End

Sempre bloqueia

A declaração 'sempre' se repete continuamente durante toda a execução da simulação. A sintaxe para a instrução always é fornecida abaixo

<always_statement> 
::= always <statement>

A instrução 'always', por causa de sua natureza de loop, só é útil quando usada em conjunto com alguma forma de controle de tempo. Se uma instrução 'sempre' não fornece meios para o tempo avançar, a instrução 'sempre' cria uma condição de impasse de simulação. O código a seguir, por exemplo, cria um loop infinito de atraso zero -

Always areg = ~areg;

Fornecer um controle de tempo para o código acima cria uma descrição potencialmente útil - como no exemplo a seguir -

Always #half_period areg = ~areg;