Guia de Projeto e Implementação de Somador Completo em Verilog
Um somador é um componente digital que realiza a adição de dois números. É o componente principal dentro de uma ULA de um processador e é usado para incrementar endereços, índices de tabelas, ponteiros de buffer e em muitos outros lugares onde a adição é necessária.
Um somador completo adiciona uma entrada de carry junto com outros números binários de entrada para produzir uma soma e uma saída de carry.
Tabela Verdade
| A | B | Cin | Cout | Sum |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 | 1 |
| 0 | 1 | 0 | 0 | 1 |
| 0 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 0 | 1 |
| 1 | 0 | 1 | 1 | 0 |
| 1 | 1 | 0 | 1 | 0 |
| 1 | 1 | 1 | 1 | 1 |
Projeto
Um exemplo de um somador de 4 bits é mostrado abaixo que aceita dois números binários através dos sinais a e b que são ambos de 4 bits de largura. Como um somador é um circuito combinacional, ele pode ser modelado em Verilog usando uma atribuição contínua com assign ou um bloco always com uma lista de sensibilidade que compreende todas as entradas. O código mostrado abaixo é da primeira abordagem.
module fulladd (
input [3:0] a,
input [3:0] b,
input c_in,
output c_out,
output [3:0] sum
);
assign {c_out, sum} = a + b + c_in;
endmodule
O código mostrado abaixo usa um bloco always que é executado sempre que qualquer uma de suas entradas muda de valor.
module fulladd (
input [3:0] a,
input [3:0] b,
input c_in,
output reg c_out,
output reg [3:0] sum
);
always @ (a or b or c_in) begin
{c_out, sum} = a + b + c_in;
end
endmodule
Esquemático de Hardware
Testbench
module tb_fulladd;
// 1. Declara variáveis do testbench
reg [3:0] a;
reg [3:0] b;
reg c_in;
wire [3:0] sum;
integer i;
// 2. Instancia o projeto e conecta às variáveis do testbench
fulladd fa0 (
.a(a),
.b(b),
.c_in(c_in),
.c_out(c_out),
.sum(sum)
);
// 3. Fornece estímulo para testar o projeto
initial begin
a <= 0;
b <= 0;
c_in <= 0;
$monitor("a=0x%0h b=0x%0h c_in=0x%0h c_out=0x%0h sum=0x%0h", a, b, c_in, c_out, sum);
// Usa um loop for para aplicar valores aleatórios às entradas
for (i = 0; i < 5; i = i + 1) begin
#10 a <= $random;
b <= $random;
c_in <= $random;
end
end
endmodule
Note que quando a e b somam para dar um número mais largo que 4 bits, a soma faz rollover para zero e c_out se torna 1. Por exemplo, a linha destacada em amarelo soma para dar 0x11 e os 4 bits inferiores são atribuídos a sum e o bit #4 a c_out.
Log de Simulação
ncsim> run a=0x0 b=0x0 c_in=0x0 c_out=0x0 sum=0x0 a=0x4 b=0x1 c_in=0x1 c_out=0x0 sum=0x6 a=0x3 b=0xd c_in=0x1 c_out=0x1 sum=0x1 a=0x5 b=0x2 c_in=0x1 c_out=0x0 sum=0x8 a=0xd b=0x6 c_in=0x1 c_out=0x1 sum=0x4 a=0xd b=0xc c_in=0x1 c_out=0x1 sum=0xa ncsim: *W,RNQUIE: Simulação completa.
Verilog
- Domine o Verilog: Tutorial Completo para Projeto de Circuitos Digitais
- Dominando Concatenação Verilog: Guia Prático
- Entendendo Atribuições em Verilog: Tipos, Sintaxe e Boas Práticas
- Verilog Blocking vs Non-Blocking: Diferenças Essenciais Explicadas
- Dominando Funções em Verilog para Design RTL Eficiente
- Entendendo Tasks em Verilog: Funções vs Tasks, Sintaxe e Uso
- Gerador de Clock Verilog: Guia de Design e Implementação
- Dominando Funções Matemáticas do Verilog para Design de Hardware Eficiente
- Dominando $timeformat do Verilog: Precisão e Controle de Exibição
- Entendendo e Imprimindo Timescales do Verilog em Qualquer Escopo