Tutorial de Verilog: Somador com Propagação do Carry – Somador Ripple-Carry

Somador Ripple-Carry
Este post faz parte da série Tutorial de Verilog

Vamos ver a partir deste post como funcionam os somadores. Um somador de N-bits consiste em um circuito que consegue somar duas entradas, cada uma delas com N-bits, e mais um sinal Carry de entrada e produz um resultado também com o mesmo tamanho, N-bits e um sinal Carry de Saída. Esse circuito somador é conhecido na literatura como Somador com Propagação do Carry, porque o sinal de Carry se propaga por todo o circuito do primeiro ao último bloco de hardware.

O símbolo de um somador pode ser representado como na figura abaixo.

Somador Ripple-Carry
Figura 1: Somador com Propagação do Carry

Existem três implementações comuns de Somador com Propagação do Carry. São elas:

  • Somador Ripple-Carry (Ripple-Carry Adder);
  • Somador Carry Adder (Carry Lookahead Adder);
  • Somador Prefixado (Prefix Adder).

Vamos abordar todos os somadores aqui no Embarcados. Neste post em específico estudaremos como funciona o Somador Ripple-Carry (Ripple-Carry Adder).

Somador Ripple-Carry

A forma mais simples, comum e intuitiva de criar um Somador é conectar vários somadores de 1-bit um após o outro, conectando o Carry de saída do anterior no Carry de entrada do atual e conectar o Carry de saída do atual no próximo bloco, totalizando uma cadeia de N blocos para um somador de N bits. Este então é o circuito do Ripple-Carry Adder. Ele é o somador mais modular que existe, já que podemos utilizar cada um dos somadores de 1-bit como módulos e escalarmos esse somador infinitamente. O problema dessa abordagem é que esse circuito é muito lento se compararmos com os demais somadores, conforme veremos quando forem apresentados os demais somadores. Abaixo está representado um somador de 4-bits. 

Representação do Circuito Somador Ripple-Carry de 4-bits em termos de Somadores Completos de 1-bit

Represento nas imagens abaixo o mesmo circuito de Somador Ripple-Carry de 4-bits. Essa representação utiliza quatro blocos Somadores Completos de 1-bit. Os dois desenhos significam a mesma coisa, mas desenhei das duas maneiras porque pode-se encontrar as duas formas de representação.

Somador Ripple-Carry
Figura 2: Representação do Circuito Somador Ripple-Carry de 4-bits em termos de Somadores Completos de 1-bit
Somador Ripple-Carry: Representação do Circuito Somador Ripple-Carry de 4-bits em termos de Somadores Completos de 1-bit
Figura 3: Representação do Circuito Somador Ripple-Carry de 4-bits em termos de Somadores Completos de 1-bit

Representação do Circuito Somador Ripple-Carry de 4-bits em Verilog

Para representar o circuito acima, escolhi a abordagem estrutural, onde codifico como se estivesse montando o esquemático do circuito. Criei um projeto em branco no Quartus (para ver como criar um projeto, veja este link) e utilizei o arquivo do meio somador e do somador completo de 1-bit mostrado no post anterior.

Arquivo meio_somador.v

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um meio somador
// Thiago Lima - 19/11/2015
module meio_somador (S, C, A, B);

output S, C;
input  A, B;

assign S = A ^ B;
assign C = A & B;

endmodule

Arquivo SOMADOR.v

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um somador completo de 1bit
// Thiago Lima - 19/11/2015

module SOMADOR (Soma, Cout, A, B, Cin);

output Soma, Cout;
input  A, B, Cin;
wire Carry_1, Carry_2, Soma_1; 

meio_somador U1 (Soma_1, Carry_1, A, B);
meio_somador U2 (Soma, Carry_2, Cin, Soma_1);
or           U3 (Cout, Carry_1, Carry_2);

endmodule

Então criei a estrutura do código em Verilog para o Somador Ripple-Carry. Como estou considerando um somador de 4-bits, considerei os sinais A, B e Soma como [3:0]. No primeiro bloco, eu apliquei o Carry de entrada Cin e assim por diante. Nos outros blocos somadores de 1-bit coloquei os sinais um a um até o quarto bloco.

Arquivo ripple_carry_adder.v

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um somador Ripple Carry de 4 bits
// Thiago Lima - 19/11/2015

module ripple_carry_adder (Soma, Cout, A, B, Cin);

output [3:0]Soma;
output Cout;
input  [3:0]A;
input  [3:0]B;
input  Cin;
wire C0, C1, C2;

SOMADOR U0 (Soma[0], C0,   A[0], B[0], Cin);
SOMADOR U1 (Soma[1], C1,   A[1], B[1], C0);
SOMADOR U2 (Soma[2], C2,   A[2], B[2], C1);
SOMADOR U3 (Soma[3], Cout, A[3], B[3], C2);
	 
endmodule

Testbench para o Circuito Somador Ripple-Carry de 4-bits em Verilog

Para injetar valore e 0 a 15 em A e de zero a 15 em B, criei dois contadores, i e j. Os valores de i, injetei em A, os valores de j, injetei em B. Fiz dois testes que mostrariam uma mensagem de erro quando executasse o Testbench, uma testando o Carry e outra testando a soma. O testbench está abaixo.

Arquivo ripple_carry_adder_tb.v

//Testbench Somador Ripple Carry 4 bits
//by Thiago Lima

module ripple_carry_adder_tb;

wire [3:0] Soma_tb;
wire cout_tb;
reg [3:0] A_tb;
reg [3:0] B_tb;
reg Cin_tb;

integer i;
integer j;

ripple_carry_adder dut( Soma_tb, cout_tb, A_tb, B_tb, Cin_tb);

initial
begin

	Cin_tb = 1'b0;
	for (i = 0; i < 16; i = i + 1) 
	begin
		A_tb = i; #1;
		for (j = 0; j < 16; j = j + 1) 
		begin
				B_tb = j; #1;
				if ( Soma_tb !== (A_tb + B_tb) )
					$display("Erro> %d+%d=%d, carry = %b", A_tb, B_tb, Soma_tb, cout_tb);
				//else
				//	$display("%d %d", A_tb+B_tb, Soma_tb);	
				if ((A_tb + B_tb > 16 ) && (cout_tb === 0))	
					$display("Erro> Carry incorreto!!!");
		end
	end
end
endmodule

Forma de Onda resultante do teste

A forma de onda resultante foi de acordo com o esperado. O resultado no terminal também não apresentou nenhuma mensagem de erro. 

Caso queira reproduzir o teste feito acima, faça Download do Projeto para o Quartus da Altera e aperte o play:

download_proteus_arduino_lcd

 

Representação do Circuito Somador Ripple-Carry de 32-bits em termos de Somadores Completos de 1-bit

Reproduzi o exemplo anterior para um somador de 32-bits na topologia Ripple-Carry. Ele funciona da mesma forma. Repare na figura abaixo para entender como funciona a expansão desse circuito. 

 

Representação do Circuito Somador Ripple-Carry de 32-bits em Verilog

Arquivo meio_somador.v (igual ao exemplo anterior)

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um meio somador
// Thiago Lima - 19/11/2015
module meio_somador (S, C, A, B);

output S, C;
input  A, B;

assign S = A ^ B;
assign C = A & B;

endmodule

Arquivo SOMADOR.v (igual ao exemplo anterior)

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um somador completo de 1bit
// Thiago Lima - 19/11/2015

module SOMADOR (Soma, Cout, A, B, Cin);

output Soma, Cout;
input  A, B, Cin;
wire Carry_1, Carry_2, Soma_1; 

meio_somador U1 (Soma_1, Carry_1, A, B);
meio_somador U2 (Soma, Carry_2, Cin, Soma_1);
or           U3 (Cout, Carry_1, Carry_2);

endmodule

Foi codificado da mesma maneira que para 4-bits, mas dessa vez para um somador de 32 bits. Veja abaixo.

Arquivo ripple_carry_adder.v

// Embarcados - Use como quiser e de os creditos
// Exemplo de Implementacao de um somador Ripple Carry de 32 bits
// Thiago Lima - 19/11/2015

module ripple_carry_adder (Soma, Cout, A, B, Cin);

output [31:0]Soma;
output Cout;
input  [31:0]A;
input  [31:0]B;
input  Cin;
wire C0, C1, C2, C3, C4, C5, C6, C7, C8, C9;
wire C10, C11, C12, C13, C14, C15, C16, C17, C18, C19;
wire C20, C21, C22, C23, C24, C25, C26, C27, C28, C29;
wire C30;

SOMADOR U0 (Soma[0],  C0,   A[0],  B[0],  Cin);
SOMADOR U1 (Soma[1],  C1,   A[1],  B[1],  C0);
SOMADOR U2 (Soma[2],  C2,   A[2],  B[2],  C1);
SOMADOR U3 (Soma[3],  C3,   A[3],  B[3],  C2);
SOMADOR U4 (Soma[4],  C4,   A[4],  B[4],  C3);
SOMADOR U5 (Soma[5],  C5,   A[5],  B[5],  C4);
SOMADOR U6 (Soma[6],  C6,   A[6],  B[6],  C5);
SOMADOR U7 (Soma[7],  C7,   A[7],  B[7],  C6);
SOMADOR U8 (Soma[8],  C8,   A[8],  B[8],  C7);
SOMADOR U9 (Soma[9],  C9,   A[9],  B[9],  C8);
SOMADOR U10(Soma[10], C10,  A[10], B[10], C9);
SOMADOR U11(Soma[11], C11,  A[11], B[11], C10);
SOMADOR U12(Soma[12], C12,  A[12], B[12], C11);
SOMADOR U13(Soma[13], C13,  A[13], B[13], C12);
SOMADOR U14(Soma[14], C14,  A[14], B[14], C13);
SOMADOR U15(Soma[15], C15,  A[15], B[15], C14);
SOMADOR U16(Soma[16], C16,  A[16], B[16], C15);
SOMADOR U17(Soma[17], C17,  A[17], B[17], C16);
SOMADOR U18(Soma[18], C18,  A[18], B[18], C17);
SOMADOR U19(Soma[19], C19,  A[19], B[19], C18);
SOMADOR U20(Soma[20], C20,  A[20], B[20], C19);
SOMADOR U21(Soma[21], C21,  A[21], B[21], C20);
SOMADOR U22(Soma[22], C22,  A[22], B[22], C21);
SOMADOR U23(Soma[23], C23,  A[23], B[23], C22);
SOMADOR U24(Soma[24], C24,  A[24], B[24], C23);
SOMADOR U25(Soma[25], C25,  A[25], B[25], C24);
SOMADOR U26(Soma[26], C26,  A[26], B[26], C25);
SOMADOR U27(Soma[27], C27,  A[27], B[27], C26);
SOMADOR U28(Soma[28], C28,  A[28], B[28], C27);
SOMADOR U29(Soma[29], C29,  A[29], B[29], C28);
SOMADOR U30(Soma[30], C30,  A[30], B[30], C29);
SOMADOR U31(Soma[31], COut, A[31], B[31], C30);
	 
endmodule

Testbench para o Circuito Somador Ripple-Carry de 32-bits em Verilog

Testei o código Verilog do Somador 32-bits utilizando o testbench altero do exemplo anterior e mostrado abaixo.

Arquivo ripple_carry_adder_tb.v

//Testbench Somador Ripple Carry 32 bits
//by Thiago Lima

module ripple_carry_adder_tb;

wire [31:0] Soma_tb;
wire cout_tb;
reg [31:0] A_tb;
reg [31:0] B_tb;	
reg Cin_tb;

integer i;
integer j;

ripple_carry_adder dut( Soma_tb, cout_tb, A_tb, B_tb, Cin_tb);

initial
begin

	Cin_tb = 1'b0;
	for (i = 0; i < 32'hFFFFFFFF; i = i + 1) 
	begin
		A_tb = i; #1;
		for (j = 0; j < 32'hFFFFFFFF; j = j + 1) 
		begin
				B_tb = j; #1;
				if ( Soma_tb !== (A_tb + B_tb) )
					$display("Erro> %d+%d=%d, carry = %b", A_tb, B_tb, Soma_tb, cout_tb);
				//else
				//	$display("%d %d", A_tb+B_tb, Soma_tb);	
				if ((A_tb + B_tb > 16 ) && (cout_tb === 0))	
					$display("Erro> Carry incorreto!!!");
		end
	end
end
endmodule

Resultado do teste

Testei o circuito apenas parcialmente. Não rodei todo o teste por ele ser muito grande e ir além do escopo deste texto. Deixo no entanto disponível o projeto completo do Quartus. Caso queira reproduzir o teste completo ou mesmo só estudar o código, faça Download do Projeto para o Quartus da Altera e aperte o play:

download_proteus_arduino_lcd

É isso ai pessoal, espero que tenham gostado. Deixem seus comentários. É importante para guiar meus próximos passos.

Tutorial de Verilog

Tutorial de Verilog: Conversor de Código Gray para Código Binário Tutorial de Verilog: Conversor BCD para 7 Segmentos
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.
Comentários:
Notificações
Notificar
0 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
Home » Hardware » Sistemas Digitais » Tutorial de Verilog: Somador com Propagação do Carry – Somador Ripple-Carry

EM DESTAQUE

WEBINARS

VEJA TAMBÉM

JUNTE-SE HOJE À COMUNIDADE EMBARCADOS

Talvez você goste: