Implementando Lógica Sequencial Usando Blocos 'always' do Verilog
Um artigo anterior mostrou diferentes exemplos de uso de um bloco always para implementar lógica combinacional. Um bloco always também é principalmente usado para implementar lógica sequencial, que possui elementos de memória como flip-flops que podem reter valores.
Flip-Flop JK
Um flip-flop JK é um dos muitos tipos de flops usados para armazenar valores e possui duas entradas de dados j e k, junto com uma para reset rstn e outra para clock clk. A tabela-verdade para um flip-flop JK é mostrada abaixo e é tipicamente implementada usando portas NAND.
| rstn | j | k | q | Comentários |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | Quando reset é afirmado, saída é sempre zero |
| 1 | 0 | 0 | Mantém valor | Quando tanto j quanto k são 0, saída permanece a mesma de antes |
| 1 | 0 | 1 | 1 | Quando k=1, saída torna-se 1 |
| 1 | 1 | 0 | 0 | Quando k=0, saída torna-se 0 |
| 1 | 1 | 1 | Alterna valor | Quando j=1,k=1 saída alterna valor atual |
O código Verilog comportamental para um flip-flop JK pode ser escrito como mostrado abaixo:
module jk_ff (
input j, // Entrada J
input k, // Entrada K
input rstn, // Reset assíncrono ativo-baixo
input clk, // Clock de entrada
output reg q // Saída Q
);
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
q <= 0;
end else begin
q <= (j & ~q) | (~k & q);
end
end
endmodule
Testbench
Primeiro declare todas as variáveis usadas no testbench e inicie um clock usando um bloco always simples que pode ser conduzido ao design. Então instancie o design e conecte suas portas com as variáveis correspondentes do testbench. Note que q é do tipo wire porque está conectado a uma saída do design que estará ativamente conduzindo-o. Todas as outras entradas para o design são do tipo reg para que possam ser conduzidas dentro de um bloco procedural como initial.
O estímulo primeiro inicializa todas as entradas do design para zero e então desafirma reset após algum tempo. Um loop for é usado para conduzir diferentes valores para j e k que são conduzidos em tempos aleatórios. Uma vez que o loop termina, espere mais algum tempo e termine a simulação.
module tb;
// Declarar variáveis do testbench
reg j, k, rstn, clk;
wire q;
integer i;
reg [2:0] dly;
// Iniciar o clock
always #10 clk = ~clk;
// Instanciar o design
jk_ff u0 (
.j(j),
.k(k),
.clk(clk),
.rstn(rstn),
.q(q)
);
// Escrever o estímulo
initial begin
{j, k, rstn, clk} <= 0;
#10 rstn <= 1;
for (i = 0; i < 10; i = i+1) begin
dly = $random;
#(dly) j <= $random;
#(dly) k <= $random;
end
#20 $finish;
end
endmodule
Note na onda de simulação que na borda de subida do clock, a saída q muda valor baseado no estado das entradas j e k como dado na tabela-verdade.
Contador Módulo-10
Contadores de Módulo (MOD) simplesmente contam até um certo número antes de voltar a zero. Um contador MOD-N contará de 0 a N-1 e então voltará a zero e começará a contar novamente. Tais contadores tipicamente requerem log2N número de flops para reter o valor da contagem. Mostrado abaixo está o código Verilog para um contador MOD-10 que continua contando a cada clock clk enquanto reset rstn estiver desafirmado.
Parâmetros Verilog podem ser usados para tornar um contador MOD-N mais escalável.
module mod10_counter (
input clk,
input rstn,
output reg [3:0] out
);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
if (out == 10)
out <= 0;
else
out <= out + 1;
end
end
endmodule
Testbench
O testbench primeiro declara algumas variáveis que podem ser atribuídas alguns valores e conduzidas às entradas do design. O módulo contador é então instanciado e conectado com os sinais do testbench que são posteriormente conduzidos com alguns valores no estímulo. Como o contador também requer um clock, o clock do testbench é modelado com um bloco always. O estímulo simplesmente define valores padrão no tempo 0ns, então desafirma reset após 10ns e o design é permitido rodar por algum tempo.
module tb;
reg clk, rstn;
reg [3:0] out;
mod10_counter u0 (
.clk(clk),
.rstn(rstn),
.out(out)
);
always #10 clk = ~clk;
initial begin
{clk, rstn} <= 0;
#10 rstn <= 1;
#450 $finish;
end
endmodule
Veja que o módulo contador conta de zero a 9, volta para zero e começa a contar novamente.
Registrador de Deslocamento à Esquerda de 4 bits
Mostrado abaixo está um registrador de deslocamento à esquerda de 4 bits que aceita uma entrada d no LSB e todos os outros bits serão deslocados à esquerda por 1. Por exemplo, se d for igual a zero e o valor inicial do registrador for 0011, ele se tornará 0110 na próxima borda do clock clk.
module lshift_4b_reg (
input d,
input clk,
input rstn,
output reg [3:0] out
);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
out <= {out[2:0], d};
end
end
endmodule
Testbench
O testbench segue um modelo similar ao mostrado antes onde algumas variáveis são declaradas, módulo de design é instanciado e conectado com os sinais do testbench. Então um clock é iniciado e o estímulo é conduzido ao design usando um bloco initial. Neste exemplo de testbench, diferentes valores de d têm que ser exercidos e portanto um loop for é usado para iterar 20 vezes e aplicar valores aleatórios ao design.
module tb;
reg clk, rstn, d;
wire [3:0] out;
integer i;
lshift_4b_reg u0 (
.d(d),
.clk(clk),
.rstn(rstn),
.out(out)
);
always #10 clk = ~clk;
initial begin
{clk, rstn, d} <= 0;
#10 rstn <= 1;
for (i = 0; i < 20; i=i+1) begin
@(posedge clk) d <= $random;
end
#10 $finish;
end
endmodule
Note que cada bit é deslocado à esquerda por 1 e o novo valor de d é aplicado ao LSB.
Verilog
- Dominando VHDL & Verilog: Escrevendo Lógica Combinacional e Sequencial Limpa
- Circuito com Chave: Guia Prático para Circuitos Elétricos Básicos
- Circuitos Integrados: Fundamentos de Portas Lógicas Digitais
- Controladores Lógicos Programáveis (CLPs): Controle Digital Moderno para Sistemas Industriais
- Entendendo Álgebra Booleana: Dos Fundamentos Lógicos a Circuitos Digitais
- Dominando Simplificação Lógica com Mapas de Karnaugh
- Lógica Digital com Realimentação: De Portas Determinísticas a Multivibradores
- Projeto de Contador Mod-N em Verilog: Módulo Parametrizado e Testbench
- Módulo Contador Gray em Verilog – Gerador de Código Gray de 4 Bits
- Obtenha Acabamentos Perfeitos com as Retificadoras de Precisão Okamoto