Para cnt[0]: sensível a posedge\;clk e posedge\;rst. No reset cnt[0] recebe 1'b0; caso contrário, em cada posedge\;clk faz cnt[0] \leftarrow \lnot cnt[0].
Para cnt[1]: sensível a negedge\;cnt[0] e posedge\;rst. No reset cnt[1] recebe 1'b0; caso contrário, em cada negedge\;cnt[0] faz cnt[1] \leftarrow \lnot cnt[1].
Para cnt[2]: sensível a negedge\;cnt[1] e posedge\;rst. No reset cnt[2] recebe 1'b0; caso contrário, em cada negedge\;cnt[1] faz cnt[2] \leftarrow \lnot cnt[2].
O comportamento geral: é um contador ripple (divisor por 2 por estágio), onde cnt[0] alterna em cada borda de subida de clk; cnt[1] alterna em cada borda de descida de cnt[0]; cnt[2] alterna em cada borda de descida de cnt[1].
O reset rst é assíncrono (porque aparece em posedge rst nas sensibilidade): quando rst=1 todos os bits são forçados a 0 imediatamente.
Passo 2
O que precisamos implementar com JK flip-flops:
Cada bit cnt[i] vira a saída Q_i de um flip-flop JK.
Cada flip-flop tem comportamento “toggle” (inverte Q no evento de clock do seu bloco always).
O reset deve ser assíncrono e forçar Q_i=0 quando rst=1.
Os clocks dos estágios 1 e 2 devem responder às bordas de descida de cnt[0] e cnt[1], respectivamente.
Antes de desenhar, formalizo o que significa “toggle” com JK: colocar J=K=1 faz o flip-flop inverter sua saída no evento ativo do clock (bordas especificadas pelo tipo de FF).
Passo 3
Mini-aula sobre o flip-flop JK (o que vou usar):
O FF JK tem entradas J e K, saída atual Q e próxima saída Q^{+}. A equação booleana do próximo estado é:
Q^{+} = J\overline{Q} + \overline{K}Q.
Casos importantes:
J=K=0 => seguram estado (Q^{+}=Q).
J=1, K=0 => set (Q^{+}=1).
J=0, K=1 => reset (Q^{+}=0).
J=K=1 => toggle (Q^{+}=\overline{Q}).
Para obter o comportamento do código (inversão a cada evento de clock do bloco), escolhe-se J=K=1 no FF.
Reset assíncrono: muitos símbolos de FF têm entrada CLR (clear) assíncrona. Como no Verilog o reset é assíncrono e força a zero na borda de rst, ligar rst à entrada de clear assíncrona (ativa em nível alto) implementa exatamente aquele comportamento.
Passo 4
Mapeamento direto do Verilog para JK-FFs:
Para cnt[0]:
Usar um JK flip-flop (positivo-edge triggered) com J=K=1 para obter toggle em cada borda ativa.
Ligar o clock deste FF a clk para que o toggle ocorra em posedge\;clk.
Ligar rst à entrada de clear assíncrona do FF (ativa em nível alto) para forçar Q_0=0 quando rst=1.
A saída Q_0 será cnt[0].
Para cnt[1]:
Desejamos toggle em negedge\;cnt[0]. Se tivermos um FF JK de borda positiva (prático no desenho), podemos inverter cnt[0] e usar a saída invertida como clock: a posedge do \lnot cnt[0] corresponde à negedge de cnt[0].
Portanto: colocar um inversor com entrada cnt[0] e saída \lnot cnt[0]; ligar \lnot cnt[0] ao clock do segundo JK-FF (positivo-edge triggered). Novamente J=K=1.
Ligar rst à clear assíncrona do segundo FF.
A saída Q_1 será cnt[1].
Para cnt[2]:
Analogamente, precisamos de toggle em negedge\;cnt[1]. Inserir um inversor em cnt[1] e usar \lnot cnt[1] como clock do terceiro JK-FF (positivo-edge triggered).
Definir J=K=1 e ligar rst à clear assíncrona do terceiro FF.
A saída Q_2 será cnt[2].
Observação sobre alternativa: se forem usados JK-FFs com trigger em borda negativa nativa, pode-se conectar diretamente cnt[0] ao clock do FF1 e cnt[1] ao clock do FF2 sem inversores. Aqui descrevo a solução usando inversores porque é comum desenhar com FFs de borda positiva.
Passo 5
Detalhes elétricos e cuidados práticos (o que anotar no esquema):
Os sinais de clock que vêm de saídas de FF (cnt[0] e cnt[1]) servindo como clock para outros FFs geram um contador do tipo ripple (assíncrono). Isso é exatamente o comportamento do Verilog original (blocos sensitive a negedge do bit anterior). No desenho, aceitar que há atraso de propagação entre os estágios — é esperado em ripple counters.
J_1 = K_1 = 1. CLK_1 \leftarrow \lnot cnt[0] (inversor entre cnt[0] e CLK_1). CLR_1 \leftarrow rst. Q_1 = cnt[1].
J_2 = K_2 = 1. CLK_2 \leftarrow \lnot cnt[1] (inversor entre cnt[1] e CLK_2). CLR_2 \leftarrow rst. Q_2 = cnt[2].
Se o símbolo do JK-FF no esquema possuir entradas \overline{CLR} (clear ativa baixa) ao invés de clear ativa alta, o arranjo de reset deve ser adaptado (por exemplo, usar inversor em rst etc.). No entanto, o código Verilog assume clear ativa em nível alto, então no esquema eu assumo entradas CLR ativas em nível alto.
Passo 6
Descrição esquemática final (passo a passo para desenhar o diagrama):
Desenhar três blocos de flip-flop JK empilhados verticalmente: FF_0, FF_1, FF_2. Em cada bloco indicar entradas J, K, CLK, CLR e saída Q.
Em cada FF_i conectar J e K ao nível lógico 1: escrever J_i = K_i = 1.
Ligar rst à entrada CLR de todos os FFs (sinal comum). Escrever CLR_i \leftarrow rst para i=0,1,2.
Para FF_0:
Ligar CLK_0 \leftarrow clk.
Sair Q_0 e rotular como cnt[0].
Para FF_1:
Colocar um inversor cujo input é Q_0 (ou cnt[0]); a saída do inversor é \lnot cnt[0].
Ligar CLK_1 \leftarrow \lnot cnt[0] (saída do inversor).
Sair Q_1 e rotular como cnt[1].
Para FF_2:
Colocar um inversor cujo input é Q_1 (ou cnt[1]); a saída é \lnot cnt[1].
Ligar CLK_2 \leftarrow \lnot cnt[1] (saída do segundo inversor).
Sair Q_2 e rotular como cnt[2].
Opcional (observação prática no diagrama): indicar que cada inversor implementa a conversão de borda negativa desejada (ou substituir por FFs de borda negativa se disponível).
Passo 7
Representação textual condensada do esquema (próxima caixa que serve como “desenho” textual — usar isto para transpor para um diagrama esquemático gráfico):