Como projetar multiplexadores em Verilog

Atualizado: 8 de nov.

Você e seu amigo estão almoçando em um restaurante e decidem marcar todos os gastos em apenas uma comanda. Na hora de pagar a conta no caixa, o atendente multiplica o número de refeições por dois, soma o valor de todas as bebidas e apresenta o valor final a vocês. Você percebe que o atendente somou uma bebida a mais, e pede para subtraí-la da conta. Ao final, com o valor corrigido, você e seu amigo pedem para dividir o valor total por dois, pois vocês vão rachar a conta.


Essa cena, comum em nossas vidas, teve como coadjuvante uma calculadora de 4 operações básicas. Nesta calculadora, há um circuito elementar chamado de multiplexador. É através dele que as operações básicas da calculadora são selecionadas.


Neste tutorial, você vai aprender a:

  • projetar um circuito multiplexador de 2 entradas (MUX2) usando portas lógicas

  • implementar o projeto do MUX2 em Verilog

  • mapear, compilar e prototipar um MUX2 na placa Community

  • criar um multiplexador de 4 entradas (MUX4) a partir de três MUX2

  • ler e compreender o relatório resumido do projeto

  • interagir com um projeto na placa Community


Antes de prosseguir, recomendamos os seguintes tutoriais:


O que é um multiplexador?

Um multiplexador é um circuito digital combinacional que transmite o bit de uma de suas entradas para a sua única saída. A seleção de uma entrada particular é realizada por um sinal de controle.



No lado esquerdo da animação acima, temos a representação de um multiplexador de 2 entradas de 1 bit em forma de chaves. Este multiplexador (ou MUX2) propaga os valores de entrada para a saída, intercalando (ou multiplexando) as entradas de acordo com o posicionamento da chave. Ao lado direito da figura, temos a representação simbólica do mesmo MUX2. Na representação simbólica, o posicionamento da chave é controlado pelo sinal c0.


A partir da animação, é possível identificar que o MUX2 possui 3 entradas e 1 saída, sendo elas: e0, e1, c0 e s0, respectivamente. O MUX2 pode também ser descrito pela seguinte tabela-verdade, onde 'X' pode ser '0' ou '1':

e0

e1

c0

s0

1

0

X

0

0

2

1

X

0

1

3

X

0

1

0

4

X

1

1

1

Note que, dependendo da variável c0, a saída s0 não é afetada pelo valor de 'X'. Em outras palavras, o valor de 'X' não importa para a saída s0 (don't care).


Descrevendo um MUX2 em Verilog

A tabela-verdade da seção anterior nos permite gerar a seguinte equação lógica através dos mintermos indicados nas linhas 2 e 4:

s0 =  (e0 AND (NOT c0)) OR (e1 AND c0)

A partir dessa equação em forma de soma-de-produto, temos o esquemático do MUX2 na tabela abaixo. O esquemático possui rótulos para os fios internos (w_0, w_1 e w_3). Estes rótulos são necessários para descrever o circuito em Verilog ao lado direito da tabela abaixo.

Esquemático (MUX2)

Código Verilog (MUX2)









    wire w_0, w_1, w_2;

    not(w_2, c0);
    and(w_0, e0, w_2);
    and(w_1, e1, c0);
    or(s0, w_0, w_1);

Veja que a codificação do esquemático para portas lógicas em Verilog é bem direta. O único cuidado a se tomar é colocar a saída da porta lógica sempre na primeira posição à esquerda, deixando as posições seguintes para as entradas da porta lógica.

porta_lógica (saída, entrada1, entrada2, ...)
Nota: a plataforma Pitanga aceita portas lógicas and, or, xor, nand, nor e xnor de até 4 entradas

Para encerrar a codificação do MUX2 em Verilog, falta-nos definir quais são as portas de entrada e saída. Iremos fazer isso utilizando a construção module/endmodule.



module mux2(
    input   e0,
    input   e1,
    input   c0,
    output  s0);

    wire w_0, w_1, w_2;

    not(w_2, c0);
    and(w_0, e0, w_2);
    and(w_1, e1, c0);
    or(s0, w_0, w_1);
endmodule

Pronto! Você acaba de projetar e descrever um multiplexador de 2 entradas em Verilog. Salve o código acima em um arquivo chamado mux2.v e vá para a seção a seguir.


Mapeando, compilando e prototipando

Prototipar o MUX2 na placa Community é bem simples e vamos fazer isso seguindo os passos abaixo:


1) Crie o arquivo de mapeamento das portas descritas em Verilog para os componentes da placa Community. Faça isso usando o exemplo a seguir:

mux2.pinout

2) Abra a placa Community

. pitanga.sh
python pitanga.py
Usuários Windows podem abrir a placa Community com um duplo clique no link Pitanga

3) Clique no botão "Upload Files" e selecione os arquivos mux2.v e mux2.pinout. Em seguida, clique em "Run".


Caso você não tenha cometido erros de codificação no Verilog, será impresso no terminal de texto o relatório com o resumo do projeto. Note que o relatório possui a mesma quantidade de fios e portas lógicas utlizados no esquemático. para este projeto, apenas 0.8% da capacidade lógica do chip virtual programável Pitanga foi utilizado.

                             DESIGN SUMMARY REPORT
  module     : mux2
  design file: mux2.v
  pinout file: mux2.pinout

Total number of wires: 3
Total number of cells: 4

  Cell          Instances   Cell          Instances   Cell          Instances
 -----------------------------------------------------------------------------
  AND2                  2 | NAND2                 0 | XOR2                  0 
  AND3                  0 | NAND3                 0 | XOR3                  0
  AND4                  0 | NAND4                 0 | XOR4                  0
  OR2                   1 | NOR2                  0 | XNOR2                 0
  OR3                   0 | NOR3                  0 | XNOR3                 0
  OR4                   0 | NOR4                  0 | XNOR4                 0
 -----------------------------------------------------------------------------
  BUF                   0 | INV                   1 | DFFRSE                0

Cells utilization: 4/500 cells (0.8 %).

4) Por fim, verifique se o circuito MUX2 está de acordo com o projeto clicando nas chaves sw9, sw1 e sw0. Na animação abaixo, você pode conferir o projeto na placa Community em operação ao lado de um MUX2.



Prototipando um MUX4 com reuso de código

Reuso de código é uma técnica muito comum. Grandes projetos se utilizam dessa técnica para poder entregar circuitos confiáveis e de forma mais rápida. Nesta seção, faremos o mesmo: iremos reusar o código do MUX2 para projetar um MUX4.


Abaixo, segue esquemático de um MUX4 composto por três multiplexadores de duas entradas. Os sinais internos foram nomeados e serão necessários para a codificação do circuito em Verilog.


Lembrando que a sintaxe para instanciar módulos é

nome_do_modulo nome_da_instancia(
    .porta_do_modulo(sinal_mapeado),
    .porta_do_modulo(sinal_mapeado),
    ...
    .porta_do_modulo(sinal_mapeado)
    );

segue descrição de um multiplexador de 4 entradas em Verilog. Note que o código do MUX4 apenas instancia módulos de MUX2, reusando o código da seção anterior.


module mux4(
    input       e0,
    input       e1,
    input       e2,
    input       e3,
    input       A,
    input       B,
    output      Y);

    wire    w_0, w_1;
    
    mux2 MUX2A (.e0(e0) , .e1(e1) , .c0(A), .s0(w_0));
    mux2 MUX2B (.e0(e2) , .e1(e3) , .c0(A), .s0(w_1));
    mux2 MUX2C (.e0(w_0), .e1(w_1), .c0(B), .s0(Y));
endmodule

Salve o código acima em um arquivo chamado mux4.v. Em seguida, escreva o arquivo de pinagem do projeto e salve-o com o nome de mux4.pinout. Reserve um tempo para fazer isso. Caso contrário, utilize o mapeamento a seguir.

mux4.pinout


Por fim, compile e prototipe o projeto do MUX4. O relatório resumido deve indircar o triplo de células lógicas utilizadas em comparação ao MUX2, como é de se esperar.


                             DESIGN SUMMARY REPORT
  module     : mux4
  design file: mux4.v
  pinout file: mux4.pinout

Total number of wires: 11
Total number of cells: 12

  Cell          Instances   Cell          Instances   Cell          Instances
 -----------------------------------------------------------------------------
  AND2                  6 | NAND2                 0 | XOR2                  0 
  AND3                  0 | NAND3                 0 | XOR3                  0
  AND4                  0 | NAND4                 0 | XOR4                  0
  OR2                   3 | NOR2                  0 | XNOR2                 0
  OR3                   0 | NOR3                  0 | XNOR3                 0
  OR4                   0 | NOR4                  0