Entendendo Case em Verilog: Implementação Eficiente de Multiplexadores
A instrução case verifica se a expressão dada corresponde a uma das expressões na lista e desvia conforme necessário. É tipicamente usada para implementar multiplexadores. O construtor if-else pode não ser adequado para muitas condições e sintetizaria em um codificador de prioridade em vez de multiplexador.
Sintaxe
Um case Verilog inicia com case e termina com endcase. A expressão entre parênteses é avaliada exatamente uma vez e comparada com a lista de alternativas na ordem escrita. As instruções para a alternativa correspondente são executadas. Blocos de múltiplas instruções devem ser agrupados entre begin e end.
// 'expressao' deve corresponder a um dos itens (item 1,2,3 ou 4)
case (<expressao>)
case_item1 : <instrucao_unica>
case_item2, case_item3 : <instrucao_unica>
case_item4 : begin <multiplas instruções> end
default : <instrucao>
endcase
Se nenhum item corresponder, as instruções no default são executadas. O default é opcional, podendo haver apenas um por case. Cases podem ser aninhados.
A execução sai do bloco case sem fazer nada se nenhum item corresponder e não houver default.
Exemplo
O módulo abaixo tem um sinal de seleção de 2 bits para rotear uma de três entradas de 3 bits para a saída out. Um case atribui a entrada correta baseada em sel. Como sel é de 2 bits, tem 22 combinações (0 a 3). O default define saída como 0 se sel for 3.
module my_mux (
input [2:0] a, b, c,
input [1:0] sel,
output reg [2:0] out
);
always @ (a, b, c, sel) begin
case(sel)
2'b00 : out = a;
2'b01 : out = b;
2'b10 : out = c;
default : out = 0;
endcase
end
endmodule
Esquema de Hardware
O código RTL é elaborado para obter um esquema representando um multiplexador 4-para-1.
Veja que a saída é zero quando sel=3 e corresponde às entradas atribuídas para outros valores.
Log de Simulação
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0b11 out=0x0 [10] a=0x5 b=0x5 c=0x5 sel=0b10 out=0x5 [20] a=0x1 b=0x5 c=0x6 sel=0b01 out=0x5 [30] a=0x5 b=0x4 c=0x1 sel=0b10 out=0x1 [40] a=0x5 b=0x2 c=0x5 sel=0b11 out=0x0 ncsim: *W,RNQUIE: Simulation is complete.
Em case, a comparação só sucede quando cada bit da expressão corresponde à alternativa incluindo 0, 1, x e z. Se qualquer bit de sel for x ou z, o default executa pois nenhuma alternativa correspondeu, resultando em saída zero.
Log de Simulação com X/Z
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x0 [10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x0 [20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x0 [30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x0 [40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x0 [50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x0 [60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x0 [70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0 [80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x0 [90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x0 ncsim: *W,RNQUIE: Simulation is complete.
Se o case tiver x e z nas alternativas, os resultados serão diferentes.
module my_mux (
input [2:0] a, b, c,
input [1:0] sel,
output reg [2:0] out
);
always @ (a, b, c, sel) begin
case(sel)
2'bxz : out = a;
2'bzx : out = b;
2'bxx : out = c;
default : out = 0;
endcase
end
endmodule
Log de Simulação
ncsim> run [0] a=0x4 b=0x1 c=0x1 sel=0bxx out=0x1 [10] a=0x3 b=0x5 c=0x5 sel=0bzx out=0x5 [20] a=0x5 b=0x2 c=0x1 sel=0bxx out=0x1 [30] a=0x5 b=0x6 c=0x5 sel=0bzx out=0x6 [40] a=0x5 b=0x4 c=0x1 sel=0bxz out=0x5 [50] a=0x6 b=0x5 c=0x2 sel=0bxz out=0x6 [60] a=0x5 b=0x7 c=0x2 sel=0bzx out=0x7 [70] a=0x7 b=0x2 c=0x6 sel=0bzz out=0x0 [80] a=0x0 b=0x5 c=0x4 sel=0bxx out=0x4 [90] a=0x5 b=0x5 c=0x5 sel=0bxz out=0x5 ncsim: *W,RNQUIE: Simulation is complete.
Como case difere de if-else?
O case difere de if-else-if em dois aspectos:
- Expressões em
if-elsesão mais genéricas; emcase, uma única expressão é comparada com múltiplos itens casefornece resultado definitivo quando há valores X e Z na expressão
Verilog
- Dominando a Instrução Switch em C#: Sintaxe, Exemplos e Boas Práticas
- Instrução Break em C#: Como e Quando Usar
- Dominando a Instrução Continue em C#: Como Pular Iterações de Loop Eficazmente
- Dominando Switch-Case em C++: Sintaxe, Uso e Exemplos Práticos
- 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