Projeto VLSI - Introdução ao Verilog

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, usando 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 projetos 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 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. 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. Estes raramente são usados ​​para trabalho de design, mas são usados ​​no mundo da pós-síntese para modelagem de células ASIC / FPGA.

A modelagem de nível de 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 N 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 (registrador) é 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 '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.

Fornecimento0, Fornecimento1

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 é suportado para 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 que estão 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 bits “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 as seleções parciais 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 ter certeza 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