Multiplexador 4-para-1 em Verilog: Projeto e Implementação
O que é um mux ou multiplexador?
Um multiplexador ou mux em resumo, é um elemento digital que transfere dados de uma das N entradas para a saída baseada no sinal de seleção. O caso mostrado abaixo é quando N é igual a 4. Por exemplo, um multiplexador de 4 bits teria N entradas cada uma de 4 bits onde cada entrada pode ser transferida para a saída pelo uso de um sinal de seleção.
sel é uma entrada de 2 bits e pode ter quatro valores. Cada valor na linha de seleção permitirá que uma das entradas seja enviada ao pino de saída out.
sel a b c d out 0 3 7 1 9 3 1 3 7 1 9 7 2 3 7 1 9 1 3 3 7 1 9 9
Um multiplexador 4x1 pode ser implementado de múltiplas formas e aqui você verá duas das formas mais comuns:
- Usando uma instrução
assign - Usando uma instrução
case
Usando instrução assign
module mux_4to1_assign (
input [3:0] a, // Entrada de 4 bits chamada a
input [3:0] b, // Entrada de 4 bits chamada b
input [3:0] c, // Entrada de 4 bits chamada c
input [3:0] d, // Entrada de 4 bits chamada d
input [1:0] sel, // entrada sel usada para selecionar entre a,b,c,d
output [3:0] out // Saída de 4 bits baseada na entrada sel
);
// Quando sel[1] é 0, (sel[0]? b:a) é selecionado e quando sel[1] é 1, (sel[0] ? d:c) é tomado
// Quando sel[0] é 0, a é enviada à saída, senão b e quando sel[0] é 0, c é enviada à saída, senão d
assign out = sel[1] ? (sel[0] ? d : c) : (sel[0] ? b : a);
endmodule
O módulo chamado mux_4x1_assign tem quatro entradas de dados de 4 bits, uma entrada de seleção de 2 bits e uma saída de dados de 4 bits. O multiplexador selecionará a, b, c ou d baseada no sinal de seleção sel usando a instrução assign.
Usando instrução case
Note que o sinal out é declarado como tipo reg porque é usado em um bloco procedural como always.
module mux_4to1_case (
input [3:0] a, // Entrada de 4 bits chamada a
input [3:0] b, // Entrada de 4 bits chamada b
input [3:0] c, // Entrada de 4 bits chamada c
input [3:0] d, // Entrada de 4 bits chamada d
input [1:0] sel, // entrada sel usada para selecionar entre a,b,c,d
output reg [3:0] out // Saída de 4 bits baseada na entrada sel
);
// Este bloco always é executado sempre que a/b/c/d/sel muda de valor
// Quando isso acontece, baseado no valor em sel, a saída é atribuída a a/b/c/d
always @ (a or b or c or d or sel) begin
case (sel)
2'b00: out <= a;
2'b01: out <= b;
2'b10: out <= c;
2'b11: out <= d;
endcase
end
endmodule
O módulo chamado mux_4x1_case tem quatro entradas de dados de 4 bits, uma entrada de seleção de 2 bits e uma saída de dados de 4 bits. O multiplexador selecionará a, b, c ou d baseada no sinal de seleção sel usando a instrução case.
Esquemático de Hardware
Ambos os tipos de modelos de multiplexador são sintetizados no mesmo hardware como mostrado na imagem abaixo.
Testbench
module tb_4to1_mux;
// Declara variáveis reg internas para conduzir entradas do projeto
// Declara sinais wire para coletar saída do projeto
// Declara outras variáveis internas usadas no testbench
reg [3:0] a;
reg [3:0] b;
reg [3:0] c;
reg [3:0] d;
wire [3:0] out;
reg [1:0] sel;
integer i;
// Instancia um dos projetos, neste caso, usamos o projeto com instrução case
// Conecta variáveis do testbench declaradas acima com as do projeto
mux_4to1_case mux0 (
.a(a),
.b(b),
.c(c),
.d(d),
.sel(sel),
.out(out)
);
// Este bloco initial é o estímulo
initial begin
// Inicia um monitor em background para exibir valores no log sempre que a/b/c/d/sel/out muda
$monitor("[%0t] sel=0x%0h a=0x%0h b=0x%0h c=0x%0h d=0x%0h out=0x%0h", $time, sel, a, b, c, d, out);
// 1. No tempo 0, conduz valores aleatórios a a/b/c/d e mantém sel = 0
sel <= 0;
a <= $random;
b <= $random;
c <= $random;
d <= $random;
// 2. Muda o valor de sel a cada 5ns
for (i = 1; i < 4; i = i + 1) begin
#5 sel <= i;
end
// 3. Após o Passo 2 terminar, espera 5ns e finaliza simulação
#5 $finish;
end
endmodule
Log de Simulação
ncsim> run [0] sel=0x0 a=0x4 b=0x1 c=0x9 d=0x3 out=0x4 [5] sel=0x1 a=0x4 b=0x1 c=0x9 d=0x3 out=0x1 [10] sel=0x2 a=0x4 b=0x1 c=0x9 d=0x3 out=0x9 [15] sel=0x3 a=0x4 b=0x1 c=0x9 d=0x3 out=0x3 Simulação completa via $finish(1) no tempo 20 NS + 0
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