Implementação de Multiplicador de Inteiros com Sinal em Verilog para FPGA

A representação de números inteiros com sinal em sistemas digitais utiliza o esquema de complemento de dois. Para uma palavra de N bits, o intervalo abrange de \(-2^{N-1}\) a \(2^{N-1}-1\). Este artigo detalha o projeto de um circuito multiplicador para operandos com sinal, empregando a linguagem de descrição de hardware Verilog.

Considerando dois números com sinal de N bits, A e B, podemos expressá-los algebricamente. Por exemplo, para N=4, A pode ser escrito como \(-a_3 \times 2^3 + A_3\), onde A_3 corresponde ao valor sem sinal dos bits menos significativos. A multiplicação A*B é então desenvolvida por expansão e simplificação, resultando em uma combinação de operações lógicas e deslocamentos.

O código Verilog a seguir apresenta uma implementação parametrizável do multiplicador. As variáveis, sinais e estrutura lógica foram modiifcados em relação a exemplos convencionais para proporcionar uma visão alternativa mantendo a funcionalidade.

`timescale 1ns/1ps

module mult_sinal
#(
    parameter LARGURA_DADOS = 8
)
(
    input  [LARGURA_DADOS-1:0] operando_a,
    input  [LARGURA_DADOS-1:0] operando_b,
    output [2*LARGURA_DADOS-1:0] produto
);

wire [LARGURA_DADOS-1:0] matriz_parciais [LARGURA_DADOS-1:0];

generate
    genvar idx_i, idx_j;
    
    for (idx_i = 0; idx_i < LARGURA_DADOS-1; idx_i = idx_i + 1) begin : linha_parcial
        for (idx_j = 0; idx_j < LARGURA_DADOS-1; idx_j = idx_j + 1) begin : coluna_parcial
            assign matriz_parciais[idx_i][idx_j] = operando_a[idx_i] & operando_b[idx_j];
        end
    end

    for (idx_i = 0; idx_i < LARGURA_DADOS-1; idx_i = idx_i + 1) begin
        assign matriz_parciais[idx_i][LARGURA_DADOS-1] = ~(operando_a[LARGURA_DADOS-1] & operando_b[idx_i]);
        assign matriz_parciais[LARGURA_DADOS-1][idx_i] = ~(operando_a[idx_i] & operando_b[LARGURA_DADOS-1]);
    end
    
    assign matriz_parciais[LARGURA_DADOS-1][LARGURA_DADOS-1] = operando_a[LARGURA_DADOS-1] & operando_b[LARGURA_DADOS-1];
endgenerate

wire [2*LARGURA_DADOS-1:0] acumulador_somas [LARGURA_DADOS-1:0];

generate
    genvar idx_k;
    
    assign acumulador_somas[0] = {1'b1, matriz_parciais[0][LARGURA_DADOS-1], matriz_parciais[0][LARGURA_DADOS-2:0]};
    
    for (idx_k = 1; idx_k < LARGURA_DADOS-1; idx_k = idx_k + 1) begin
        assign acumulador_somas[idx_k] = {matriz_parciais[idx_k][LARGURA_DADOS-1], matriz_parciais[idx_k][LARGURA_DADOS-2:0]} << idx_k;
    end
    
    assign acumulador_somas[LARGURA_DADOS-1] = {1'b1, matriz_parciais[LARGURA_DADOS-1][LARGURA_DADOS-1], matriz_parciais[LARGURA_DADOS-1][LARGURA_DADOS-2:0]} << (LARGURA_DADOS-1);
endgenerate

assign produto = acumulador_somas[0] + acumulador_somas[1] + acumulador_somas[2] + acumulador_somas[3] + acumulador_somas[4] + acumulador_somas[5] + acumulador_somas[6] + acumulador_somas[7];

endmodule

Um banco de testes em Verilog é fornecido para validação funcional. A estrutura e nomenclatura foram adaptadas para demonstrar uma metodologia de verificação distinta.

`timescale 1ns/1ps

module banco_testes_mult;

localparam LARGURA = 8;

reg [LARGURA-1:0] estimulo_x, estimulo_y;
wire [2*LARGURA-1:0] resposta;

mult_sinal #(.LARGURA_DADOS(LARGURA)) inst_dut (
    .operando_a(estimulo_x),
    .operando_b(estimulo_y),
    .produto(resposta)
);

initial begin
    estimulo_x = 8'hFF;
    estimulo_y = 8'hFF;
    #40;
    estimulo_x = 8'h01;
    estimulo_y = 8'hFF;
    #40;

    integer contador_i, contador_j;
    for (contador_i = 0; contador_i < 256; contador_i = contador_i + 1) begin
        for (contador_j = 0; contador_j < 256; contador_j = contador_j + 1) begin
            estimulo_x = contador_i;
            estimulo_y = contador_j;
            #20;
        end
    end

    #100;
    $stop;
end

endmodule

Os resultados das simulações confirmam que o multiplicador gera saídas corretas para múltiplos cenários de entrada, incluindo valores positivos, negativos e combinações limítrofes.

Tags: Verilog FPGA Multiplicador de Sinal Projeto Digital HDL

Publicado em 6-2 21:37 por Thomas