0% acharam este documento útil (0 voto)
18 visualizações343 páginas

Manual Verilog

O documento é uma introdução ao Verilog, abordando conceitos fundamentais de Álgebra Booleana e suas aplicações em lógica digital. Ele inclui tópicos como mintermos, maxtermos, mapas de Karnaugh, e detalha a sintaxe e os operadores da linguagem Verilog. Além disso, apresenta postulados e teoremas da Álgebra Booleana, essenciais para a compreensão de circuitos lógicos e funções booleanas.

Enviado por

MattGrossi
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PPTX, PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
18 visualizações343 páginas

Manual Verilog

O documento é uma introdução ao Verilog, abordando conceitos fundamentais de Álgebra Booleana e suas aplicações em lógica digital. Ele inclui tópicos como mintermos, maxtermos, mapas de Karnaugh, e detalha a sintaxe e os operadores da linguagem Verilog. Além disso, apresenta postulados e teoremas da Álgebra Booleana, essenciais para a compreensão de circuitos lógicos e funções booleanas.

Enviado por

MattGrossi
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PPTX, PDF, TXT ou leia on-line no Scribd

SD112 – Introdução ao Verilog

Autores

Elivander Judas Tadeu Pereira (INATEL) Letícia Carneiro de Souza (INATEL)

Felipe Gustavo de Freitas Rocha (INATEL)

Histórico de revisões
23/01/2025 V1.0 Versão inicial

2
Tópicos
• Introdução à Álgebra Booleana
• Introdução a Mintermos, Maxtermos e Mapas de Karnaugh
• Introdução às Ferramentas e Servidor
• Verilog – Introdução à Linguagem
• Verilog – Tipos de Dados
• Verilog – Operadores
• Verilog – Declarações Processuais
• Verilog – Declarações Blocking e Non-blocking
• Verilog – Reset Síncrono e Assíncrono
• Verilog – Estilos de Código
• Verilog – Descrição RTL
• Verilog – Descrição Comportamental
• Verilog – Descrição Estrutural
• Verilog – Primitivas do Verilog e Primitivas Definidas por Usuário
• Verilog – Codificação para Síntese e Simulação
3
Página em branco.

4
Aula 0
Introdução à Álgebra Booleana
Definição
• Álgebra Booleana é um
sistema matemático dedutivo
que lida com variáveis lógicas
e operações baseadas em
dois valores possíveis: 0
(falso) e 1 (verdadeiro).
George Boole
(1815 - 1864)
• Foi desenvolvida por George
Boole no século XIX e serve
como base teórica para a
lógica digital e os circuitos
lógicos utilizados em
computadores e dispositivos
digitais.

6
Postulados
• Os postulados de um sistema matemático formam as
suposições básicas a partir das quais é possível deduzir as
regras, os teoremas e as propriedades do sistema. Os
postulados mais comuns usados para formular várias
estruturas algébricas são os seguintes:

1) Fechamento
2) Lei Associativa
3) Lei Comutativa
4) Elemento Identidade
5) Elemento Inverso
6) Lei Distributiva

7
Fechamento
• Um conjunto S é fechado em
relação a um operador binário se,
para cada par de elementos de S, o
operador binário especifica uma
regra para obter um elemento
único de S. Por exemplo, o
conjunto dos números naturais
N={1,2,3,4,…} é fechado em
relação ao operador binário + pelas
regras da adição aritmética, pois,
para quaisquer a, b ∈ N, existe um
único c ∈ N tal que a + b = c.

• No entanto, o conjunto dos números naturais não é fechado em


relação ao operador binário − pelas regras da subtração
aritmética, porque 2 − 3 = −1, e 2, 3 ∈ N, mas (−1) ∉ N.

8
Lei Associativa
Os operadores binários * e + em um conjunto S são ditos
serem associativos sempre que:

(x * y) * z = x * (y * z) = x * y * z para todos os valores de x, y, z ∈ S

(x + y) + z = x + (y + z) = x + y + z para todos os valores de x, y, z ∈ S

9
Lei Comutativa
Um operador binário * em um conjunto S é dito ser
comutativo sempre que:

x * y = y * x para todos os valores de x, y, z ∈ S

x*y=y*x

x=4 4*5=5*4
y=5
20 = 20

10
Elemento Identidade
Um conjunto S possui um elemento identidade em relação a
uma operação binária * se existir um elemento e ∈ S que
satisfaça a propriedade:
e * x = x * e = x para todo valor de x ∈ S

Exemplo: O elemento 0 é um elemento identidade para o


operador binário + no conjunto dos inteiros Z = {..., -3, -2, -1,
0, 1, 2, 3,...} pois:
x + 0 = 0 + x = x, para qualquer x ∈ Z

11
Inverso
Um conjunto S, com um elemento identidade em relação a
uma operação binária *, possui inversos se, para cada x ∈ S,
existir um elemento y ∈ S tal que:

x*y=e

onde e é o elemento identidade da operação.

Exemplo: No conjunto dos números inteiros Z, com o


operador + e o elemento identidade e = 0:
• O inverso de um elemento a é −a, pois:
a + (−a) = 0

12
Lei Distributiva
Se * e ⋅ são dois operadores binários em um conjunto S, dizemos
que * é distributivo sobre ⋅ se, para todos os x, y, z ∈ S:

x ∗ (y.z) = (x∗y) ⋅ (x∗z)

Exemplo: Considere x = 2, y = 3 e z = 4:

2 ⋅ (3 + 4) = (2 ⋅ 3) + (2 ⋅ 4)
x=2
y=3
2⋅7= 6+8
z=4
14 = 14

13
Álgebra Booleana de Dois
Valores
A álgebra booleana de dois valores usa o conjunto B = {0, 1},
com os operadores binários OR (+), AND (⋅) e NOT (x’). As
tabelas abaixo mostram as regras de cada operador:

Tabela do Tabela do Tabela do operador


operador OR (+) operador AND (⋅) de Complemento (x’)
x y x+y x y x .y x x’
0 0 0 0 0 0 0 1
0 1 1 0 1 0 1 0
1 0 1 1 0 0
1 1 1 1 1 1

14
Álgebra Booleana de Dois
Valores
1) Fechamento:
A estrutura é fechada para os operadores + e ⋅, pois o resultado
de qualquer operação é sempre 0 ou 1, ambos pertencentes ao
conjunto B.
2) Elementos Identidade:
• Das tabelas da verdade, observamos os seguintes elementos
identidade:
(a) Para “+”: 0, pois 0 + x = x + 0 = x;
(b) Para “⋅”: 1, pois 1 ⋅ x = x ⋅ 1 = x;
• Isso confirma os elementos identidade conforme o Postulado
2.
3) Leis Comutativas:
As tabelas do slide anterior mostram que x + y = y + x e
x ⋅ y = y ⋅ x, demonstrando a comutatividade dos operadores.

15
Álgebra Booleana de Dois
Valores
x y z y+z 4) Leis Distributivas:
x . (y+z) x.y x.z (x.y) + (x.z)
0 0 0 0 0 0 0 0
1 0 0 0 0
A tabela da verdade
0 0 1
0 1 0 1 0 0 0 0
confirma que os resultados
1 0
de x ⋅ (y + z) e (x ⋅ y) + (x ⋅ z)
0 1 1 0 0 0
0 0
são sempre iguais.
1 0 0 0 0 0

1 0 1 1 1 0 1 1

1 1 0 1 1 1 0 1

1 1 1 1 1 1 1 1

(a) Lei Distributiva de “⋅” sobre “+”:


A tabela da verdade acima, demonstra que x ⋅ (y + z) = (x ⋅y) + (x ⋅z) para todos
os valores de x, y e z.
(b) Lei Distributiva de “+” sobre “⋅”:
A propriedade distributiva de + sobre ⋅ segue a mesma lógica e pode ser
validada usando uma tabela semelhante, onde x+(y ⋅ z)=(x + y)⋅(x + z)

16
Álgebra Booleana de Dois
Valores
5) Complemento
O Postulado 1 trata das propriedades do Complemento e
afirma que:
• x + x’ = 1
• x⋅x=0
(a) Para x + x′ = 1
• 0 + 0′ = 0 + 1 = 1
• 1 + 1′ = 1 + 0 = 1
Assim, verificamos que o Postulado 1
é verdadeiro para os valores de x e x’.
(b) x ⋅ x′ = 0
• 0 ⋅ 0′ = 0 ⋅ 1 = 0
• 1 ⋅ 1′ = 1 ⋅ 0 = 0

17
Álgebra Booleana de Dois
Valores
6) Estrutura binária
O Postulado 6 define a estrutura binária da Álgebra Booleana,
que possui dois elementos distintos, representados por 0
(falso) e 1 (verdadeiro) e esses elementos são diferentes entre
si:
1≠0

Esses valores representam os dois estados fundamentais:

• 1: Verdadeiro, ligado, alto.

• 0: Falso, desligado, baixo.

18
Postulados e Teoremas
Postulados e Teoremas da (a) (b)
Álgebra Booleana
Postulado 2 x+0=x x⋅1=x
Postulado 5 x + x’ = 1 x ⋅ x’ = 0
Teorema 1 x+x=x x⋅x=x
Teorema 2 x+1=1 x⋅0=0
Teorema 3, Involução (x’)’ = x
Postulado 3, Comutativo x+y=y+x x⋅y = y⋅x
Teorema 4, Associativo x + (y + z) = (x + y) + z x(y⋅z) = (x⋅y)z
Postulado 4, Distributivo x(y + z) = xy + xz x + yz = (x + y)(x + z)
Teorema 5, DeMorgan (x + y)’ = x’y’ (xy)’ = x’ + y’
Teorema 6, Absorção x + xy = x x(x + y) = x

(a): Identidade do (b): Identidade do


operador somatório (+) operador produto (⋅)

19
Postulados e Teoremas
Teorema 1 (a): Prova de x + x = x

Declaração Justificativa

x + x = (x + x) ⋅ 1
Postulado 2 (b)
= (x + x)(x + x’)
5 (a)
= x + xx’
4 (b)
=x+0
5 (b)
=x
2 (a)
20
Postulados e Teoremas
Teorema 1 (b): Prova de x ⋅ x = x

Declaração Justificativa

x ⋅ x = xx + 0
Postulado 2 (a)
= xx + xx’
5 (b)
= x(x + x’)
4 (b)
=x⋅1
5 (a)
=x
2 (b)
21
Postulados e Teoremas
Teorema 2 (a): Prova de x + 1 = 1

Declaração Justificativa

x + 1 = 1 ⋅ (x + 1)
Postulado 2 (a)
= (x + x’) (x + 1)
5 (b)
= x + x’ ⋅ 1
4 (b)
= x + x’
5 (a)
Teorema 2 (b): x ⋅ 0 ==
0 por
1 dualidade
2 (b)
22
Postulados e Teoremas
Teorema 3: Prova de (x’)’ = x

x x’ (x’)’
Base: A partir do Postulado 5,
0 1 0
temos:
1 0 1
x + x’ = 1 e x ⋅ x’ = 0

Esses resultados definem o


complemento de x, que é x’, e o
complemento de x’, que é x.

Conclusão: Como o complemento


é único, segue que (x’)’ = x.

23
Postulados e Teoremas
Teorema 6 (a): Prova de x + xy = x

Declaração Justificativa

x + xy = x⋅1 + xy
Postulado 2 (b)
= x(1 + y)
4 (a)
= x(y + 1)
3 (a)
= x⋅1
2 (a)
Teorema 6 (b): x(x + y)== xx por dualidade.
2 (b)
24
Funções Booleanas
Definição:
• A Álgebra Booleana lida com variáveis binárias e operações
lógicas.
Componentes de uma Função Booleana:
• Uma função booleana é descrita por uma expressão algébrica
com:
Variáveis binárias (x, y, z);
Constantes (0 e 1);
Operadores lógicos (AND, OR, NOT, etc).
Comportamento:
• Para um valor dado das variáveis binárias, a função retorna 0
ou 1.

F(x,y) = x⋅y + x′

25
Exemplo: Funções Booleanas
F1 = x + y'z
• Uma Função Booleana descreve
uma relação lógica entre as
variáveis binárias, determinando
sua saída com base nos valores
binários atribuídos às entradas.
x y z F1
• Representação com a Tabela da
0 0 0 0
Verdade:
0 0 1 1
• A Tabela da Verdade mostra todas
as combinações possíveis de 0 1 0 0
entrada e saída correspondente.
0 1 1 0
• O número de linhas da tabela da
1 0 0 1
verdade é 2n, onde n é o número
de variáveis. 1 0 1 1
• Exemplo: Para F1 = x + y'z, há 8 1 1 0 1
combinações possíveis (n = 3). 1 1 1 1

26
Exemplo: Funções Booleanas
(a)
F2 = x’y’z + x’yz +
xy’ (a)
F2 = x’z (y’ + y) +
xy’1

F2 = x’z + xy’ (b)

(b) Manipular uma expressão


Booleana, de acordo com as
regras, permite simplificar a
função, reduzindo o número
de portas e entradas no
circuito, o que diminui
significativamente seu custo
e complexidade.

27
Simplificando Funções
1) x(x’ + y) = xx’ + xy = 0 + xy = xy

2) x + x’y = (x + x’)(x + y) = 1(x + y) = x + y

3) (x + y)(x + y’) = x + xy + xy’ + yy’ = x(1 + y +y’) =


x

4) xy + x’z + yz = xy + x’z + yz(x + x’)


= xy + x’z + xyz + x’yz
= xy(1 + z) + x’z(1 + y)
= xy + x’z

5) (x + y)(x’ + z)(y + z) = (x + y)(x’ + z), pela


dualidade da função 4.
28
Complemento de Função
Booleanas
Definição Geral
• O complemento de uma função F, representado por F’, é obtido trocando 0’s por
1’s e 1’s por 0’s no valor da função F.
Relevância dos Teoremas de DeMorgan
• Os Teoremas de DeMorgan fornecem uma forma algébrica para calcular
complemento de expressões Booleanas.
• Esses teoremas podem ser estendidos para três ou mais variáveis.
Derivação do Teorema de DeMorgan para três variáveis
1. Dada a expressão (A + B + C)’ , substitua (B + C) por x. A nova expressão é dada
por (A + x)’.
2. Aplicando o Teorema de DeMorgan (o complemento da soma A + x é igual ao
complemento de A vezes o complemento de x) a expressão fica A’x’.
3. Fazendo novamente a substituição do valor de x, a expressão fica A’(B + C)’.
4. Aplicando novamente o teorema de DeMorgan em (B + C)’, a expressão fica
A’B’C’.

29
Complemento de Função
Booleanas
• Os teoremas de DeMorgan, para qualquer número de variáveis,
seguem a mesma lógica dos casos com duas variáveis.
• Eles podem ser derivados por substituições sucessivas,
semelhantes ao método usado nas derivações anteriores.
 Para soma (+):
(A + B + C + D + ... + F)’ = A’B’C’D’...F’
O complemento de uma soma de variáveis resulta no produto dos
complementos das variáveis.

 Para produto (⋅):


(ABCD...F)’ = A’ + B’ + C’ + D’ + ... + F’
O complemento de um produto de variáveis resulta na soma dos
complementos das variáveis.

30
Exemplo: Cálculo do Complemento de
Funções Booleanas

• Objetivo: Demonstrar como calcular o complemento das funções F1 e


F2 utilizando os Teoremas de DeMorgan.

Função F1 e seu complemento: Função F2 e seu complemento:

F1 = x’yz’ + x’y’z F2 = x(y’z’ + yz)


F1’ = (x’yz’ + x’y’z)’ F2’ = [x(y’z’ + yz)]’ = x’
= (x + y’ +z)(x + y + (y’z’ + yz)’
+ z’) = x’ + (y + z)(y’ +
z’)
= x’ + yz’ +y’z

31
Página em branco.

32
Aula 1
Introdução à Álgebra Booleana
(cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados sobre
Álgebra Booleana em exercícios práticos, presentes no
arquivo Relatórios Práticos – SD112 atividade A-001.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-001.

• Caso opte por elaborar diagramas de circuitos no


computador, uma solução online e gratuita recomendada é
a utilização do software Draw.IO https://app.diagrams.net/.

34
Instruções
• Para utilização da plataforma Draw.IO, deve-se habilitar as
formas para circuitos elétricos, que incluem portas lógicas,
de acordo com as imagens a seguir:
1) 2)

35
Página em branco.

36
Aula 2
Introdução à Mintermos,
Maxtermos e Mapas de
Karnaugh
Mintermo/Maxtermo
• São duas formas padrões para expressar as funções
booleanas.

• Mintermo (Produto padrão): produto contendo


todas as variáveis na sua forma complementada ou
não.
• Maxtermo (Soma padrão): soma contendo todas as
variáveis na sua forma complementada ou não.

38
Mintermo
• Com duas variáveis binárias são possíveis 4
combinações (22 = 4).

• Cada uma dessas combinações define uma área no


diagrama de Venn.

A B

39
Mintermo
• Esses 4 termos são chamados de mintermos ou
produto padrão.
• Mintermo é composto por duas ou mais variáveis,
ou o seu complemento, aplicadas através de uma
porta AND.
• Para funções de n variáveis
tem-se 2n mintermos,
designados por mj, onde o A B
subscrito j representa o
decimal equivalente ao
número binário que
representa o mintermo.
40
Mintermo
Tabela da verdade ilustrando os mintermos com funções com 3 variáveis.
A B C Mintermo Designação
0 0 0 m0
0 0 1 m1
0 1 0 m2
0 1 1 m3
1 0 0 m4
1 0 1 m5
1 1 0 m6
1 1 1 m7

Se a variável assume o valor "0", ela é representada em sua forma


complementada; se assume o valor "1", é representada em sua forma
direta.

41
Maxtermo

• Da mesma forma que os mintermos, uma função


OR contendo as variáveis na sua forma
complementar ou não é chamado de maxtermo ou
termo soma padrão.

• O maxtermo é designado por Mj onde o subscrito j


representa o decimal equivalente para cada
número binário do maxtermo.

42
Maxtermo
Tabela da verdade ilustrando os maxtermos com funções com 3 variáveis.
A B C Maxtermo Designação
0 0 0 M0
0 0 1 M1
0 1 0 M2
0 1 1 M3
1 0 0 M4
1 0 1 M5
1 1 0 M6
1 1 1 M7

Se a variável assume o valor "0", ela é representada em sua forma direta;


se assume o valor "1", é representada em sua forma complementada.

43
Mintermo/maxtermo
Toda expressão booleana pode ser representada como uma
soma de mintermos ou como um produto de maxtermos.
Exemplo 01: Expressar X(A,B,C) e Y(A,B,C) em termos de soma
de mintermos:
A B C X Y
0 0 0 0 0 1
1 0 0 1 1 1
2 0 1 0 1 0
3 0 1 1 0 0
4 1 0 0 0 1
5 1 0 1 1 1
6 1 1 0 1 0
7 1 1 1 0 1

44
Mintermo/maxtermo
Toda expressão booleana pode ser representada como uma
soma de mintermos ou como um produto de maxtermos.
Exemplo 02: Expressar X(A,B,C) e Y(A,B,C) em termos de
produto de maxtermos:
A B C X Y
0 0 0 0 0 1
1 0 0 1 1 1
2 0 1 0 1 0
3 0 1 1 0 0
4 1 0 0 0 1
5 1 0 1 1 1
6 1 1 0 1 0
7 1 1 1 0 1

45
Mintermo/maxtermo
• Cada maxtermo é o complemento do seu
correspondente mintermo e vice-versa.

Exemplo 03:
• Prove que

Complementando M1 e aplicando o teorema de


DeMorgan tem-se:

46
Mintermo/maxtermo
Exemplo 04:
• Prove que

47
Propriedades dos Mintermos e
Maxtermos
1. Qualquer função booleana pode ser expressa
através da soma de mintermos.
2. Qualquer função booleana pode ser expressa
através do produto de maxtermos.
Uma função booleana pode ser obtida da Tabela da Verdade
atribuindo-se um mintermo para cada combinação de
variáveis que produz lógica 1 e então unindo todos os termos
através do operador OR.
3. Quando uma função booleana está representada
na forma de soma de mintermos ou produto de
maxtermos a função está representada na forma
canônica.

48
Mintermo/maxtermo
Exemplo 05: Expressar as funções D e B através da soma de
mintermos. Entradas Saídas
X Y Z D B
0 0 0 0 0
0 0 1 1 1
0 1 0 1 1
0 1 1 0 1
1 0 0 1 0
1 0 1 0 0
1 1 0 0 0
1 1 1 1 1

49
Mintermo/maxtermo
Exemplo 06: Expressar as funções D e B através do produto de
maxtermos. Entradas Saídas
X Y Z D B
0 0 0 0 0
0 0 1 1 1
0 1 0 1 1
0 1 1 0 1
1 0 0 1 0
1 0 1 0 0
1 1 0 0 0
1 1 1 1 1

50
Mintermo/Maxtermo
• Muitas funções booleanas são compostas por termos que
não contém todas as variáveis.
• Contudo, é possível expressar a função através da soma de
produtos.
(Teoria do Complemento)

51
Mapa de Karnaugh
• O Mapa de Karnaugh (K-map) é um método
utilizado para simplificação de expressões
da Álgebra Booleana.
• Foi desenvolvido por Maurice Karnaugh em
1953, sendo um aperfeiçoamento do Mapa Maurice Karnaugh
de Veitch, este desenvolvido por Edward (1924-2022)
Veitch em 1952. K-map
K-map K-map (4 variáveis)
(2 variáveis) (3 variáveis)
AB
A AB 00 01 11 10
0 1 00 01 11 10
00 0 0 0 0
0 0 1 0 0 0 0 0
B C 01 0 1 1 0
1 0 1 1 0 1 1 0 CD 11 1 1 1 1
10 1 1 0 1

52
Mapa de Karnaugh
• O Mapa de Karnaugh é um método para reduzir uma
expressão booleana na sua forma mais simples.
• Contém as mesmas informações contidas na Tabela da
Verdade, entretanto permite que o projetista identifique os
termos que podem ser simplificados.
• Cada linha da Tabela da Verdade representa uma célula no
Mapa de Karnaugh.
• O princípio do Mapa de Karnaugh é o Teorema do
Complemento:
• Termos que diferem em um único bit podem ser
simplificados, eliminando a variável que assume o valor "1"
em um dos termos e o valor "0" no outro termo.
• Código Gray.

53
Mapa de Karnaugh para Duas Variáveis
A
0 1 v1 A=0 e B=0
0 v1 v3 ou v1 v3 v2 A=0 e B=1
B 1 v2 v4 v2 v4 v3 A=1 e B=0
v4 A=1 e B=0

A A A
X 0 1 Y 0 1 0 1
Z
0 1 0 1 0 1
B B 1 1 B
1 1 1 1 1

54
Mapa de Karnaugh para Duas Variáveis
A A A A
0 1 0 1 0 1 0 1
0 1 0 0 1 0
B 1 B 1 1 B B
1 1 1

A A A A
0 1 0 1 0 1 0 1
0 1 0 1 0 1 1 0
B 1 1 B 1 1 B B
1 1 1 1

55
Mapa de Karnaugh para Duas Variáveis
A
X 0 1
0 1 1
B 1

A
Y 0 1
0 1 1
B 1 1

A A A
Z 0 1 Z 0 1 Z 0 1
0 1 1 0 1 1 0 1 1
B 1 1 1
B 1 1 1 B 1 1 1

56
Mapa de Karnaugh para Três
Variáveis
AB • A sequência dos termos é
00 01 11 10 importante para que o Mapa
0 de Karnaugh possa ser
C 1 utilizado corretamente.
AB AB AB
00 01 11 10 00 01 11 10 00 01 11 10
0 1 0 1 0 1
C C C
1 1 1 1 1 1

AB
00 01 11 10
0 1
C
1 1

57
Mapa de Karnaugh para Três
Variáveis

AB AB AB
00 01 11 10 00 01 11 10 00 01 11 10
0 1 1 0 1 1 0 1 1
C C C
1 1 1

AB
00 01 11 10
0 1 1
C
1

58
Mapa de Karnaugh para Três
Variáveis

AB AB AB
00 01 11 10 00 01 11 10 00 01 11 10
0 0 0
C C C
1 1 1 1 1 1 1 1 1

AB
00 01 11 10
0
C
1 1 1

59
Mapa de Karnaugh para Três
Variáveis AB
AB AB
00 01 11 10 00 01 11 10 00 01 11 10
0 1 1 0 1 1 0 1 1
C C C
1 1 1 1 1 1 1 1 1

AB
00 01 11 10
0 1 1
C
1 1 1
AB AB
00 01 11 10 00 01 11 10
0 1 1 1 1 0 1 1 1 1
C C
1 1

60
Mapa de Karnaugh para Três
Variáveis
AB
00 01 11 10
0 1 1 1 1
C
1 1 1

AB
00 01 11 10
0 1 1
C
1 1 1

AB
00 01 11 10
0 1 1 1
C
1 1 1

61
Mapa de Karnaugh para Três
Variáveis AB
00 01 11 10
(3 variáveis / 18 literais)
0 1 1 1
C
1 1 1 1
Algumas possibilidades de agrupamentos*:
AB AB AB
00 01 11 10 00 01 11 10 00 01 11 10
0 1 1 1 0 1 1 1 0 1 1 1
C C C
1 1 1 1 1 1 1 1 1 1 1 1

(3 variáveis / 6 literais) (2 variáveis / 3 literais) (2 variáveis / 2 literais)

EXPRESSÕES BOOLEANAS
EQUIVALENTES EXPRESSÃO BOOLEANA MÍNIMA
(possuem o mesmo resultado lógico) (a mais reduzida: menor quantidade de literais e
menor quantidade de variáveis)
*Existem outros agrupamentos possíveis, mas que também não são mínimos.

62
Mapa de Karnaugh para Quatro Variáveis

AB
00 01 11 10
00 A B C D A BC D
01 D D
CD 11
10

63
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00 1
01 01
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 1 00 1
01 01
CD 11 CD 11
10 10

64
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 1 01 1
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 1 01 1
CD 11 CD 11
10 10

65
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 CD 11 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 CD 11 1
10 10

66
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 CD 11
10 1 10 1

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 CD 11
10 1 10 1

67
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 01
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 01
CD 11 CD 11
10 10

68
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 1 1 01 1 1
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 1 1 01 1 1
CD 11 CD 11
10 10

69
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 1 CD 11 1 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 1 CD 11 1 1
10 10

70
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 CD 11
10 1 1 10 1 1

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 CD 11
10 1 1 10 1 1

71
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00
01 1 01 1
CD 11 CD 11 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00 1
01 01
CD 11 1 CD 11
10 1 10 1

72
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00
01 1 01 1
CD 11 CD 11 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00 1
01 01
CD 11 1 CD 11
10 1 10 1

73
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00
01 1 01 1
CD 11 CD 11 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00 1
01 01
CD 11 1 CD 11
10 1 10 1

74
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00
01 1 01 1
CD 11 CD 11 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00 1
01 01
CD 11 1 CD 11
10 1 10 1

75
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 1 1 01 1 1
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 1 1 01 1 1
CD 11 CD 11
10 10

76
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 1 1 01 1 1
CD 11 1 1 CD 11 1 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 1 1 01 1 1
CD 11 1 1 CD 11 1 1
10 10

77
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 1 CD 11 1 1
10 1 1 10 1 1

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 1 CD 11 1 1
10 1 1 10 1 1

78
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 01
CD 11 CD 11
10 1 1 10 1 1

AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 01
CD 11 CD 11
10 1 1 10 1 1

79
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 1 1 00
01 01 1 1 1 1
CD 11 CD 11
10 10

AB AB
00 01 11 10 00 01 11 10
00 00
01 01
CD 11 1 1 1 1 CD 11
10 10 1 1 1 1

80
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 00 1
01 1 01 1
CD 11 1 CD 11 1
10 1 10 1

AB AB
00 01 11 10 00 01 11 10
00 1 00 1
01 1 01 1
CD 11 1 CD 11 1
10 1 10 1

81
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 1 1 00
01 1 1 1 1 01 1 1 1 1
CD 11 CD 11 1 1 1 1
10 10

AB AB
00 01 11 10 00 01 11 10
00 00 1 1 1 1
01 01
CD 11 1 1 1 1 CD 11
10 1 1 1 1 10 1 1 1 1

82
Mapa de Karnaugh para Quatro Variáveis
AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 1 1 01 1 1
CD 11 1 1 CD 11 1 1
10 1 1 10 1 1

AB AB
00 01 11 10 00 01 11 10
00 1 1 00 1 1
01 1 1 01 1 1
CD 11 1 1 CD 11 1 1
10 1 1 10 1 1

83
Mapa de Karnaugh para Quatro Variáveis

AB
00 01 11 10
00 1
01 1 1
CD 11 1 1
10 1

AB
00 01 11 10
00 1 1 1
01
CD 11 1 1
10 1 1 1 1

84
Mapa de Karnaugh para Cinco
Variáveis

85
Mapa de Karnaugh para Seis
Variáveis

86
Mapa de Karnaugh com Condições
Irrelevantes
• Condições irrelevantes são situações de entrada na
qual a saída pode assumir 0 ou 1 de forma
indiferente.
• Essa condição ocorre, principalmente, devido à
impossibilidade prática de a situação de entrada
acontecer.
• Para utilizá-la em Mapas de Karnaugh, devemos,
para cada condição irrelevante, adotar o valor (0
ou 1) que permita um melhor agrupamento,
visando uma simplificação mais eficiente.

87
Mapa de Karnaugh com Condições
Irrelevantes
A B C S AB
0 0 0 X 00 01 11 10
0 0 1 1 0 X 1 1 1
0 1 0 1 C 1 0 0 0 0
0 1 1 1
1 0 0 0 𝐒 =𝐂
1 0 1 0
1 1 0 0 • O símbolo (X) indica uma condição em que a
1 1 1 0 saída pode assumir 0 ou 1 de forma
indiferente.
• Para fins de simplificação, é recomendado
atribuir X = 1, pois essa escolha permite
formar um agrupamento de uma quadra, em
vez de dois pares (caso X = 0), resultando em
uma expressão de saída mais simplificada.

88
Aula 3
Introdução à Mintermos,
Maxtermos e Mapas de
Karnaugh (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Mintermos, Maxtermos e Mapas de Karnaugh em
exercícios práticos, presentes no arquivo Relatórios Práticos
– SD112 atividade A-002.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-002.

90
Aula 4
Introdução às Ferramentas e
Servidor
92
Aula 5
Verilog - Introdução à
Linguagem
O que é Verilog?
• Verilog não é uma
linguagem de software.
• Verilog é uma HDL
(hardware description
language).
• Uma linguagem de
programação com
estruturas especiais
para modelar
hardware.

94
Benefícios de Utilizar HDLs
• HDL é escrito em texto ASCII comum.
• Permite desenvolver o projeto de forma rápida e
gerenciar modificações facilmente.
• Permite projetar em um nível de abstração mais alto.
• Facilita avaliar diferentes opções de design.
• Permite identificar problemas mais cedo no ciclo de
projeto.
• A descrição é independente da implementação.
• A escolha da tecnologia de implementação pode ser
postergada.
• Torna mais simples realizar alterações arquiteturais e
funcionais.
• Facilita a adaptação do design para projetos futuros.
95
Níveis de Abstração
Behavioral
(comportamental)
- algorítimico

Register
Transfer Síntese
Level (RTL) Lógica
Verilog
Gate Level
(nível de portas) Layout
- netlist Place
&
Route
Físico
- silício
- polígonos

96
Níveis de Abstração: Trade-
offs
Simulação/entrada
Menos detalhado
mais rápida Behavioral (comportamental)
- algorítimico

Register
Transfer
Level (RTL)

Gate Level (nível de portas)


- netlist

Físico
- silício
Simulação/entrada - polígonos Mais detalhado
mais lenta

97
Níveis de Abstração
Alto Nível
Estrutural (Structural)

Comportamental
(Behavioral)

RTL

Nível de transistor
Baixo Nível

98
Níveis de Abstração: Exemplo

MUX

Comportamental
Estrutural
if sel == '0'
then
RTL out = IN1
else
out = IN2

case(sel)
'0': out = IN1
'1': out = IN2

99
Simulação Tradicional
• Aplica-se estímulos de baixo nível, proprietários e não
portáveis (ou seja, sinais específicos que não são facilmente
transferidos para outros sistemas ou ferramentas).
• Observa-se os resultados na exibição de formas de onda.
• Verifica-se manualmente se a funcionalidade e o tempo do
circuito estão corretos).
• Agora, vamos comparar isso com o uso de Verilog...

100
Simulação baseada em
Verilog
• Testbench de alto nível em
Verilog.
• Testbench escrito em
estilo comportamental.
• Interage-se com o design.
• Design escrito em
estilo RTL.
• Pode-se verificar
automaticamente a
funcionalidade do design.
• Portável entre ferramentas.

101
Estrutura Básica
• Começa com a palavra-chave module module_name
(port_list);
module e termina com a Declarações de porta
palavra-chave endmodule.
• Espaços em branco são Declarações de tipos de dados
utilizados para legibilidade.
Funcionalidade do circuito
• O ponto e vírgula é utilizado
para finalizar instruções. Especificações de tempo
• //: utilizado para comentar
endmodule
uma única linha.
Importante!
• /* */: utilizado para comentar O Verilog é case sensitive para
múltiplas linhas. identificadores
As palavras-chave são sempre
escritas com letra minúscula

102
Declaração de Portas
• Os módulos se comunicam através
de portas. module mult_acc
(out, ina, inb, clk,
• Declaração de portas: aclr);

• <port_type> input [7:0] ina, inb;


<port_name>; input clk, aclr;
output [15:0] out;
• Define-se cada porta como entrada …
(input), saída (output) ou endmodule
entrada/saída (inout). module mult_acc
(
• Na lista após a declaração do input [7:0] ina, inb,
módulo. input clk, aclr,
output [15:0] out
input clk, aclr, …; );

• Verilog-2001: na lista de portas. endmodule
(input clk, aclr, …);

103
Representando Hierarquia
Criação de hierarquia por:
• Instanciação de módulo(s).
• Conexão das portas do
módulo a portas ou nets
locais.

module fulladd (input a, b, cin, output sum, carry);

wire n_sum, n_carry1, n_carry2; Nets locais do tipo wire

halfadd U1 (.a(a), .b(b), .sum(n_sum), .carry(n_carry1));


halfadd U2
(.a(n_sum), .b(cin), .sum(sum), .carry(n_carry2));
or U3 (carry, n_carry2, n_carry1);
Primitiva de gate
endmodule

104
Instanciação de Módulos
Formato:
• <component_name> <instance_name> (port
list);
• <component name>
• O nome do módulo que será instanciado.
• <instance name>
• Nome da instância. Deve ser único dentro do módulo
superior.
• (port_list)
• Mapeamento explícito de portas (nome da porta no
módulo original conectado a um sinal ou variável no
módulo superior).

105
Conexão de Portas Nomeadas (Named Port
Connection)
• Especifica-se explicitamente
qual porta da instância está
mapeada para qual
porta/conexão local.
Dica:
Use conexão de
module fulladd (input a, b, cin, output sum, carry);
portas nomeadas
wire n_sum, n_carry1, n_carry2; para conectar
hierarquias
halfadd U1
(.a(a), .b(b), .sum(n_sum), .carry(n_carry1));
...
endmodule wire n_carry1
module halfadd (a, b, sum, do módulo
carry); fulladd mapeado
output sum, carry; para a saída carry
input a, b; do módulo
... halfadd
endmodule

106
Conexão de Portas Ordenadas (Ordered Port
Connection)
• Mapeia-se portas/conexões
locais para as portas de
instância por posição na
ordem que as portas são
declaradas.
module fulladd (input a, b, cin, output sum, carry);
input a do
wire n_sum, n_carry1, n_carry2; fulladd mapeada
halfadd U1 (a, b, n_sum, n_carry1);
para a input a do
... halfadd
input b do
endmodule fulladd mapeada
para a input b do
module halfadd (a, b, sum, halfadd
carry); Cuidado!
output sum, carry; Menos legível e mais propensa a
input a, b; erros do que a conexão de portas
... nomeadas
endmodule
107
Revisão
1. O que é Verilog e para que ele é utilizado?
2. Qual é o bloco básico de construção de um design em Verilog?
3. O que significa instanciar um módulo em Verilog?
4. Qual a diferença entre conexão ordenada e conexão nomeada
ao instanciar um módulo?
5. O que é um testbench e por que ele é importante?
6. Escreva o código para instanciar o seguinte módulo:

108
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog - Introdução à Linguagem em exercícios
práticos, presentes no arquivo Relatórios Práticos – SD112
atividade A-004.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-004.

109
Página em branco.

110
Aula 6
Verilog – Tipos de Dados
O Sistema de Lógica de 4 Valores do
Verilog

Zero, baixo (low), falso, baixo lógico Um, alto (high), verdadeiro, alto
(logic low), terra (ground), VSS, negativo lógico (logic high), VDD, VCC, positivo

HiZ, alta impedância (high


impedance), tri-state, não direcionado
X, desconhecido (contenção de (undriven), desconectado, driver
barramento), não inicializado desabilidade (desconhecido)

112
High-Z (Alta Impedância)
• Representa um estado de alta impedância no circuito.
• O circuito comporta-se como se estivesse desconectado,
sem conduzir corrente elétrica.
• Usado em barramentos de três estados (tri-state buses)
para evitar conflitos de sinal.

Quando ocorre?
• Drivers desativados: Quando todos os drivers do
barramento estão desligados.
• Portas não conectadas: Dados ou portas que não
possuem conexão física.

113
Conceito de Tipo de Dados
• Ao declarar uma variável, é necessário reg op;
especificar seu tipo. Caso a variável
tenha mais de um bit, também é Tipo reg Nome(s) da variável
preciso definir sua largura. module mux
(
• Exemplo: as portas de um módulo, por input a, b,
padrão, são fios (wire) de um único input sel,
bit. output reg op
);
• É possível especificar o tipo e a
always @(a or b or
largura, conforme necessário. sel)
• Existem regras que determinam o uso if (sel == 1)
op = a;
dos tipos de dados: else
op = b;
• Exemplo: atribuições procedurais só
podem ser feitas para tipos de registro endmodule
(register). a 1
op
• Tipos permitidos: integer, b 0
real, reg, time, realtime. sel

114
Tipos de Dados
• Tipo de dado net: representa a interconexão física
entre estruturas.
Bloco nets Bloco nets
nets
funcional: funcional:
Mux (nets) Adder (nets)

• Tipo de dado variável: representa um elemento


que armazena dados temporariamente.
Armazenamento Temporário

115
Tipos de Dado Net
Tipo Definição
wire Representa um nó ou conexão
tri Representa um nó de três estados
supply0 0 lógico
supply1 1 lógico

• Identificadores não declarados utilizados nas conexões de


porta de instância são atribuídos, por padrão, ao tipo wire.
• Declarações de barramento:
• <data_type> [MSB:LSB] <signal name>;
• Exemplos:
• wire [7:0] out;
• tri enable;
116
Resolução de Conflitos Lógicos com Nets
• Se o mesmo barramento for
acionado por várias fontes,
ocorre um conflito. assign y =
a;
• Os tipos de barramento assign y =
possuem uma função de b;
resolução para determinar o
valor final do destino.
y declarado como y declarado como y declarado como
wire y; wand y; wor y;
tri y; triand y; trior y;

117
Tipos de Dados Variáveis
Tipo Definição
reg Variável sem sinal de qualquer tamanho
Utilize reg signed para implementação sinalizada
integer Variável com sinal de 32 bits
real* Armazena números de ponto flutuante
time* Variável inteira de 64 bits usada para representar o tempo de simulação
realtime* Variante de real, usada para medir tempos com ponto flutuante

• Só pode ser atribuída dentro de um processo (procedure), tarefa (task)


ou função (function).
• Declarações de barramento
• reg [MSB:LSB] <signal name>;
• Exemplos No desenvolvimento de circuitos, o uso
de Little Endian [MSB:LSB] é,
• reg [7:0] out; normalmente, adotado como padrão,
mas é possível encontrar projetos
• integer count; utilizando Big Endian [LSB:MSB].
*Sem suporte para síntese.
118
Regras de Conexão de Portas
• O diagrama mostra os critérios de tipos de dados para
conexão de portas quando módulos são instanciados.

Módulo de mais alto nível

Módulo de mais baixo nível

variável ou net output net

variável input net net inout net


ou net

119
Exemplo
DUT – Design Under Test

Input Port Output Port


net/register net net/register net
atop a y ytop
btop b net

Inout port
module top;
wire ytop;
reg atop, btop; net module dut (
input a, b,
initial output y
begin
);
atop = 1'b0;
btop = 1'b0;
end assign y = a & b;

dut U1 endmodule
(.a(atop), .y(ytop), .b(btop));

endmodule

120
Parâmetros
• Um parâmetro é um valor constante definido em um módulo para
controlar certos aspectos do seu comportamento ou
configuração.
• Largura de bits, variáveis, delays, valores iniciais etc.
• Pode ser sobrescrito para cada instância individual.
• Os parâmetros do módulo não podem ser modificados durante a
execução – eles não são variáveis.
Sintaxe Verilog 1995 Sintaxe Verilog 2001
module mux (a, b, sel, module mux #(parameter WIDTH =
out); 2)(
parameter WIDTH = 2; input [WIDTH-1:0] a, b;
input [WIDTH-1:0] a, input sel;
b; output [WIDTH-1:0] out;
input sel; reg [WIDTH-1:0] out;
output [WIDTH-1:0] out; );
reg [WIDTH-1:0] out; ...
... endmodule
endmodule
121
Parâmetros
• Ao instanciar o módulo mux, pode-se utilizar o valor padrão
do parâmetro (2) ou modificá-lo conforme necessário para
atender aos requisitos do design.

// Utilizando o parâmetro padrão (WIDTH = 2)


mux mux2
(.a(abus), .b(bbus), .sel(sel), .out(opbus);

// Sobrescrevendo o parâmetro
mux #(8) mux8
(.a(abus), .b(bbus), .sel(sel), .out(opbus);

122
Parâmetros
Parâmetros locais:
• localparam: idêntico aos parâmetros de módulo em
todos os aspectos, exceto pelo fato de não poder ser
sobrescrito.
• Usado para constantes que nunca devem ser sobrescritas
durante a instanciação.
parameter size = 8;
localparam outsize = 16;
reg [size-1:0] dataa, datab;
reg [outsize-1:0] out

...

123
Revisão
1. Qual é a principal diferença entre o tipo de dado net e
register (variável)?
2. O que significa declarar um sinal como inout em Verilog
e quando seria útil?
3. Quais são as implicações de declarar um sinal de porta de
módulo como wire ou reg?
4. Qual a principal diferença entre um parameter e um
localparam em Verilog e quando você deve usar cada
um?

124
Aula 7
Verilog – Tipos de Dados (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Tipos de Dados em exercícios práticos,
presentes no arquivo Relatórios Práticos – SD112 atividade
A-005.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-005.

126
Aula 8
Verilog – Operadores
Sistema de Numeração
• Valores numéricos são representados
como:
<size>'<base><value>
• size: número de bits.

• Números sem tamanho definido reg [3:0] zbus;
possuem, por padrão, 32 bits. …
zbus = 4'b1001; //1001
• base: pode ser b (binário), o zbus = 4'o05; //0101
(octal), d (decimal) ou h zbus = 4'd14; //1110
zbus = 4'h2f; //1111
(hexadecimal).

4'b1001 = 4'd9 =
4'o11.
• Números sem base definida são, por
padrão, decimais.
• value: qualquer número válido na
base escolhida (mais Z ou X, se for
binário, octal ou hexadecimal). 128
Sistema de Numeração
8'b1100_0001 Binário de 8 bits
64'hff01 Hexadecimal de 64 bits
9'o17 Octal de 9 bits
12 Base e tamanho não definidos (default: decimal de 32
bits)
'h83a Hexadecimal com tamanho não definido
32'bz z de 32 bits (x e z mais à esquerda são
automaticamente estendidos)
• Usa-se _ (underscore) para melhorar a legibilidade.
• Números negativos são especificados colocando-se um sinal de
menos antes do <size>.
• Correto: -8'd3 = Número negativo de 8 bits armazenado
como complemento de 2 de 3.
• Incorreto: 4'd-2 = ERROR!

129
Extensão Automática de
Números
• A base numérica utilizada
define quantos bits cada dígito reg [7:0] a;
reg [11:0] b;
representa: initial
• Um bit (binário) begin
// 0 passing contents of
• Três bits (octal) a
a = 8'h11; // 00010001
• Quatro bits (hexadecimal) a = 8'b11; // 00000011
a = 8'd11; // 00001011
• Se o bit mais significativo for a = 8'h01; // 00000001
um X ou Z, esse valor será a = 8'h10; // 00010000
estendido à esquerda para a = 0; // 00000000
pelo menos 32 bits.
// z padding contents of
• Verilog-2001: estende até b
a largura da expressão. b = 12'hzzz; //
zzzzzzzzzzzz
b = 12'hz; //
zzzzzzzzzzzz
b = 12'h0z; //
00000000zzzz
130
b = 12'hz0; //
Vetores
• Um vetor é um net ou reg com uma largura de dois ou mais bits.
• A largura é especificada ao declarar a variável:
[left position : right position]
• A convenção é utilizar [msb:lsb], e.g., [3:0].
module mux4 (
input wire [3:0] a, b, Vetor wire de 4 bits
input wire sel,
output reg [3:0] op
);
Vetor reg de 4 bits
always @ (a or b or sel)
if (sel == 1)
op = a;
else
op = b;

endmodule

131
Atribuição de Vetores e Ordem de Bits
• Os elementos de um vetor podem ser acessados
pela posição.
input [3:0] inp; reg [3:0] ibus;
output [3:0] reg [3:0] obus;
outp;
assign outp = obus = ibus;
inp;
outp[3 inp[3] obus[3 ibus[3
]
outp[2 inp[2] ]
obus[2 ]
ibus[2
]
outp[1 inp[1] ]
obus[1 ]
ibus[1
]
outp[0 inp[0] ]
obus[0 ]
ibus[0
] ] ]

132
Atribuição de Vetores e Ordem de Bits

assign outp[3] =
inp[0];
outp[3 inp[3]
]
outp[2 inp[2]
]
outp[1 inp[1]
]
outp[0 inp[0]
]
• Os elementos são acessados com base em sua posição, e
não pelo número do elemento — utilize o vetor de acordo
com a forma como ele foi declarado.

133
Atribuição de Vetores e
Largura de Bit
• As larguras dos vetores não precisam coincidir em uma atribuição.
• Se o vetor de origem for maior que o vetor de destino, ele
será truncado. Isso significa que os bits mais significativos
(MSB) do vetor de origem serão descartados para que o
tamanho do vetor de origem se ajuste ao tamanho do vetor
de destino.
• Se o vetor de origem for menor que o vetor de destino, o
vetor de destino será preenchido com 0 a partir dos bits
mais significativos (MSB) até atingir o tamanho necessário.
• Isso pode resultar em um comportamento indesejado, portanto, é
uma boa prática de codificação garantir que as larguras dos
vetores de destino e origem coincidam.
• Pode-se utilizar fatias (slices) e o operador de concatenação { }
para ajustar as larguras dos vetores de maneira mais flexível.

134
Atribuição de Vetores e
Largura de Bit
reg [3:0] zbus; // Vetor de 4
bits
reg [5:0] widebus; // Vetor de 6
bits
zbus = widebus =
widebus; zbus;
widebus[5 widebus[5 0
]
widebus[4 ]
widebus[4 0
zbus[3 ]
widebus[3 ]
widebus[3 zbus[3]
]
zbus[2 ]
widebus[2 ]
widebus[2 zbus[2]
]
zbus[1 ]
widebus[1 ]
widebus[1 zbus[1]
]
zbus[0 ]
widebus[0 ]
widebus[0 zbus[0]
] ] ]
slice concatenation
zbus = widebus = {2'b00,
widebus[3:0]; zbus};
135
Operadores Aritméticos
Símbolo do Operador Funcionalidade module arithops;
// Constantes locais Verilog-2001
+ Adicionar, positivo
localparam integer CONST_INT = -3
- Subtrair, negativo CONST_5 = 5;
localparam [3:0] rega = 3,
* Multiplicar regb = 4'b1010,
regc = 14;
/ Dividir
integer val;
% Módulo reg [3:0] num;

** Expoente initial
begin
• integer é com sinal. val = CONST_5 * CONST_INT; // -
15
• reg é sem sinal . val = (CONST_INT + 5)/2; // 1
• Verilog-2001 – pode-se val = CONST_5/CONST_INT; // -
1
declarar um reg com sinal. num = rega + regb; //
• Verilog-2001 – pode-se 1101
num = rega + 1; //
converter um valor com 0100
sinal e sem sinal utilizando 1101
num = CONST_INT; //

$signed e $unsigned. num = regc % rega; // 2


end

endmodule 136
Operadores Bit a Bit (Bit-wise)
Símbolo do Operador Funcionalidade
module bitwise;
~ NOT (bit a bit) reg [3:0] rega, regb, regc;
& AND (bit a bit) reg [3:0] num;

| OR (bit a bit) initial


begin
^ XOR (bit a bit)
rega = 4'b1001;
^~ ou ~^ XNOR (bit a bit) regb = 4'b1010;
regc = 4'b11x0;

• Operadores bit a bit são num = ~rega; // num =


aplicados diretamente sobre 0110
num = rega & 0; // num =
vetores binários. 0000
• As operações bit a bit, processam num = rega & regb; // num =
cada bit de forma independente. 1000
• Bits desconhecidos em um num = rega | regb; // num =
1011
operando não necessariamente num = regb & regc; // num =
levam a bits desconhecidos no 10x0
num = regb | regc; // num =
resultado. 1110
end 137
endmodule
Operadores Lógicos
Símbolo do Operador Funcionalidade
! Expressão não module logical;
verdadeira // Constantes locais Verilog-
2001
&& AND de duas localparam integer FIVE = 5;
expressões localparam [3:0] CONST_A =
|| OR de duas 4'b0011,
expressões CONST_B =
4'b10xz,
CONST_C =
4'b0z0x;
Os operadores lógicos
interpretam seus operandos reg ans;

como verdadeiro (1'b1), falso initial


(1'b0) ou desconhecido (1'bx). begin
ans = !CONST_A; //
• 1 — se qualquer bit for 1. 0
• 0 — se todos os bits forem 0. 0
ans = CONST_A && 0; //

• x — se qualquer bit for z ou x ans = CONST_A || 0; //


1
e nenhum bit for 1. ans = CONST_A && FIVE; //
1
ans = CONST_A && CONST_B; //
138
1
Operadores de Redução
Símbolo do Operador Funcionalidade
& AND de todos os bits
module reduction;
~& NAND de todos os bits // Constantes locais Verilog-
2001
| OR de todos os bits localparam [3:0] CONST_A =
4'b0100,
~| NOR de todos os bits CONST_B =
4'b1111;
^ XOR de todos os bits
reg val;
^~ ou ~^ XNOR de todos os bits
initial
begin
val =
• Operadores de redução realizam &CONST_A; // 0
val = |
uma operação bit a bit em todos CONST_A; // 1
val
os bits de um único operando. = &CONST_B; // 1
• O resultado é sempre 1’b1, 1’b0 val = |
CONST_B; // 1
ou 1’bx. val = ^CONST_A; // 1

val = ^CONST_B; // 0
val = ~|
CONST_A; // 0
val = 139
~&CONST_A; // 1
Operadores de Deslocamento
Símbolo do Operador Funcionalidade module shift ();
reg [7:0] rega =
<< Deslocamento lógico 8'b10011001;
para a esquerda reg [7:0] regb;
>> Deslocamento lógico
para a direita initial
<<< Deslocamento aritmético begin
para a esquerda regb = rega << 1;
// 00110010
>>> Deslocamento aritmético regb = rega >> 1;
para a direita // 01001100
regb = rega << -1;
// 00000000
end -1 é 2**32-1
endmodule
• Realizam deslocamentos de bits para a esquerda ou direita.
• Deslocamentos para a esquerda (lógico ou aritmético): posições vazias preenchidas com 0.
• Deslocamentos para a direita:
• Lógico: posições vazias preenchidas com 0
• Aritmético (sem sinal): posições vazias preenchidas com 0
• Aritmético (com sinal): posição vazia preenchida com o valor de sinal do bit valor do
MSB.
• Os bits deslocados são perdidos.

140
Operadores Relacionais
module relationals;
Símbolo do Operador Funcionalidade
reg [3:0] rega, regb,
> Maior que regc;
reg val;
< Menor que
>= Maior ou igual initial
begin
<= Menor ou igual
rega = 4'b0011;
regb = 4'b1010;
• Utilizados para comparar valores. regc = 4'b0x10;
• O resultado é: val = regc > rega;
• 1'b1 se a condição for // val = x
verdadeira; val = regb < rega;
// val = 0
• 1'b0 se a condição for falsa; val = regb >= rega;
• 1'bx se a condição não puder // val = 1
val = regb > regc;
ser resolvida. // val = x
end

endmodule
141
Operadores de Igualdade
Símbolo do Operador Funcionalidade
module equalities ();
== Igualdade reg [3:0] rega, regb, regc;
reg val;
!= Desigualdade
=== Igualdade estrita initial
begin
!== Desigualdade estrita rega = 4'b0011;
regb = 4'b1010;
• Utilizados para comparar valores. regc = 4'b1x10;

• Para as igualdades/desigualdades val = rega == regb; // val =


lógicas, x ou z são considerados 0
val = rega != regb; // val =
valores não conhecidos e o 1
resultado é sempre val = regb != regc; // val =
x
desconhecido. val = regc == regc; // val =
• Para as igualdades/desigualdades x
val = rega === regb; // val =
estritas, x ou z são considerados 0
valores distintos e os operandos val = rega !== regc; // val =
1
devem ser idênticos. val = regb === regc; // val =
0
val = regc === regc; // val 142
=
1
Outros Operadores
Símbolo do Operador Funcionalidade Símbolo do Operador Funcionalidade
?: Teste condicional { } Concatenar

module concatenation;
reg [7:0] rega, regb, regc, regd, new;
... reg [3:0] nib1, nib2;
wire out3;
reg out1, out2; initial
begin
rega = 8'b00000011;
always @ (a or b or sel) regb = 8'b00000100;
out1 = sel ? a : b; regc = 8'b00011000;
regd = 8'b11100000;
always @ (a or b or sel) new = {regd[6:5], regc[4:3],
if (sel) regb[3:0]};
out2 = a; // new = 8'b11_11_0100
else new = {2'b11, regb[7:5], rega[4:3],
1'b1};
out2 = b; // new = 8'b11_000_00_1
new = {regd[4:0], regd[7:5]};
assign out3 = sel ? a : // rotate regd right 3 places
b; // new = 8'b00000_111
{nib1, nib2} = rega;
... //nib1 = 4'0000, nib2 = 4'0011
end
endmodule
143
Outros Operadores
Símbolo do Operador Funcionalidade
{ { } } Replicar
module replicate ();
reg rega;
reg [1:0] regb;
• A replicação permite que reg [3:0] regc;
reg [7:0] bus;
você reproduza uma variável initial
begin
dimensionada um número rega = 1'b1;
regb = 2'b11;
determinado de vezes. regc = 4'b1001;

• Pode ser usada com bus = {8{rega}};


// bus = 11111111
concatenação. };
bus = { {4{rega}}, {2{regc[1:0]}}

• Sintaxe: // bus = 1111_01_01


bus = { regc, {2{regb}} };
{<repetitions> // bus = 1001_11_11
{<variable>}} bus = { 2{regc[2:1],
{2{1'b1}}} };
// bus = 00_1_1_00_1_1
end
endmodule

144
Prioridade de Operadores
Tipos de Operadores Símbolos
Alta
Concatenação/Replicação { } { { } }
Inversão (Lógica/Bit a Bit/Aritmética) ! ~ + -
Exponencial **
Aritmética * / %
+ - (binária)
Deslocamento << >> <<< >>>

Relacional < <= > >= Prioridade


Igualdade == != === !==
Bit a Bit/Redução & ~&
^ ^~ ~^
| ~|
Lógico &&
||
Condicional ? :
Baixa

145
Revisão
1. Quantos bits tem o resultado de uma operação lógica &&?
2. Reescreva a seguinte instrução utilizando um número
hexadecimal: aval = 8'b11010011
3. O que é necessário garantir ao replicar valores com o
operador de replicação?
4. Dado o seguinte código "regx = 4'b0101;", qual é
o valor de "bus = { 2{regx[3:1], {3{1'b0,
regx[0]}}} };"?
5. Se regb for definido como um número assinado de 4 bits
conforme abaixo, forneça o código para uma divisão
aritmética binária por dois. Dica: o bit de sinal (ou bit mais
significativo) deve permanecer intacto.
reg [3:0] regb;

146
Aula 9
Verilog – Operadores (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Operadores em exercícios práticos,
presentes no arquivo Relatórios Práticos – SD112 atividade
A-006.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-006.

148
Aula 10
Verilog – Declarações Processuais
e Contínuas
Declarações Contínuas (Continuous
Assignment)
Modela o comportamento de lógica
combinacional utilizando expressões
e operadores. /*implicit continuous assignment*/
wire [15:0] adder_out = mult_out +
1. O lado esquerdo da expressão out;
(left-hand side – LHS) deve ser é equivalente a
um dado do tipo net.
wire [15:0] adder_out;
2. Sempre ativo: quando um dos assign adder_out = mult_out +
operandos do lado direito da out
expressão (right-hand side –
RHS) muda, a expressão é
avaliada e o net LHS é
atualizado imediatamente.
3. O RHS pode ser net, register ou
funções. assign #5 adder_out = mult_out +
4. Valores de delay podem ser out
atribuídos para modelar
atrasos de portas lógicas.
150
Declarações Processuais (Procedural
Assignments)

Existem dois tipos de blocos reg a, b, zor, zand;
processuais
initial
• always: executa begin
a = 1'b1;
repetidamente ao longo da b = 1'b0; Verilog-2001:
simulação, sendo acionado end
Lista de eventos
por uma mudança no valor de always @* com operador
qualquer variável na lista de begin "coringa"
eventos. if (a | b)
zor = 1'b1;
• initial: executa apenas else
zor = 1'b0;
uma vez no início da
simulação. if (a & b)
zand = 1'b1;
• É necessário agrupar várias else
Blocos initial
instruções dentro de um bloco zand = 1'b0;
não são
end
usando begin...end. ... sintetizáveis.

151
Declarações Processuais (Procedural
Assignments)
• Atribuições feitas dentro
de blocos processuais module fulladder (
são chamadas de input a, b, cin,
output reg [1:0] out
atribuições processuais );
(procedural
reg sum, carry;
assignments).
always @(a, b, cin)
begin
• Todas as variáveis no sum = a ^ b ^ cin;
carry = (a & b) | cin & (a ^
lado esquerdo (LHS) b);
devem ser do tipo de out = {carry, sum};
end
dado register (por
exemplo, reg). endmodule

152
Lista de Eventos (Event List)
Lista de eventos construída
• Um evento é qualquer transição utilizando o operador or
dos sinais especificados. always @(a or b or sel)
if (sel == 1)
• O processo é reiniciado quando um op = a;
else
evento na lista de eventos ocorre. op = b;
• O Verilog-2001 adicionou os Lista de eventos construída
operadores vírgula e "coringa". utilizando o operador ','
always @(a, b, sel)
• O operador "coringa" adiciona if (sel == 1)
todos os sinais que entram no op = a;
else
bloco e em qualquer função op = b;
chamada a partir do bloco. Lista de eventos construída
• Nota: Parênteses são opcionais utilizando o coringa '*'
always @(*)
para expressões de evento if (sel == 1)
compostas por um único token. op = a;
else
op = b;

153
Tipos de Processo
Processo Combinacional
• Sensível a todas as entradas utilizadas na lógica combinacional.
A lista de eventos inclui
always @(a, b, sel)
todas as entradas
always @*
usadas na lógica
combinacional.

Processo Sequencial (clocked)


• Sensível ao clock e/ou sinais de controle.
always @(posedge clk, negedge
clr_n)
A lista de eventos não
inclui as entradas d ou ena,
somente o clock e os sinais
de controle assíncronos.

154
Blocos Processuais no Verilog
module design;
wire nsela;

wire nsel = !sel;


wire selb = sel & b;

always @(nsel or selb)


out = nsel | selb;

assign nsela = nsel & a;

always @(a or b or sel)


begin
// procedural
statements
end

// continuous statements

endmodule
155
Comando if
module if_example (
• if é um comando input [3:0] a, b, c, d,
condicional. );
output reg [3:0] y

• A condição é uma
always @(a or b or c or d)
expressão booleana. if (d == 4'b0000)
y = a;
• Cada condição do if else if (d <= 4'b0101)
é testada em y = b;
else
sequência. y = c;
• O primeiro teste válido endmodule
executa aquele ramo.
Estrutura de
• As condições podem se hardware inferida
sobrepor.
If sintetiza
em estruturas
de mux

156
Sintaxe do Comando If
if (CONDITION) begin • Comandos if únicos executam
// procedural instruções processuais apenas se
statements a condição for verdadeira...
end

if (CONDITION) begin
• ...adicione um else incondicional
// procedural para executar instruções
statements processuais quando a condição do
end
else begin
if for falsa...
// procedural • ...adicione else if para testar
statements
end outras condições caso a primeira
if (CONDITION) begin seja falsa.
// procedural
statements • O else final é opcional e pode
end ser usado para indicar uma
else if (CONDITION) begin operação padrão.
// procedural
statements • Use begin e end para delimitar
end
else begin
múltiplas instruções processuais.
// procedural
statements 157
Comando case
• case é um comando
condicional de múltiplas vias. module case_example (
input [3:0] a, b, c,
• A expressão do case é d,
avaliada e comparada com output reg [3:0] y
cada item em sequência. );

• Os itens do ramo podem always @*


se sobrepor. case (d)
0 : y = a;
• O primeiro item que 1, 2, 3, 4, 5 : y = b;
6 : y = c;
corresponder executa 7 : y = c;
aquele ramo. default : y =
4'b0000;
• O default opcional captura endcase
valores não especificados.
endmodule
• Neste exemplo, valores
contendo x ou z.
158
Sintaxe do Comando case
case (expression) • Use begin e end para delimitar
item 1 : statement
item 2 : statement múltiplos comandos processuais.
item 3,
item 4 : begin
• casex e casez permitem tratar
statements valores x e/ou z como condições
end "não se importa" (don’t care):
...
item n : statement • casex: x, z e ? são
default : statement considerados como don’t care.
endcase
casex (expression)
item 1 : statement
• casez: apenas z e ? são
... considerados como don’t care.
item n : statement
default : statement
endcase
casez (expression)
item 1 : statement
...
item n : statement
default : statement
endcase

159
Comandos casex e casez
• casex trata x, ? e z casex (encoder)
4'b1xxx : high_lvl = 3;
como "don't cares" ao 4'b01xx : high_lvl = 2;
4'b001x : high_lvl = 1;
invés de valores lógicos. 4'b0001 : high_lvl = 0;
default : high_lvl = 0;
endcase

Se encoder = 4'b1z0x,
então high_lvl = 3
casez (encoder)
• casez trata ambos z e ? 4'b1??? : high_lvl
4'b01?? : high_lvl
=
=
3;
2;
como "don't cares". 4'b001? : high_lvl
4'b0001 : high_lvl
=
=
1;
0;
default : high_lvl = 0;
endcase

Se encoder = 4'b1z0x,
então high_lvl = 3

160
Comando case Alternativo

module finscase (
input [3:0] a, b, c, • Um case item também
d, pode ser uma expressão.
input x, y,
output reg [3:0] op • É possível usar case para
);
verificar os valores de
always @* várias variáveis ao mesmo
case (1'b1) tempo.
x : op = a;
y : op = b; • Os itens são priorizados de
(c==d) : op = c;
default : op = d;
acordo com a ordem.
endcase

endmodule

161
Comandos em Loop: for
• O for é iterado no loop por um número especificado
de vezes.
• A variável de loop deve ser declarada.
• Quando o loop é executado:
• A variável de loop é inicializada.
• A(s) instrução(ões) do loop é(são) executada(s).
• A operação do loop é realizada.
• Quando a condição for falsa, o loop é encerrado.

162
Comandos em Loop: for
module parity (
input wire [3:0] a,
output reg odd
);

integer i;
reg tmp;

always @ a
begin // Expansão do loop for
tmp = 0; tmp = 0 ^ a[0]; // =
for (i = 0; i <= 3; i = i + a[0]
1) tmp = tmp ^ a[1];
tmp = tmp ^ a[i]; tmp = tmp ^ a[2];
odd = tmp; tmp = tmp ^ a[3];
end
O padrão de síntese
endmodule oferece suporte a loops
com limites constantes.

163
Comandos em Loop: repeat
module multiplier ( • O loop repeat executa
input [3:0] op_a, op_b,
output reg [7:0] result um bloco de declarações
); processuais um número
reg [7:0] shift_opa;
determinado de vezes,
reg [3:0] shift_opb; conforme especificado
always @(op_a, op_b)
pelo valor ou expressão
begin entre parênteses.
result = 0;
shift_opa = op_a; // Zero extend • Se uma variável isolada
left for usada na expressão
shift_opb = op_b;
repeat (4) de um loop repeat, o
begin valor da variável dita o
if (shift_opb[0])
result = result + shift_opa;
número de vezes que o
shift_opa = shift_opa << 1; \\ loop será executado.
left
shift_opb = shift_opb >> 1; \\ repeat (count)
right
end // executa o número
end de vezes = valor de
count 164
endmodule
Comandos em Loop: while
... • O loop while executa
while (count < 10) um bloco de declarações
begin
// statements procedurais enquanto
count = count + 1; sua expressão for
end verdadeira (ou diferente
... de zero). Se a expressão
... for inicialmente falsa, as
reg [7:0] tempreg; declarações não são
reg [3:0] count;
...
executadas.
// Count the ones in tempreg • Se uma variável isolada
count = 0;
while (tempreg) // tempreg = 8 for usada na expressão
begin de um loop while, o
if (tempreg[0]) tamanho da variável
count = count + 1;
tempreg = tempreg >> 1; // Shift determina o número de
right vezes que o loop será
end executado.
...

165
Sintaxe dos Comandos em
Loop
Comandos em Loop: // Variável de loop deve ser
declarada
• O loop for requer a declaração for (initial; condition;
de uma variável de loop. inc_dec)
begin
• O loop while continua // statements
enquanto a condição for end
while (condition)
verdadeira. begin
// statements
• O loop repeat itera o número end
de vezes definido pela expressão.
• O loop forever executa repeat (expression)
begin
indefinidamente. // statements
O padrão de síntese não end
suporta forever, repeat
e while. Use-os apenas em forever
testbenches e modelos de begin
simulação. // statements
end

166
Revisão
1. Se mais de uma condição de uma instrução
if...else for verdadeira, qual condição tem
prioridade?
2. As instruções if, case e for são contínuas ou
processuais?
3. Codifique a seguinte lógica condicional:

167
Página em branco.

168
Aula 11
Verilog – Declarações Processuais
e Contínuas (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Declarações Processuais e Contínuas em
exercícios práticos, presentes no arquivo Relatórios Práticos
– SD112 atividade A-007.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-007.

170
Aula 12
Verilog – Declarações Blocking
e Non-Blocking
Tipos de Atribuições
Processuais
• Declaração blocking (=): É executada imediatamente, ou seja, o
valor é atribuído à variável antes que as instruções seguintes
sejam processadas. É geralmente usada em blocos
combinacionais e segue uma execução sequencial, onde cada
linha deve ser concluída antes da próxima ser executada.

• Declaração non-blocking (<=): É usada em blocos sequenciais


(como always com @posedge), permitindo que o valor seja
calculado e armazenado, mas a atualização da variável é agendada
para o final do ciclo atual. Isso significa que outras operações
podem ser executadas sem esperar a conclusão da atribuição,
garantindo a simulação correta de circuitos sequenciais.
172
Declarações Blocking vs. Non-blocking

Blocking (=) Non-Blocking (<=)


initial initial
begin begin
a = #5 b; a <= #5 b;
c = #10 a; c <= #10
end a;
end

Assumindo inicialmente a = 1 e b = 2

a=b=2 c=2 a=b=2 c=a=1


5 10 15 5 10 15

173
Ciclo de Simulação
module sim_ex(
input a,
output reg m, y, w
);

always @(a or m)
begin:P1
m <= a;
y <= m;
end

always @(m)
begin: P2
w <= m;
• Assuma que a, m, y e end
w são todos 1'b0. endmodule
• a muda de valor de 1'b0
a : 0
para 1'b1. Valores das
m : 0
variáveis no
y : 0
começo:
w : 0

174
Ciclo de Simulação
module sim_ex(
input a,
output reg m, y, w
);

always @(a or m)
begin:P1
m <= a;
y <= m;
end

always @(m)
begin: P2
w <= m;
• a foi atualizado de 1'b0 para 1'b1. end
• O processo P1 é executado.
endmodule
• Atualização de m agendada.
• Nenhuma alteração no valor de y. Valores das
a : 1
m : 0
variáveis no
y : 0
começo:
w : 0

175
Ciclo de Simulação
module sim_ex(
input a,
output reg m, y, w
);

always @(a or m)
begin:P1
m <= a;
y <= m;
end

always @(m)
begin: P2
w <= m;
• m muda de valor para 1'b1. end
• O processo P1 é colocado na
endmodule
lista de agendamento.
• O processo P2 é colocado na a : 1
Valores das m : 1
lista de agendamento. variáveis depois y : 0
de um delta: w : 0

176
Ciclo de Simulação
module sim_ex(
input a,
output reg m, y, w
);

always @(a or m)
begin:P1
m <= a;
y <= m;
end

always @(m)
begin: P2
• Os processos P1 e P2 são w <= m;
end
executados (em ordem aleatória).
• Atualizações para y e w são endmodule

agendadas. a : 1
Valores das
• Nenhuma mudança no valor de m. m : 1
variáveis depois y : 0
de um delta: w : 0

177
Ciclo de Simulação
module sim_ex(
input a,
output reg m, y, w
);

always @(a or m)
begin:P1
m <= a;
y <= m;
end

always @(m)
begin: P2
• Y e w são atualizados para 1'b1. w <= m;
end
• Não há mais processos para
serem executados. endmodule

a : 1
Valores das m : 1
variáveis depois y : 1
de dois deltas: w : 1

178
Ciclo de Simulação: Resumo
a : 0
Valores das
m : 0
variáveis no module sim_ex(
y : 0 input a,
começo:
w : 0 output reg m, y, w
);
Lista de Eventos das Agendamento Valores das
Variáveis de Processos Variáveis
always @(a or m)
a <= 1 P1 a : 1 begin:P1
m : 0 m <= a;
y : 0 y <= m;
w : 0 end

m <= 1 P1 a : 1 always @(m)


P2 m : 1 begin: P2
y : 0 w <= m;
w : 0 end
y <= 1 a : 1
w <= 1 endmodule
m : 1
y : 1
w : 1

179
Ciclo Delta e Tempo de
Simulação
• Vários ciclos delta ocorrem em cada ponto no tempo de
simulação.
• É possível especificar o tempo de execução dentro dos
blocos processuais utilizando três tipos de controle de
tempo:
• Controle de tempo sensível à borda (edge): @
• Atrasos simples: #
• Controle de tempo sensível ao nível: wait

O padrão de síntese
não suporta wait.

180
Declarações Blocking vs. Non-blocking
always @(posedge clk) always @(posedge clk)
begin begin
x = next_x; x <= next_x;
end end

Mesmo
comportamento

always @(posedge clk) always @(posedge clk)


begin begin
x = next_x; x <= next_x;
y = x; y <= x;
end end

Comportamento
diferente

181
Declaração Blocking em Processos
Sequenciais
Declarações do tipo blocking podem levar a
“race conditions” quando: initial
begin
• Múltiplos processos são acionados pelo avar = 1'b1;
mesmo evento, de forma que... bvar = 1'b1;
end
• Um processo pode ler uma variável que
outro processo “simultaneamente” escreve. always @(posedge
clock)
Exemplo: bvar = avar + 1'b1
• Ambos os processos são executados na
always @(posedge
borda positiva do clock.
clock)
• Declarações blocking para bvar e cvar são cvar = bvar;
concluídas imediatamente após a execução
das instruções. Importante!
Os processos podem
• Mas qual instrução será executada primeiro?
ser executados em
• O valor de cvar depende de qual qualquer ordem.
procedimento é executado primeiro.

182
Declaração Non-blocking em Processos
Sequenciais
• Declarações non-blocking
evitam "race conditions".
• Exemplo: initial
begin
• Ambos os processos são avar = 1'b1;
bvar = 1'b1;
executados na borda positiva end
do clock. always @(posedge
• As atribuições para bvar e clock)bvar <= avar + 1'b1
cvar são agendadas.
always @(posedge
• A atribuição para cvar clock)
cvar <= bvar;
utiliza o valor de bvar antes
da borda de subida do clock.

183
Código Dependente da
Posição
• Declarações blocking em processos sequenciais podem
resultar em códigos dependentes de posição.
always @(posedge always @(posedge
clk) clk)
begin begin
b = a; d = c;
c = b; c = b;
d = c; b = a;
end end

Como seriam os diagramas se as declarações non-blocking fossem utilizadas?

184
Lógica Combinacional
always @(a or b) always @(a or b or m or n)
begin begin: P1
m = a; m <= a;
n = b; n <= b;
p = m + n; p <= m + n;
end end

• As declarações non-blocking
podem ser ineficientes para lógica
combinacional. Lista de Eventos Agendamento
de Variáveis de processos
• Especificamente, quando a lógica
contém comportamento serial ou a <= 1 P1
variáveis intermediárias: b <= 2
• Variáveis intermediárias m <= 1 P1
precisam ser adicionadas à lista n <= 2
de eventos. p <= 3
• O procedimento levará vários
ciclos delta para atingir o
“estado estável”.

185
Regra Prática

• Utilize a declaração blocking (=) para lógica


combinacional.
• Utilize a declaração non-blocking (<=) para lógica
sequencial.

186
Revisão
1. Qual é a principal diferença entre atribuições
blocking e non-blocking?
2. Onde você deve usar atribuições non-blocking?
3. Onde você deve usar atribuições blocking?

187
Página em branco.

188
Aula 13
Verilog – Declarações Blocking e
Non-Blocking (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Declarações Blocking e Non-blocking em
exercícios práticos, presentes no arquivo Relatórios Práticos
– SD112 atividade A-008.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-008.

190
Aula 14
Verilog – Reset síncrono e
assíncrono
Reset Síncrono
• O reset síncrono (synchronous module synchronous_reset_test
reset) é um tipo de reset que é (
acionado por um sinal de clock. Ou input clk, reset,
seja, o reset ocorre apenas em uma in1,
borda específica do clock (borda de output reg out1
subida ou de descida). );

• O reset é aplicado dentro do always @(posedge clk)


domínio do clock. Isso significa que if (reset)
o reset só afetará os flip-flops out <= 1'b0;
quando houver uma transição de else
out <= in1;
clock. endmodule
No exemplo acima, podemos observar
• O controle do reset está que a variável out1 só será alterada
sincronizado com o clock, o que com a borda de subida do clock
garante que não haverá transições (posedge clk). Para que o efeito do
assíncronas que possam criar reset ocorra, o sinal de reset deve ser
problemas de sincronização. longo o suficiente para ser capturado
pela próxima borda de subida do clock.

192
Reset Síncrono
Vantagens:
• Circuito completamente síncrono: O reset é acionado e
propagado de forma controlada em relação ao clock, garantindo
que todos os elementos do circuito sejam inicializados de forma
sincronizada.
• Menor chance de comportamento indesejado, como glitches ou
condições de corrida, pois o reset é controlado pelo clock.
• Mais fácil de prever o comportamento do circuito.
Desvantagens:
• Pode exigir mais lógica e recursos, pois precisa ser sincronizado
com o clock.
• O sinal de reset precisa ser estendido, caso não seja longo o
suficiente para ser capturado pela borda ativa do clock.
• A resposta ao reset é retardada em uma borda de clock, o que
pode ser uma limitação em sistemas de alta velocidade.

193
Reset Assíncrono

•O reset assíncrono module


(asynchronous reset) é um synchronous_reset_test (
input clk, reset,
tipo de reset que não depende in1,
do sinal de clock. output reg out1
);
• Quando o sinal de reset é
acionado, ele imediatamente always @(posedge clk or
força o estado do flip-flop ou posedge reset)
if (reset)
registrador para o valor out <= 1'b0;
desejado, independentemente else
out <= in1;
do clock. endmodule

194
Reset Assíncrono
Vantagens:
• Resposta mais rápida ao reset, pois não depende
do clock. O sistema é resetado imediatamente
quando o sinal de reset é ativado.
• Útil em situações onde a inicialização rápida do
sistema é necessária, como em sistemas de
recuperação de falhas.
Desvantagens:
• Pode causar problemas de sincronização, como
glitches e condições de corrida.
• Pode ser mais difícil de prever e controlar,
especialmente em sistemas complexos.
195
Reset Síncrono vs. Assíncrono
Síncrono Assíncrono
module dff_sync ( module dff_sync (
input d, clk, sclr, input d, clk, aclr,
spre output reg q
output reg q );
);
always @(posedge clk,
always @(posedge clk) posedge aclr)
begin begin
if (sclr) if (aclr)
q <= 1'b0; q <= 1'b0;
else if (spre) else
q <= 1'b1; q <= d;
else end
q <= d;
end endmodule

endmodule

196
Reset Síncrono vs. Assíncrono
• O reset síncrono é preferido quando a precisão e a
previsibilidade são cruciais, como em sistemas de
alta frequência.
• O reset assíncrono pode ser útil em situações onde
o tempo de resposta rápido é mais importante que
a sincronização precisa.
• Em alguns sistemas, pode ser tentador usar tanto
resets síncronos quanto assíncronos. No entanto,
isso exige cuidados extras para evitar conflitos e
problemas de sincronização.

197
Revisão
1. Quais são as diferenças entre reset síncrono e
assíncrono?
2. Quais são as vantagens do reset síncrono?
3. Quais são as vantagens do reset assíncrono?
4. Explique com suas palavras a diferença da
implementação, em nível de código, de um reset
síncrono e assíncrono.

198
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Reset Síncrono e Assíncrono em exercícios
práticos, presentes no arquivo Relatórios Práticos – SD112
atividade A-009.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-009.

199
Página em branco.

200
Aula 15
Verilog – Estilos de Códigos
Boas Práticas de
Implementação
Comentários em Verilog
1. Linha única:
 Representados com “//”.
 Qualquer texto à direita de // é ignorado pelo compilador.
 Exemplo:
// Este é um comentário de linha única
input a, b; // Comentário ao final da linha de
código
2. Bloco:
 Representados com “/* */”:
 Permitem comentários em várias linhas, mas não podem ser
alinhados.
 Exemplo:
/* Este é um comentário
que ocupa várias linhas
*/
202
Boas Práticas de
Implementação
Objetivo dos comentários
1. Ajudar no entendimento do código, especialmente para
leitores futuros.
2. Melhorar a comunicação entre desnvolvedores.
3. Esclarecer intenções em partes mais complexas do
código.
 Evite comentários óbvios ou desnecessários, como:

// Multiplica a e b e atribui
a c
c = a * b;

É desnecessário pois o código é autodescritivo. Use


comentários apenas quando necessário para explicar partes
não triviais do código.
203
Boas Práticas de
Implementação
Espaçamento e Organização
1. Verilog é uma linguagem de formato livre:
• Não impõe restrições sobre onde os espaços ou quebras de
linha devem ser usados.
• Exemplo de uso de espaçamento para melhor legibilidade:

assign sum = a ^ b; // Operação


XOR
assign carry = a & b; // Operação
AND
• O espaçamento uniforme facilita a leitura e o debug.

204
Boas Práticas de
Implementação
Espaçamento e Organização
2. Indentação e quebra de linhas:

• Estruturas como if, always e case devem ser organizadas


com indentação.
• A indentação melhora a leitura, especialmente para
estruturas alinhadas.

always @ (a or
b)
if (a > b)
op = a;
else
op = b;

205
Boas Práticas de
Implementação
Regras de Nomes de Identificadores
• Identificadores podem conter caracteres alfanuméricos
(a–z, A–Z, 0–9), incluindo o símbolo do dólar $ e o
sublinhado _.

• Devem começar com uma letra ou um sublinhado.

• Exemplos válidos:
• unit_32, structural, bus_16_bits, a$b.

206
Boas Práticas de
Implementação

Case Sensitive
• O Verilog diferencia entre maiúsculas e minúsculas (case
sensitive).

• ABC, Abc e abc seriam identificadores diferentes.

207
Boas Práticas de
Implementação

Restrições de Caracteres e Comprimento


• Identificadores não podem conter caracteres inválidos,
como @, - ou começar com números.

• Exemplos inválidos:
• unit@32, 16_bit_bus.
• Não há um limite estrito para o comprimento do nome,
mas ferramentas específicas podem restringir esse
tamanho.

208
Boas Práticas de
Implementação
Palavras-chave
• Palavras-chave em Verilog devem ser em minúsculas e não
podem ser usadas como identificadores. (ex.: module,
wire).

• Exemplos: • case • always • @(posedge)


• module • assign • @(negedge)
• wire • endcase • deassign • wait
• endmodule • for • force • disable
• input • while • release • function
• output • repeat • integer • endfunction
• inout • forever • real • task
• reg • begin • time • endtask
• if • end • # (“delay”) • default
• else • initial

209
Boas Práticas de
Implementação
Identificadores Escapados (Escape Identifiers)
• Permitem o uso de caracteres especiais ou nomes não
convencionais.

• Começam com uma barra invertida \ e terminam com um


espaço.

• Exemplos:
• \unit@32, \16-bit-bus.

• Embora sejam permitidos, os identificadores escapados


devem ser usados apenas em situações específicas, como
compatibilidade com bibliotecas ou ferramentas.

210
Boas Práticas de
Implementação

Recomendações
• Evitar o uso de palavras-chave como identificadores, mesmo
que tecnicamente permitido.

• Seguir padrões consistentes de nomenclatura para facilitar


leitura e manutenção.

• Usar identificadores escapados apenas quando necessário.

211
Boas Práticas de
Implementação
Compatibilidade e Ferramentas
• Identificadores escapados são úteis para lidar com
bibliotecas que exigem formatos específicos de nomes (ex.:
nomes de células de tecnologia que especificam o número
de entradas como 2nand, 4or).

Recomendações
• Para a maioria dos casos, use identificadores convencionais.
• Identificadores escapados devem ser a última alternativa,
sendo aplicáveis apenas em cenários de compatibilidade
técnica.

212
Boas Práticas de
Implementação
Latches
• Um latch é um elemento de memória simples que armazena
o estado de um sinal. Ele é transparente, ou seja, enquanto
o enable está ativo, o latch continua atualizando seu estado
com base no sinal de entrada. Quando o enable é
desativado, o latch mantém o último valor da entrada.

• É uma boa prática evitar descrições que resultem na


geração de latches, a menos que eles sejam necessários e
intencionalmente usados.

213
Boas Práticas de
Implementação
Evitando latches indesejados
• Falta de uma condição “else” em blocos combinacionais:
Quando uma variável não recebe valor para todas as condições
possíveis, um latch é inferido para armazenar o valor da variável
até que uma nova condição seja atendida.
Errado:
always @ (*) begin
if (enable)
out = data; // Não há valor definido para 'out' quando
enable = 0
end
Correto:
always @ (*) begin
out = 0; // Valor
padrão
if (enable)
out = data;
end

214
Boas Práticas de
Implementação
Evitando latches indesejados
Uso inadequado de lógica combinacional para memória: Descrever
memória sem utilizar flip-flops pode levar à criação de latches. No
exemplo abaixo, memory[address] depende de write_enable,
mas não há clock, o que faz com que a ferramenta infira um latch. Uma
boa prática é a utilização de um bloco sensível ao clock para descrever a
memória.
Errado:
always @ (*) begin
if (write_enable)
memory[address] = data; // Latch será inferido para
'memory[address]'
end
Correto:
always @ (posedge clk) begin
if (write_enable)
memory[address] <=
data;
end

215
Boas Práticas de
Implementação
Evitando latches indesejados
Lógica de seleção parcial (case incompleto): Ao usar um bloco “case”
sem cobrir todas as possibilidades, um latch será gerado para armazenar o
valor anterior. Uma boa prática é lidar com todas as condições possíveis,
incluindo o default.
always @ (*) begin
case (sel)
2'b00: out = a;
Errado: 2'b01: out = b;
// Outros valores de 'sel' não são
especificados
endcase
end
always @ (*) begin
case (sel)
2'b00: out = a;
Correto: 2'b01: out = b;
default: out = 0; // Valor padrão
endcase
end

216
Revisão
1. Qual a diferença entre a utilização de comentários com
“//” e “/* */” ?
2. Qual é o impacto da má organização no entendimento do
código?
3. Como garantir que um bloco case não gere latches
indesejados?
4. Por que é importante lembrar que Verilog é case
sensitive?

217
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Estilos de Código em exercícios práticos,
presentes no arquivo Relatórios Práticos – SD112 atividade
A-010.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-010.

218
Aula 16
Verilog - Descrição RTL
Níveis de Abstração

MUX

Comportamental
RTL (Register Transfer Estrutural
if sel == '0'
Level) then
out = IN1
else
out = IN2

case(sel)
'0': out = IN1
'1': out = IN2

220
Descrição RTL
• Descrição RTL, ou Register-Transfer Level, é um
nível de abstração onde os circuitos são descritos
em termos de registros e fluxo de dados entre eles.
• A descrição especifica como os dados são
transferidos de um registrador para outro, como
são processados ​e como os sinais de controle são
gerados para controlar o fluxo de dados e as
operações dentro do circuito.

221
Descrição RTL
• A imagem abaixo destaca o papel central da Descrição RTL
no processo de design de circuitos digitais, conectando a
abstração comportamental à implementação física do
hardware.

222
Por que o código é RTL?
1. Descrição em Termos de Operações em Portas e Sinais:
• O código descreve operações lógicas e conexões entre sinais, caracterizando o
nível RTL ao detalhar a lógica sem descer ao nível de transistores ou portas
básicas.
2. Uso de Operações Combinatórias:
module or_nand_1 (
• As operações or e nand são utilizadas input enable, x1, x2, x3,
para determinar os sinais intermediários x4,
(w1, w2, w3) e a saída (y), output logic y
);
caracterizando a lógica combinatória
logic w1, w2, w3;
típica de RTL, sem referências ao nível
estrutural do hardware. or (w1, x1, x2);
3. Abstração RTL: or (w2, x3, x4);
or (w3, x3, x4); //
• Não é puramente comportamental, pois Redundante
define explicitamente as portas e sinais nand (y, w1, w2, w3,
usados, nem estrutural, já que utiliza enable);
operadores lógicos em vez de instanciar endmodule
componentes ou portas físicas
diretamente.

223
Descrição RTL
module mux_2x1_rtl1(
• Exemplo MUX 2x1: input in1, in2, select,
output out
);
wire n_select, and1, and2;

not g1(n_select, select);


and g2(and1, select, in1);
and g3(and2, n_select,
in2);
or g4(out, and1, and2);
endmodule
module mux_2x1_rtl2(
input in1, in2, select,
output out
);
wire n_select, and1, and2;

assign n_select = ~select;


assign and1 = select & in1;
assign and2 = n_select &
in2;
assign out = and1 | and2;
endmodule

224
Descrição RTL
• Exemplo:

module combinational_circuit (
input A, B, C, // Entradas do circuito
output S // Saída do circuito
);

wire and_out, not_c, not_and_out, or_out1, or_out2;

// Operações intermediárias
assign and_out = A & B; // Porta AND entre A e B
assign not_c = ~C; // Inversão do sinal C
assign not_and_out = ~and_out; // Inversão da saída da porta AND
assign or_out1 = not_and_out | not_c; // Porta OR entre ~AND e ~C
assign not_or_out1 = ~or_out1; // Inversão da saída da porta OR1
assign not_b = ~B; // Inversão do sinal B
assign or_out2 = not_or_out1 | not_b; // Porta OR entre o resultado anterior e
~B

// Saída final
assign S = ~(or_out2);

endmodule

225
Revisão
1. O que é o RTL (Register Transfer Level) em
Verilog?
2. Quais são os três principais níveis de abstração
usados na descrição de circuitos?
3. Qual é o papel dos blocos assign na descrição
RTL?
4. No exemplo do MUX 2x1, como o seletor (select)
determina a saída (out)?

226
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Descrição RTL em exercícios práticos,
presentes no arquivo Relatórios Práticos – SD112 atividade
A-011.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-011.

227
Página em branco.

228
Aula 17
Verilog - Descrição
Comportamental
Descrição Comportamental
• É uma forma de representar circuitos digitais descrevendo
sua funcionalidade (função e algoritmo), sem detalhar
como o hardware realiza essas operações.
• Essa descrição está focada em “o que fazer” e não em
“como fazer”.

230
Descrição Comportamental
• A descrição comportamental é amplamente utilizada nas
fases iniciais do desenvolvimento para:
• Simular o comportamento funcional do design.
• Validar a lógica do circuito antes de detalhar a
implementação.
• Possui alta abstração e flexibilidade, facilitando ajustes
rápidos na lógica.
• Permite a criação de testbenches simples e rápidas para
verificar o comportamento funcional.
always @(*)
begin
if (sel)
out =
in2;
else
out =
in1;
end
231
Descrição Comportamental
Vantagens para simulações:
1. Detecção precoce de erros
 Identificação de problemas na lógica sem precisar
construir o hardware completo.
2. Prototipagem rápida
 Permite testar ideias de design rapidamente.
3. Custo reduzido
 Minimiza retrabalhos ao detectar falhas antes da
implementação física.

232
Descrição Comportamental
Exemplo: Multiplexador 2 para 1

module mux_2x1_behavioural1(
input in1, in2, select,
output out
);
assign out = select ? in2 :
in1;
endmodule

233
Descrição Comportamental
Exemplo: Multiplexador 2 para 1

module mux_2x1_behavioural2(
input in1, in2, select,
output out
);
reg muxout;
always @(*) begin
if (select)
// Se select for 1, saída recebe
in2
muxout <= in2;
else
// Se select for 0, saída recebe
in1
muxout <= in1;
end
assign out = muxout;
endmodule

234
Descrição Comportamental
Exemplo: Multiplexador 2 para 1

module mux_2x1_behavioural3(
input in1, in2, select,
output out
);
reg muxout;
always @(*) begin
case (select)
// Se select = 0, saída recebe
in1
1'b0 = muxout <= in1;
// Se select = 1, saída recebe
in2
1'b1 = muxout <= in2;
default = muxout <= 0;
endcase
end
assign out = muxout;
endmodule

235
Descrição Comportamental
Exemplo: Contador de 4 bits com Incremento

module counter_4bit (
input clk, // Clock
input reset, // Reset
output reg [3:0] count // Saída do
contador
);
always @(posedge clk or posedge reset)
begin
if (reset) begin
// Reseta o contador
count <= 4'b0000;
end else begin
// Incrementa o contador
count <= count + 1;
end
end
endmodule

236
Descrição Comportamental
Exemplo: Unidade Lógica e
Aritmética (ALU) Simples

module alu (
input [3:0] a, b, //Entrada de 4 bits
input [1:0] sel, // Sinal de seleção
input reg [3:0] result // Resultado
);
always @(*) begin
case (sel)
2'b00: result = a + b; // Soma
2'b01: result = a – b; //
Subtração
2'b10: result = a & b; // AND bit-
a-bit
2'b11: result = a | b; // OR bit-
a-bit
default: result = 4'b0000 // Valor
padrão
endcase
end 237
Descrição Comportamental
Exemplo: Registro de Deslocamento (Shift Register)

module shift_register (
input clk, // Clock
input reset, // Reset
input shift_in, // Bit de entrada
output reg [3:0] q // Saída do registro
);
always @(posedge clk or posedge reset) begin
if (reset) begin
q <= 4'0000 // Reseta o registro
end else begin
q <= {q[2:0], shift_in}; // Desloca os bits para a
direita
end
end
endmodule
238
Revisão
1. O que caracteriza uma descrição comportamental em
Verilog?
2. Quais são as principais vantagens da descrição
comportamental durante a simulação de circuitos?
3. Qual é a diferença entre descrição comportamental e a
descrição RTL?
4. O que acontece no código do contador de 4 bits quando o
sinal de reset é acionado?

239
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Descrição Comportamental em exercícios
práticos, presentes no arquivo Relatórios Práticos – SD112
atividade A-012.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-012.

240
Aula 18
Verilog - Descrição Estrutural
Descrição Estrutural
Definição
• A modelagem estrutural descreve o circuito ao especificar
explicitamente as conexões entre componentes pré-definidos.
• Similar ao diagrama esquemático, mas descrito textualmente.
• Baseia-se na instância de componentes como módulos definidos
anteriormente.

242
Descrição Estrutural

• Útil para representar sistemas complexos.


• Proporciona controle preciso das conexões entre
os elementos.
• Diagrama esquemático mais simplificado de um
circuito.
• Uma visão textual que corresponde ao diagrama.

243
Descrição Estrutural
Exemplo: Crossbar Switch
module mux_2x1_rtl1(
input in1, in2, select,
output out
);
wire n_select, and1, and2;

not g1(n_selct, select);


and g2(and1, select, in1);
and g3(and2, n_select,
in2);
or g4(out, and1, and2);
endmodule
module crossbar_structural(
input in1, in2, select,
output out1, out2
);
mux_2x1_rtl1 mux1(in1, in2, select, out1);
mux_2x1_rtl1 mux2(in2, in1, select, out2);

endmodule

244
Descrição Estrutural
Exemplo: Full Adder

245
Descrição Estrutural
module Add_half (sum, c_out, a, b);
Exemplo: Full Adder input a, b;
output sum, c_out;

// XOR para calcular a soma


parcial
assign sum = a ^ b;
// AND para calcular o carry-out
assign c_out = a & b;
endmodule
module Add_full (sum, c_out, a, b, c_in);
input a, b, c_in; // Entradas do somdor
output c_out, sum; // Saídas do somador
wire w1, w2, w3; // Fios intermediários

// Instâncias de dois Half Adders


Add_half M1 (w1, w2, a, b); // Primeiro meio somador
Add_half M2 (sum, w3, w1, c_in); // Segundo meio somador

// Porta OR para calcular o carry-out final


or (c_out, w2, w3);
endmodule

246
Descrição Estrutural
Exemplo: 4-bit
Adder

module full_adder (i0, i1, cin, s, cout);


input i0, i1, cin; // Entradas
output s, cout; // Saída e carry-
out

// Soma: XOR das entradas


assign s = i0 ^ i1 ^ cin;
// Carry-out
assign cout = (i0 & i1) | (cin & (i0 ^
i1));

247
Descrição Estrutural
Exemplo: 4-bit Adder
module four_bit_adder (a, b, cin, s, cout);
input [3:0] a, b; // Entradas de 4 bits
input cin; // Carry-in (entrada de transporte)
output [3:0] s; // Saída de 4 bits (soma)
output cout; // Carry-out (transporte final)
wire [2:0] cy; // Barramento de transporte intermediário

// Instâncias do módulo full_adder em uma única linha cada


full_adder fa_0(.i0(a[0]), .i1(b[0]), .cin(cin),
s(s[0]), .cout(cy[0]));
full_adder fa_1(.i0(a[1]), .i1(b[1]), .cin(cy[0]),
s(s[1]), .cout(cy[1]));
full_adder fa_2(.i0(a[2]), .i1(b[2]), .cin(cy[1]),
s(s[2]), .cout(cy[2]));
full_adder fa_3(.i0(a[3]), .i1(b[3]), .cin(cy[2]),
s(s[3]), .cout(cout));

endmodule

248
Descrição Mista
Exemplo: MultiplicadorAcumulador (MAC)
module mult_acc (outZ, inA, inB, clk, clr);
input [7:0] inA, inB; // Entradas de 8 bits
input clk, clr; // Entradas de clock e reset
output [15:0] outZ; // Saída acumulada de 16 bits

wire [15:0] mult_out, add_out;


reg [15:0] acc_out;

// Instância do módulo multiplicador


mult u1 (.P(mult_out), .A(inA), .B(inA));

// Instância do módulo somador


adder16b u2 (.S(add_out), .A(mult_out), .B(acc_out));

// Bloco sequencial –> accumulador igual a FF


always @ (posedge clk or posedge clr)
begin
if (clr)
acc_out <= 16'h0000;
else
acc_out <= add_out;
end

assign outZ = add_out;


endmodule

249
Revisão
1. O que caracteriza a descrição estrutural em Verilog?
2. Cite um exemplo de módulo estrutural e descreva sua
funcionalidade.
3. Qual é a função do “Crossbar Switch”? Como ele utiliza
instâncias de outros módulos?
4. Quais são os módulos básicos que compõem um “Full
Adder” em Verilog? Como eles interagem entre si?
5. Quais são as vantagens de usar a descrição estrutural em
sistemas complexos?

250
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Descrição Estrutural em exercícios práticos,
presentes no arquivo Relatórios Práticos – SD112 atividade
A-013.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-013.

251
Página em branco.

252
Aula 19
Verilog – Primitivas do Verilog e
Primitivas Definias por Usuário
O que são primitivas?
• Primitivas em Verilog são construções básicas utilizadas
como macros para representar o comportamento de
hardware em um nível mais próximo do físico.
• Elas modelam componentes lógicos simples, como portas
lógicas combinacionais e elementos sequenciais.

• As primitivas podem ser dividas em 2 grupos:


 Primitivas Predefinidas (built-in);
 Primitivas Definidas pelo Usuário (UDP)

254
Primitivas Predefinidas vs Definidas pelo
Usuário (UDP)
• Primitivas Predefinidas (Built-in) são fornecidas como parte
da linguagem Verilog e não podem ser modificadas. São 26
primitivas utilizadas para modelar portas lógicas e
transistores.

• Primitivas Definidas pelo Usuário (User Defined Primitive -


UDP) são criadas pelo projetista para descrever o
comportamento de circuitos em mais baixo nível para
modelos de simulação mais precisos. São personalizadas,
podendo implementar tanto circuitos combinacionais
quanto sequenciais, com base em tabelas da verdade.
Tipo de Primitiva Exemplo Característica
Predefinida (Built-in) AND, OR, PMOS Gates, buffers e transistores
Definida pelo Usuário (UDP) Mux, Flip-Flop Circuito customizado

255
Primitivas Predefinidas
Lista de tipos e primitivas da linguagem Verilog.

• Portas lógicas comuns são utilizadas para modelar circuitos


combinacionais.
• Portas do tipo tri-state incluem buffers e inversores com controle,
que assuem estado de alta impedância quando deligados.
• Transistores para modelar MOS switches são unidirecionais,
enquanto os transistores de transmissão são bidirecionais.
• Resistores de pull-up e pull-down também podem ser modelados
por meio de primitivas.

256
Primitivas Predefinidas
Tabela verdade para gates lógicos.

257
Primitivas Predefinidas
Tabela verdade para buffers e inversores.

258
Primitivas Predefinidas
Tabela verdade para transistores.

259
Pinos Primitivos são
Expansíveis
• Saídas são sempre definidas à esquerda, seguidas por dados
de entrada e controle mais à direita. Uma primitiva pode ter
múltiplas entradas, mas uma única saída.

260
Declaração de primitivas
• Gates: and, nand, or, nor, xor, xnor, buf, not
Estas primitivas servem para modelar portas lógicas
convencionais ou buffers. Suportam o assignment de drive
strength, delay, range e portas.
gate (drive_strength) #(2delays) instance_name[range] (list_of_ports);

• Gates tri-state: bufif0, bufif1, notif0, notif1


Este tipo de gate é controlável. Quando desabilitado, a saída
permanecerá em estado de alta impedância.
gate (drive_strength) #(3delays) instance_name[range] (list_of_ports);

261
Declaração de primitivas
• Gates: and, nand, or, nor, xor, xnor, buf, not
Estas primitivas servem para modelar portas lógicas
convencionais ou buffers. Suportam o assignment de drive
strength, delay, range e portas.
gate (drive_strength) #(2delays) instance_name[range] (list_of_ports);

• Gates tri-state: bufif0, bufif1, notif0, notif1


Este tipo de gate é controlável. Quando desabilitado, a saída
permanecerá em estado de alta impedância.
gate (drive_strength) #(3delays) instance_name[range] (list_of_ports);

262
Declaração de primitivas
• Transistores MOS de chaveamento: nmos, pmos, rnmos,
rpmos, cmos, rcmos,
Estas primitivas permitem modelar portas lógicas e circuitos a
nível de transistor. São extremamente úteis para um modelo de
simulação mais complexo, permitindo avaliar codinções de
corrida e outras mais a fundo. Possuem condução unidirecional.
gate #(3delays) instance_name[range] (list_of_ports);

• Transistores MOS de transmissão: rtranif0, rtranif1, rtran,


tranif0, tranif1, tran
São transistors com condução bidirecional, podendo ser
controlados ou não.
gate #(3delays) instance_name[range] (list_of_ports);
(para rtran e tran) gate instance_name[range] (list_of_ports);

263
Declaração de primitivas
• Resistores de pull-up e pull-down: pullup, pulldown
Utilizados para modelar o drive de um sinal para valor lógico 1
(pull-up) ou 0 (pull-down).
pullup (pullup_strength) instance_name[range] (list_of_ports);
pulldown (pulldown_strength) instance_name[range] (list_of_ports);

264
Declaração de primitivas
• Opcionalmente pode-se omitir o nome da instância:
and (out, in1, in2, in3, in4); // Instância sem
nome
buf b1 (out1, out2, in); // Instância com
nome
• Especificar as saídas antes das entradas. As saídas SEMPRE são
declaradas antes das entradas no código Verilog.

• Opcionalmente especificar atraso da primitiva (se suportado):


notif0 #3.1 n1 (out, in cntrl); // Atraso
especificado

• Opcionalmente especificar a força do sinal:


not (strong1, weak0) n2 (inv, bit); // Força do sinal
not (strong1) #2.5 n3 (op, ip); // Força do sinal e
atraso

265
Primitivas Definidas pelo Usuário (UDPs)
• As Primitivas Definidas pelo Usuário (UDPs) permitem criar
primitivas personalizadas no Verilog para modelar
comportamentos lógicos específicos. Seu formato é baseado em
tabelas da verdade. São utilizadas apenas para simulação, uma
vez que não são sintetizáveis.

Pontos chaves:
✅Complementam primitivas existentes: Permitem adicionar elementos ao
conjunto padrão de primitivas do Verilog.
✅ Independentes: UDPs não instanciam outros módulos.
✅ Suportam comportamentos combinacionais e sequenciais.
✅ Definição simples: O comportamento é descrito em uma tabela da
verdade.
✅ Instanciação intuitiva: UDPs são instanciadas assim como as primitivas
built-in.
266
Características das UDPs
✅ Podem ter apenas uma saída.
✅ Podem ter de 1 a 10 entradas.
✅Todas as portas devem ser escalares e portas bidirecionais
não são permitidas.
✅ O valor lógico Z (alta impedância) não é suportado.
✅ A porta de saída deve ser listada primeiro na lista de portas.
✅ O terminal de saída do UDP pode ser inicializado com um
valor conhecido no início da simulação.
✅ UDPs não podem ser sintetizados.

267
Tabelas verdade
Símbolo Descrição Exemplo de Uso
0 Representa um nível lógico baixo 0 (zero volt ou
(LOW). nível baixo)
1 Representa um nível lógico alto 1 (tensão alta ou
(HIGH). nível alto)
X Valor indefinido ou desconhecido, X (estado incerto)
comum durante simulação quando o
estado não pode ser determinado.
? Coringa que aceita qualquer valor 0, 1 ou X
entre 0, 1 e X. Satisfaz a lógica (qualquer valor)
independente do valor.
B Representa valores binários válidos (0 0 ou 1 (binário)
ou 1). Não permite X como valor
válido.

268
Tabelas verdade
Símbolo Descrição Exemplo de Uso
- Representa sem mudança no estado de saída -
ou próximo estado.
(vw) Indica uma relação onde v pertence a {0, 1, x} v ∈ {0, 1, x} ->
e w pertence a {0, 1, x} w ∈ {0, 1, x}
* Representa qualquer combinação entre {0, 1, * : {0, 1, x} ->
x} e mapeia para {0, 1, x} {0, 1, x}
r Indica uma transição crescente (0 -> 1). r : (01)
f Indica uma transição decrescente (1 -> 0). f : (10)
p Representa uma mudança para 1 ou estado (01), (0x), (x1),
indefinido. Inclui variações de 0x, 1x, etc. (0z), (z1)
n Representa uma mudança para 0 ou estado (10), (1x), (x0),
indefinido. Inclui variações de 1x, x0, etc. (1z), (z0)

269
Primitivas Definidas pelo Usuário
(UDP)
• Primitiva que implementa
um Flip-Flop tipo D
simples:

primitive d_flipflop (q, d, clk);


output q; // Saída do flip-flop
input d, clk; // Entradas: Dados e Clock
reg q;

table
// d clk : q : q+
0 (01) : ? : 0; // Armazena '0' na borda de subida
1 (01) : ? : 1; // Armazena '1' na borda de subida
? (0?) : ? : -; // Sem mudança durante borda descendente ou nível
baixo
endtable
endprimitive

270
Primitivas Definidas pelo Usuário
(UDP)
• Um latch SR sensível ao nível
com entradas Set e Reset:

primitive sr_latch (q, s, r);


output q; // Saída do latch
input s, r; // Entradas: Set e Reset
reg q; // Estado interno do
latch

table
// s r : q : q+
0 0 : ? : -; // Sem mudança
1 0 : ? : 1; // Set ativo
0 1 : ? : 0; // Reset ativo
1 1 : ? : x; // Estado indefinido
endtable
endprimitive

271
Primitivas Definidas pelo Usuário
(UDP)
• Um Multiplexador 2:1:

primitive multiplexer (o, a, b,


s);
output o;
input a, b, s;

table
// a b s : o
0 ? 1 : 0;
1 ? 1 : 1;
? 0 0 : 0;
? 1 0 : 1;
0 0 x : 0;
1 1 x : 1;
endtable
endprimitive

272
Primitivas Definidas pelo Usuário
(UDP)
• Um Flip-Flop com primitive u_ff_p_cl (q, clk, data,
clr);
Clear Síncrono: input clk, data, clr;

output q;
reg q;
table
// clk data clr próximo estado
r ? 1 : ? : 0;
r 0 ? : ? : 0;
r 1 0 : ? : 1;

// Reduz pessimismo
p 0 ? : 0 : -;
p 1 0 : 0 : -;
p 1 0 : 1 : -;

// Ignora borda de block


inativa
n ? ? : ? : -;

// Ignora transições de dados


? * ? : ? : -;
? ? * : ? : -;
endtable
endprimitive
273
Primitivas Sequenciais
• n entradas: o número de entradas n refere-se às entradas lógicas que
influenciam o comportamento da primitiva sequencial.
• 1 estado e 1 saída: em primitivas sequenciais, a saída não depende
apenas das entradas, mas também do histórico, ou seja, do estado
anterior.
• n + 2 colunas: descreve a estrutura usada para definir o comportamento
de primitivas sequenciais. As colunas incluem:
 Entradas, estado atual, saída (próximo estado).
• Dois tipos:
 Sensível à borda: A primitiva é  Sensível ao nível: A primitiva é
ativada apenas durante a ativada enquanto o sinal de
transição (subida ou descida) controle (ex.: clock) estiver em um
de um sinal. nível lógico específico (0 ou 1).

274
Primitivas Sequenciais
primitive dff(q, clk, data);
output q; reg q;
input clk, data;
table
// clk data q new-q
(01) 0 : ? : 0; // Travar em 0
(01) 1 : ? : 1; // Travar em 1
(0x) 1 : 1 : 1; // Manter quando d e q são
ambos 1
(0x) 0 : 0 : 0; // Manter quando d e q são
ambos 0
(?0) ? : ? : -; // Manter quando clk cai
(??) ? : ? : -; // Manter quando clk estável
endtable
CLK D Q(n+1)
endprimitive Condição
0 x Qn Sem mudança
1 x Qn Sem mudança
↓ x Qn Sem mudança
↑ 0 0 Q segue a entrada D
↑ 1 1 Q segue a entrada D

275
Primitivas em nível de
chaveamento
• Primitivas de chaveamento são modelos simples que
representam transistores como chaves digitais (ON/OFF).​
• O Verilog fornece primitivas unidirecionais e bidirecionais que
podem ser utilizadas para modelar redes de chaveamento.
• Primitivas unidirecionais:
Permitem a passagem de CMOS
corrente apenas em um
sentido:
 cmos, nmos, pmos,
pullup
• Primitivas bidirecionais:
Permitem a passagem de
corrente nos dois sentidos.
 tran, tranif0,
tranif1

276
Primitivas em nível de
chaveamento
• Exemplo de implementação de uma porta NAND com CMOS, utilizando
primitivas de chaveamento. Esses códigos são especialmente úteis para
simular o comportamento de circuitos em um nível mais próximo do
hardware real.
module cmos_nand_gate(output Y, input A, B);
supply1 Vdd; // Alimentação positiva
supply0 GND; // Alimentação negativa

wire nmos1, nmos2, pmos1, pmos2;

// NMOS Transistors (em série)


nmos (nmos1, A, GND);
nmos (nmos2, B, nmos1);

// PMOS Transistors (em paralelo)


pmos (pmos1, A, Vdd);
pmos (pmos2, B, Vdd);

// Saída beaseada nas conexões


assign Y = ~(nmos2 & pmos2); //Porta
NAND
endmodule

277
Primitivas em nível de
chaveamento
• Modelagem detalhada: um
esquema de modelagem mais
aprofundado, capaz de
identificar problemas elétricos
adicionais que podem surgir ao
utilizar transistores dessa forma.
• Uso atual: Circuitos geralmente
não são projetados dessa forma.
• Simulação avançada: Esses
circuitos são frequentemente
simulados com softwares
semelhantes ao SPICE, que
utilizam solucionadores de
equações diferenciais não
lineares.

278
Primitiva de Transporte
• Definição:
Primitivas de transporte são
blocos básicos em linguagens de
descrição de hardware, como
Verilog, que implementam
funções lógicas simples.

• Aplicação:
As primitivas de transporte são
amplamente usadas para
descrever operações como carry
(transporte) em somadores
binários e outras funções lógicas
em circuitos digitais.
279
Primitiva de Transporte: Exemplo e
Funcionamento
• A primitiva “carry” descreve o comportamento de um bit de transporte
em circuitos combinacionais, com base na tabela de verdade
apresentada.
primitive carry(out, a, b, c);
output out; // Sempre possui exatamente uma saída A B C Out
input a, b, c;
0 0 ? 0
// A tabela da verdade pode incluir entradas "não
importa" (?) ? 0 0 0
table
00? : 0;
? 0 0 0
?0? : 0; 1 1 ? 1
?00 : 0;
11? : 1; 1 ? 1 1
1?1 : 1;
?11 : 1; ? 1 1 1
endtable
endprimitive

• Essas primitivas são frequentemente utilizadas em circuitos


aritméticos, como somadores, para controlar o bit de transporte
(“carry”).

280
Revisão
1. O que são primitivas em Verilog e quais são os dois tipos
principais?
2. Qual a diferença entre primitivas predefinidas e definidas
pelo usuário (UDPs)?
3. Qual é a função de uma primitiva condicional como
bufif0 e notif0?
4. Explique a diferença da primitiva sensível à borda e
sensível ao nível.
5. Qual a diferença entre primitivas unidirecionais e
bidirecionais?
6. O que caracteriza uma UDP combinacional e uma UDP
sequencial?

281
Aula 20
Verilog – Primitivas do Verilog e
Primitivas Definias por Usuário
(cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Primitivas do Verilog e Primitivas Definidas
por Usuário em exercícios práticos, presentes no arquivo
Relatórios Práticos – SD112 atividade A-014.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-014.

283
Aula 21
Verilog - Codificação para
Síntese e Simulação
Fluxos Típicos de Síntese RTL e
Simulação RTL

285
Simulação

286
Síntese de circuitos

287
Simulação vs. Síntese
• Simulação
• Código executado exatamente como escrito;
• Usuário tem flexibilidade na escrita de modelos
comportamentais;
• Inicialização lógica totalmente suportada;
• Síntese
• Código é interpretado e o hardware criado;
• As ferramentas de síntese exigem uma codificação
específica para gerar a lógica correta;
• O estilo de codificação é importante para lógica rápida e
eficiente;
• As lógicas Pré & Pós- síntese devem funcionar da mesma
maneira!

288
Síntese
• Síntese é o processo de transformar uma descrição em HDL
(como Verilog ou VHDL) em um circuito físico que pode ser
implementado no hardware.
• Esse processo inclui a tradução de operações abstratas
(como transferências entre registradores e operações
aritméticas) em uma rede de portas lógicas.
• O sintetizador pega a descrição em RTL e gera uma
representação do circuito no nível de portas lógicas.

289
Síntese
• Converte código HDL (RTL) em uma netlist.
• O código HDL (descrito no nível RTL) é transformado em uma
netlist, que é uma descrição do circuito no nível de portas
lógicas e interconexões.
• Simulação Pós-Síntese: Garante que a funcionalidade
permanece alinhada.
• Ferramentas de síntese (como Vivado, Quartus ou Synopsys
Design Compiler) mapeiam a netlist gerada para a tecnologia de
destino:
Implementam para FPGA ou criam layouts físicos para ASIC.
• Objetivo da Síntese:
Criar uma representação física do design que possa ser
implementada em hardware real.

290
Síntese

291
Objetivos da Síntese
• Minimizar a área: Em termos de contagem de literais,
contagem de células, contagem de registradores, etc.
• Minimizar o consumo de energia: Em termos de atividade
de comutação em portas individuais, blocos de circuito
desativados, etc.
• Maximizar o desempenho: Em termos de frequência
máxima de clock em sistemas síncronos e taxa de
processamento para sistemas assíncronos.
• Qualquer combinação dos itens acima: Por exemplo um
problema de restrição: “minimizar a área para uma
velocidade de clock > 300 MHz”.
• Mais objetivos globais: Tamanhos físicos reais, atrasos,
posicionamento e roteamento.

292
Restrições na Síntese
• Estilo de implementação fornecido
• Implementação em dois níveis (PLA, CAMs);
• Lógica multinível;
• FPGAs.
• Requisitos de desempenho fornecidos
• Requisito mínimo de velocidade de clock;
• Latência mínima, vazão (throughput).
• Biblioteca de células fornecida:
• Conjunto de células na biblioteca padrão de células;
• Restrições de fan-out (número máximo de portas
conectadas a outra porta);
• Geradores de células.

293
Síntese RTL

294
Estruturas Sintetizáveis em
Verilog
• module • Portas
• port • and, nand, nor, or,
• parameter xor, xnor
• Tipos de dados de rede • buf, not, bufif0,
• wire, tri, tri0, tri1 bufif1, notif0, notif1
• wor, wand, trior,
triand • Primitivas definidas pelo
• supply0, supply1
usuário (UDP)
• Atribuições Blocking e Non-
• Tipos de dados variáveis
Blocking
(registros)
• reg, integer • Blocos Sequenciais
• Tasks & funções
• assign (contínuo) • Seleção de bits & partes
• always & initial blocks

295
Estruturas Sintetizáveis em Verilog
(continuação)
 Estruturas Comportamentais
 If-else • As ferramentas de síntese
 Case podem impor certas
 Loop (com restrições)
restrições sobre as
 disable
 Instanciação de módulos estruturas suportadas.
• Consulte a ajuda online no
 Tasks de Sistema readmemb e
software Quartus® (ou na
readmemh
 Diretivas do compilador: ferramenta de síntese alvo)
 `define, `undef, `ifdef, para uma lista completa.
`else, `endif • O software Quartus®
 `include suporta muitas estruturas
 `unconnected_drive que não são compatíveis
[pull0|pull1],
com outras ferramentas de
`nounconnected_drive
 `resetall síntese.

296
Estruturas Não-Sintetizáveis em
Verilog
• Estas são algumas das estruturas não suportadas pela síntese de
software Quartus®:
 Tipos de dados de rede  force e release (para redes e
 trireg registradores)
 Tipos de dados variáveis  Controle de delays
 time, real, realtime  Eventos (intra-procedural)
 Portas lógicas  Evento nomeado;
 rtran, tran, tranif0, 
Estruturas de paralelismo (fork
tranif1,
 rtranif0, rtranif1 e join)
 Blocos de especificação
 Chaves
 cmos,
 Diretivas de tempo
nmos, rcmos,
rnmos, pmos, rpmos
 Maioria das tarefas de sistema
 pullup e pulldown (ex.: $display)
 Força de condução
 assign (contínuo procedural) e
deassign

297
Operadores
• As ferramentas de síntese substituem operadores por
blocos de lógica predefinidos (pré-otimizados).

• O projetista deve estar ciente do uso de operadores e


controlar quando e quantos são usados.

• Exemplo: divisores
• Divisores são grandes blocos de lógica.
• Cada “/” (divisão) e “%” (módulo) insere um bloco
divisor e deixa para a síntese a tarefa de otimizá-lo.
• Uma melhor otimização de recursos geralmente
envolve o uso criativo de multiplicadores ou
operações de deslocamento (shifts) para realizar
divisões.
298
Gerando Lógica de
Operadores

• As ferramentas de
síntese dividem o
código em blocos
lógicos.
• Em seguida, elas
montam, otimizam
e mapeiam para o
hardware.

299
Estruturando Procedimentos

Pergunta
Este
Este códigocódigo
pode descrever
pode
always @(posedge clk) essa lógica, ou
descrever seja,lógica,
essa é ou
begin possível
seja, é descrever
possível adescrever
// lógica nos blocos A e estrutura acima usando um
a estrutura acima usando
B único procedimento
um único procedimento
sequencial?
end
sequencial?

300
Síntese de Declarações if

module if_example (
input a, b, c,
input [3:0] ctrl,
output reg op
); Pergunta

always @(a or b or c or Desenhe a


ctrl) arquitetura de
if (ctrl == 4'h0) hardware que
op = a;
else if (ctrl <= 4'h4) isso representa.
op = b;
else
op = c;
endmodule

301
A Arquitetura Inicial de Declarações
if e case

if (ctrl == 4'h0)
op = a;
else if (ctrl <= 4'h4)
op = b;
else
op = c;

case (ctrl)
0: op = Síntese
a;
0, 1, 2, 3, 4: op = b; Como isso mudaria se
default: op = c; orientássemos a ferramenta
endcase de síntese a construir os
ramos do case em paralelo?

302
Declarações de case Paralelo
• Ferramentas de síntese são capazes
de construir ramos de case
mutuamente exclusivos sem a
necessidade de uma estrutura de (* synthesis, parallel_case
*)
prioridade. case (1)
• As ferramentas de síntese podem this: op = a;
identificar automaticamente um that: op = b;
case claramente paralelo. Para default: op = c;
endcase
situações em que isso não ocorre, é
possível utilizar as seguintes opções:
• Metacomentário (ainda aceito):
// ambit synthesis case =
full
• Atributo do Verilog-2001
(padrão atual):
(* synthesis, parallel_case
*)

303
Diretivas de Síntese
• A maioria das ferramentas de síntese também aceita diretivas
de síntese como metacomentários.
• Metacomentários são comentários em Verilog, ignorados pela
simulação, mas significativos para outras ferramentas.
• Seu efeito é idêntico ao do atributo de síntese padrão.

case (test) // ambit synthesis


parallel_case
2'b00: op = a;
2'b01,
2'b10: op = b;
2'b11: op = c;
default: $display("unknown test!");
endcase

304
Síntese de Declarações casex
• As declarações casex e casez
always @(pri_in)
permitem que você especifique casex (pri_in)
posições de bits como "não 4'b1???: op = 3;
importa" (don’t-care). 4'b01??: op = 2;
• A ferramenta de síntese 4'b001?: op = 1;
interpreta essas declarações 4'b0001: op = 0;
exatamente como interpreta a default: op = 0;
declaração case. endcase
• Por vezes, pode ser difícil end
determinar se uma declaração
always @(ctrl) begin
casex ou casez é realmente
int = 3'b000;
paralela. casex (ctrl)
3'b??1: int[0] =
Pergunta 1'b1;
3'b?1?: int[1] =
Essas declarações 1'b1;
casex são 3'b1??: int[2] =
1'b1;
paralelas? endcase
end 305
Declarações de full_case
• Lógica Combinacional: A saída é determinada // no latch
always @(ctrl or a or
a todo momento pelo estado atual das b)
entradas. Se existir uma combinação de case (ctrl)
entradas para a qual a saída não esteja 0,1: op = a;
2: op = b;
definida, a ferramenta de síntese irá acionar 3: op = 1'bx;
um latch para essa combinação. endcase
// no latch
reg [1:0] ctrl; always @(ctrl or a or b)
reg a, b, op; case (ctrl)
0,1: op = a;
// latch op when ctrl == 2: op = b;
3 default: op =
always @(ctrl or a or b) 1'bx;
case (ctrl) endcase
// no latch
0,1: op = a;
always @(ctrl or a or b)
2: op = b;
begin
endcase op = 1'bx
Síntese case (ctrl)
Atribuir o estado desconhecido ‘x’ informa à 0,1: op = a;
2: op = b;
ferramenta de síntese que você não se importa com endcase
qual será a saída para aquela combinação de entradas. end

306
O Atributo full_case
• O padrão de síntese suporta o // no latch
atributo full_case para forçar a always @(ctrl or a or b)
(* synthesis, full_case
ferramenta de síntese a assumir *)
que todos os ramos do case estão case (ctrl)
representados. 0,1: op = a;
• É equivalente a um item de 2: op = b;
endcase
correspondência default case
que atribui "não importa" (don’t-
care) a todas as saídas. // no latch
always @(ctrl or a or b)
case (ctrl)
Atenção: 0,1: op = a;
• Ele não realiza nenhuma função 2: op = b;
além daquela que um item de default: op =
1'bx;
correspondência default case endcase
já pode executar. Além disso, não
impede a inferência de latches.

307
Ainda é Possível Obter
Latches!
A ferramenta de síntese ainda
pode inferir latches para uma module select (
input wire [1:0] sel,
declaração de case marcada output reg a, b
com full_case. );
• O atributo full_case
always @(sel) begin
aplica-se apenas às a = 0; b = 0; // Evita latch para a
expressões de (* sythesis, full_case *)
case (sel)
correspondência do case. 2'b00: begin a = 0; b = 0; end
• Qualquer variável que não 2'b01: begin a = 1; b = 1; end
2'b10: begin a = 0; b = 1; end
for totalmente atribuída no 2'b11: b = 1;
bloco combinacional ainda default: begin a = 'bx; b = 'bx;
end
será armazenada em latch. endcase
• Atribuições default end
evitam a inferência de
endmodule
latches — use-as!

308
Síntese de Declarações initial
— Não!
module counter ( module counter (
input wire clk, input wire clk,
output reg [3:0] rst,
q output reg [3:0]
); q
);
initial q = 0;
always @(posedge clk)
always @(posedge clk) if (rst)
if (q == 9) q <= 4'h0;
q <= 4'h0; else if (q == 9)
else q <= 4'h0;
q <= q + 1; else
q <= q + 1;
endmodule
endmodule
Síntese
O padrão de síntese suporta a construção initial apenas para a
inicialização de dados de ROM e exige que seja acompanhada pelos
atributos logic_block ou rom_block.

309
Inferência de Registradores para
Atribuição Blocking
module blockshift (
input wire clk, ip, always @(posedge clk)
output reg op begin
); // expansão do loop do
reg [7:0] shift_reg; for
integer i; op = shift_reg[7];
shift_reg[7] =
always @(posedge clk) shift_reg[6];
begin shift_reg[6] =
op = shift_reg[7]; shift_reg[5];
for (i = 7, i > 0, i = i – 1) shift_reg[5] =
shift_reg[i] = shift_reg[4];
shift_reg[i-1]; shift_reg[4] =
shift_reg[0] = ip; shift_reg[3];
end shift_reg[3] =
endmodule shift_reg[2];
• Para uma atribuição
shift_reg[2] = do tipo
blocking, um registrador é
shift_reg[1];
Pergunta shift_reg[1]
inferido =
se a variável for lida
shift_reg[0];
Quantos registradores antes de ser escrita.
shift_reg[0] = ip;
são inferidos? end

310
Atribuição de Variável
Temporária
Variáveis atribuídas com atribuições
do tipo blocking e, posteriormente,
lidas no mesmo procedimento são module tworeg (
temporárias – a ferramenta de síntese input wire d, clk,
output reg q
não infere armazenamento para elas. );
reg rega;

always @(posedge
clk)
begin
rega = d;
q <= rega;
end
endmodule

311
Atribuição de Variável
Temporária
A ferramenta de síntese sempre
infere armazenamento para module tworeg (
input wire d, clk,
variáveis atribuídas com output reg q
atribuições do tipo nonblocking. );
reg rega;

always @(posedge
clk)
begin
rega <= d;
q <= rega;
end
endmodule

312
Inferindo Latches
module latch (
• Uma atribuição incompleta em um input data,
procedimento combinacional enable,
output reg q
infere armazenamento por meio );
de latches.
always @(enable, data)
• É dessa forma que se codifica um if (enable)
design baseado em latch, caso q = data;

seja realmente necessário. endmodule


module latch (
• Na maioria dos casos, latches não input enable data, set,
clr,
são desejados – portanto, é output reg q
importante codificar corretamente );

o bloco combinacional. always @(enable, data, set,


• Latches podem ter set/reset clr)
if (set)
assíncronos. q = 1;
else if (clr)
q = 0;
else if (enable)
q = data;
endmodule
313
Inferência de Tristates

module tri_state_drivers (
input en_1, en_2,
input [7:0] data_1, data_2,
output [7:0] data_bus
);

assign data_bus = en_1 ? data_1 :


8'bz;
assign data_bus = en_2 ? data_2 :
8'bz;

endmodule

• O uso do tipo de rede wire assume que as linhas de habilitação


(enable) são mutuamente exclusivas.
• Caso contrário, use os tipos de rede triand ou trior (verifique o
suporte da ferramenta de síntese).

314
Hierarquia: Registre Todas as
Saídas

315
Gerenciamento de Hierarquia
Algumas pontos a serem considerados:
• Mesclagem de lógica combinacional;
• Estratégias de otimização;
• Tamanhos sintetizáveis;
• Controle de caminhos críticos.

316
Revisão
1. Qual é a principal diferença entre a simulação e a
síntese em Verilog?
2. Cite e explique dois dos principais objetivos da
síntese.
3. Dê dois exemplos de estruturas ou construções
em Verilog que não são suportadas pelas
ferramentas de síntese.
4. O que ocorre quando há atribuições incompletas
em um bloco combinacional?

317
Aula 22
Verilog - Codificação para
Síntese e Simulação (cont.)
Simulação
• O que é?
 Modela e verifica o comportamento lógico do design.
 Foco na funcionalidade, sem considerar detalhes físicos.
• Por que usar?
 Explora opções: Teste diferentes configurações antes da síntese.
 Economiza tempo: Identifica e corrige erros no início.
 Verifica a lógica: Garante a funcionalidade antes de custos
elevados.
• Exemplo​
ü Multiplicação no HDL é
tratada idealmente, sem
detalhes do hardware.​
• Objetivo:​
ü Garantir que a lógica está
correta e funcional antes
de etapas caras.

319
Simulação
A simulação requer um ambiente específico com ferramentas e técnicas
para testar e verificar o circuito.
• Usando recursos auxiliares: Esses recursos não fazem parte do circuito
final, mas ajudam a criar cenários de teste e depuração durante a
simulação. Por exemplo:
 Formas de onda Active-HDL;
 Leitura de arquivos;
 Instruções de impressão/logs;
• Usando código de simulação em Verilog: A simulação em Verilog utiliza
um testbench, também chamado de "test fixture".
 Um testbench fornece entradas ao circuito, monitora as saídas e
valida seu comportamento.
 Este código simula um ambiente funcional sem fazer parte do
circuito sintetizável.

320
Test Fixture (Testbench)
• Fornece clock: gera os sinais de clock necessários para o circuito
durante a simulação.
• Fornece vetores de teste/verifica resultados: vetores de teste e
resultados são pré-computados. Geralmente, os vetores de teste
são lidos a partir de arquivos.
• Modela o ambiente do sistema: programa complexo que simula o
ambiente externo para o circuito.
• O test fixture pode utilizar todos os recursos da linguagem: inclui
comandos como inicialização (initial), atrasos (delays), leitura/
escrita de arquivos, etc.

*DUT: Design

Under Test

321
O que é Simulação Lógica?
• Simular o comportamento de um design
lógico.
• Descrição do design lógico:
 Netlist, rede.
 Componentes.
 Ex.: AND, OR, RAM, PENTIUM
 Interconexões dos componentes.
• Modelos Lógicos:
 Comportamento dos componentes.
 Comportamento das interconexões.
 Valores dos sinais.
• Modelos Temporais:
 Comportamento dos componentes.
 Comportamento das interconexões.
 Atrasos dos sinais.

322
Descrição do Design Lógico
• Componentes:
 Módulos, células, etc.
 Primitivos (ex.: AND, OR, NOT).
 Predefinidos – a partir de bibliotecas:
 Comportamento funcional.
 Comportamento temporal.
 Compostos – definidos pelo usuário:
 Sub-rede.
 Hierarquia.
• Conexões de Componentes:
 Fiação.
 Pontos de conexão - pinos, portas,
terminais.
 Pode incluir estrutura de fiação:
 Fan-in, fan-out.
 Parasitismo.
323
Organização do Design
• Linhas tracejadas indicam que a compilação pode verificar
a existência e a legibilidade dos arquivos de entrada, assim
como a permissão para criar arquivos de saída.

324
Simulação de um Modelo
Verilog
initial
avec = 8'h00;
always @(posedge clk)
q <= d;
always @(a or b or
sel)
if sel
y = a;
...

325
Organização da Testbench
Testbench Simples
• Apenas envia dados para o
design.
• Poucos processos envolvidos.
• Não há interação com o
design.

Testbench Sofisticado
• Modela o ambiente ao redor
do design.
• Interage com o design.
• Evolui em direção a um
modelo de sistema completo.
• Possui verificação automática
(self-checking).

326
Estímulo “Em Linha”
module inline_tb;

reg [7:0] data_bus,


• Basta especificar as transições addr;
reg reset;
de valores das variáveis.
• É possível definir relações // Instância do DUT
initial begin
temporais complexas com reset = 1'b0;
data_bus = 8'h00;
facilidade. #5 reset = 1'b1;
• Esse tipo de testbench pode se #15 reset = 1'b0;
#10 data_bus =
tornar muito extenso para testes 8'h45;
complexos. #15 addr = 8'hf0;
#40 data_bus =
8'h0f;
end

endmodule

327
Estímulo a Partir de Loops
Em um loop, é possível
modificar repetidamente a module loop_tb;
mesma variável de estímulo.
As vantagens incluem: reg clk;
reg [7:0] stimulus;
• Facilidade de entrada. integer i;
• Descrição compacta.
// Instância do DUT
Esse método pode ser mais // Geração de clock
adequado para estímulos que
initial begin
possuem: for (i = 0; i <= 255; i = i +
• Um período de tempo 1)
@(negedge clk) stimulus =
definido. i;
• Valores regulares. end
Importante: endmodule
É importante inserir um
controle de tempo no loop!

328
Estímulo a Partir de Arrays
• É possível pré-carregar module array_tb;

valores de estímulo em um // Palavra de estímulo e array


array e, em seguida, aplicar reg [7:0] data_bus, stim_array
[0:15]
esses valores em um loop. integer i;
• Descrição compacta // Instância do DUT
• Esse método pode ser mais // Define o clock
adequado para estímulos que initial begin
possuem: // Carrega array com os valores
stim_array[0] = 8'h2f;
• Um período de tempo stim_array[1] = 8'h7a;
definido; ...
stim_array[15] = 8'h0b;
• Valores irregulares.
// Aplica estímulo do array
• Alternativamente, é possível for (i = 0; i <= 15; i = i + 1)
carregar o array de estímulos @(negedge clk)
data_bus = stim_array[i];
a partir de um arquivo. end

endmodule

329
Estímulo a partir de Arquivos
module file_array_tb;

// Palavra de estímulo e array


• Este exemplo é reg [7:0] data_bus, stim_array [0:15]
equivalente ao anterior, integer i;

mas pré-carrega o // Instância do DUT


array de memória a // Define o clock

partir de um arquivo. initial begin


// Carrega array com os valores
$readmemb("stimulus.txt",
stim_array);

// Aplica estímulo do array


for (i = 0; i <= 15; i = i + 1)
@(negedge clk)
data_bus = stim_array[i];
end

endmodule

330
Estímulo Aleatório usando
$random
Números aleatórios podem ser gerados utilizando a função de
sistema $random.
Retorna um inteiro com sinal de 32 bits aleatório
• Verilog-1995: O algoritmo não é padrão nem portátil.
• Verilog-2001: O algoritmo é padrão e portátil.
É possível inicializar o gerador (seed) para produzir sequências
reproduzíveis. module random_tb;
O Verilog fornece funções de sistema que reg [3:0] avec;
permitem alterar a distribuição dos números reg [7:0] bvec;
aleatórios. ...
• $dist_chi_square​ initial
• $dist_erlang​ begin
• $dist_exponential​ avec =
• $dist_normal​ $random;
• $dist_Poisson​ bvec =
$random;
• $dist_t​ ...
• $dist_uniform end

endmodule 331
As Palavras-Chave fork e join
• As instruções incluídas dentro module forkfoin_tb;
reg [7:0] data,
de fork...join são addr;
executadas simultaneamente.
// Instância do DUT
• Cada instrução segue o initial
fork
controle de evento ou atrasos data = 8'h00;
que ela contém. #10 data =
8'h45;
• O bloco fork...join é #15 addr =
concluído quando todas as 8'hf0;
#30 data =
instruções iniciadas com fork 8'h0f;
join
são finalizadas.
Síntese endmodule
• O padrão de síntese não
suporta a construção
fork...join.

332
Bloco de Estímulo
Concorrente
Um bloco concorrente pode conter
qualquer instrução processual
(chamadas de tarefas, loops, etc).
Algumas questões importantes a module concurrent_tb;
reg [7:0] data;
serem consideradas:
• Não é possível prever a ordem // Instância do DUT

de execução das instruções initial


agendadas para o mesmo fork
#10 data = 8'h45;
tempo de simulação. Isso pode #20 repeat (7)
resultar em condições de #10 data = data +
1
corrida. #25 repeat (5)
• Se alguma instrução (por #20 data = data <<
1;
exemplo, um loop forever) #99 data = 8'h0f;
não for concluída, o bloco nunca join
endmodule
será concluído (join).

333
A palavra-chave event
• Declare um evento module event_example (
nomeado em Verilog usando input [3:0] in1, in2,
output [4:0] o1
a palavra-chave event. );
• Notifique o evento usando o
event e1; // Declara
operador de disparo evento
-> event.
always @(in1 or in2)
• Utilize o evento em um begin
o1 = in1 + in2;
controle de evento @ -> e1; // Notifica
event. evento
end
Síntese:
• O padrão de síntese não always @(e1) // Usa
evento
oferece suporte ao comando $displayb(o1);
event. endmodule

334
Usando Strings para Monitorar o
Progresso module testbench;
Exibir strings informativas pode reg [40*8:1] message;
ajudar nos esforços de depuração ao task reset;
begin
monitorar o progresso da simulação. message = "reset";
@(negedge clock);
• Defina um vetor com 8 bits para reset <= 1'b1;
cada caractere ASCII. @(negedge clock);
reset <= 1'b0;
• Atribua um literal de string ao end
endtask
vetor (preenchido ou truncado task test1;
input [3:0] a_vec,
como qualquer outro número). b_vec;
• Defina um processo acionado por output [7:0] d_vec;
begin
alterações na mensagem para message = "test one";
...
exibir a nova mensagem. end
• Visualize as mensagens com a endtask
always @(message)
ferramenta de exibição de formas $display ("%s",
message);
de onda (defina a base de exibição initial begin
para ASCII). reset;
test1(a, b, out);
end
endmodule
335
Variáveis Hierárquicas
•É possível acessar module mux (
variáveis fora do módulo input a, b, sel, clk,
output reg f
utilizando um caminho );
wire g = sel ? a : b;
hierárquico. always @(posedge clk)
• Isso é útil em f <= g;
endmodule
testbenches.
• Os caminhos podem ser module tb;
...
relativos ou absolutos. mux uut (.a, (1'b0), .b(bnet),
.sel(select), .clk(clk), .f(f));
• Este exemplo utiliza um initial
caminho relativo. begin
wait (uut.g);
• O caminho absoluto $display("mux has a logic
equivalente poderia one");
end
ser: ...
endmodule
wait (tb.uut.g);

336
Captura de Vetor
• É possível capturar os module capture_tb;
estímulos e as reg [7:0] stimulus, response;
integer stimfile, respfile;
respostas nos pinos
do DUT. // Instância do DUT
• Esses vetores podem initial
ser reproduzidos no begin
stimfile = $fopen("stimulos.txt");
DUT utilizando respfile = $fopen("results.txt");
apenas um ambiente fork
if (stimfile != 0)
de teste simplificado. forever #(period)
$fstrobeh (stimfile, "%b",
• Além disso, é possível stimulus);
fornecer esses if (respfile != 0)
#(period/2) forever #(period)
vetores de teste ao $fstrobeh (respfile, "%b",
fabricante do response);
join
dispositivo. end
endmodule

337
Reprodução de Vetores
• É possível reproduzir
vetores lidos de um
arquivo. module playback_tb;
localparam integer num_vecs = 256;
reg [7:0] data_bus;
reg [7:0] stim [0:num_vecs-1];
integer i;

// Instância do DUT
00111000
00111001 initial
begin
00111010
// Carrega estímulos
00111100
$readmemb("vec.txt", stim);
00110000 // Replay os vetores
10111000 for (i = 0; i < num_vecs; i =
... i + 1)
vec.txt #50 data_bus = stim[i];
end
endmoule

338
Gerador de Clock
• Exemplos de gerador de clock
always begin // Simples
#(period/2) clk = 0; nand #(period/2) u1 (ck, ck,
#(period/2) clk = 1; go);
end initial begin
go = 0;
initial begin // Com atraso #(period/2) go = 1;
clk = 0; end
#(period)
forever nand #(period/2) u1 (ck, ck,
#(period/2) clk = go);
~clk; initial begin
end go = 0;
#(period) go = 1;
initial begin // Irregular end
#(period + 1) clk = 1;
#(period/2 - 1) nand #(period/4, 3*period/4)
forever begin u1 (ck, ck, go);
#(period/4) clk = 0; initial begin
#(3 * period/4) clk = go = 0;
1; #(period) go = 1;
end end
end
339
Uso de Tasks
module bus_ctrl_tb;
• Usar tasks em um testbench reg [7:0] data;
encapsula operações reg data_valid;
wire data_read;
repetidas, tornando seu
task cpu_driver;
código mais eficiente. input [7:0] data_in;
begin
#30 data_valid = 1;
wait (data_read ==
1);
#20 data = data_in;
wait (data_read ==
0);
#20 data = 8'hzz;
#30 data_valid = 0;
end
endtask
// Instânciação da CPU
initial
begin
cpu_driver
(8'b0000_0000);
cpu_driver
(8'b1010_1010);
cpu_driver
340
(8'b0101_0101);
Revisão
1. O que é uma simulação em Verilog e qual é o seu
principal objetivo?
2. Quais recursos de Verilog podem ser usados em um
testbench e não são sintetizáveis?
3. Qual é a diferença entre estímulos “em linha” e estímulos
gerados por “arrays”?
4. Quais as vantagens de usar loops para gerar estímulos
durante a simulação?
5. Explique o uso das palavras-chave “fork” e “join” em
uma testbench.

341
Aula 23
Verilog - Codificação para
Síntese e Simulação (cont.)
Relatório Prático
• Nesta aula, iremos aplicar os conceitos estudados
sobre Verilog – Codificação para Síntese e Simulação em
exercícios práticos, presentes no arquivo Relatórios Práticos
– SD112 atividade A-015.
• O aluno deverá fazer todos os exercícios e enviar os arquivos
da resolução assinados com seu nome completo para o e-
mail [email protected];
• Assunto do e-mail: Relatório SD112 – Atividade A-015.

343

Você também pode gostar