Реализация последовательной логики с помощью блоков always в Verilog
Предыдущая статья показывала примеры комбинационной логики с always. always блок также широко используется для последовательной логики с элементами памяти (триггеры), способными удерживать значения.
JK-триггер
JK-триггер — один из типов триггеров для хранения значений с двумя входами данных j и k, сбросом rstn и тактом clk. Таблица истинности:
| rstn | j | k | q | Комментарий |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | Сброс утверждает выход в 0 |
| 1 | 0 | 0 | Hold | j=k=0: выход сохраняет предыдущее значение |
| 1 | 0 | 1 | 1 | k=1: выход становится 1 |
| 1 | 1 | 0 | 0 | k=0: выход становится 0 |
| 1 | 1 | 1 | Toggle | j=k=1: выход переключает текущее значение |
Поведенческий Verilog-код для JK-триггера:
module jk_ff ( input j, k, rstn, clk, output reg q);
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin q <= 0; end
else begin q <= (j & ~q) | (~k & q); end
end
endmodule
Тестбенч
Объявляем переменные, запускаем такт простым always блоком, инстанцируем дизайн. q — wire (подключён к выходу дизайна), остальные входы — reg для управления в процедурных блоках. Стимул: инициализация нулями, деассерт сброса через 10 единиц, for цикл для случайных значений j, k в случайное время.
module tb; reg j, k, rstn, clk; wire q; integer i; reg [2:0] dly;
always #10 clk = ~clk;
jk_ff u0 ( .j(j), .k(k), .clk(clk), .rstn(rstn), .q(q));
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
На волне видно: на posedge такта q меняется в зависимости от j, k по таблице истинности.
Счётчик по модулю 10 (Modulo-10 counter)
Счётчики по модулю (MOD) считают до определённого числа, затем сбрасываются в ноль. MOD-N считает от 0 до N-1 и снова. Требуют log2N триггеров. Код MOD-10 счётчика, считающего вверх на каждом такте пока rstn деассертирован. Параметры Verilog позволяют сделать масштабируемый MOD-N.
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
Тестбенч
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
Счётчик считает 0→9, перескакивает на 0 и продолжает.
4-битный левый сдвиговый регистр
Принимает вход d в LSB, все биты сдвигаются влево на 1. Если d=0 и начальное значение 0011, на следующем фронте станет 0110.
module lshift_4b_reg ( input d, clk, 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
Тестбенч
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
Видно: каждый бит сдвигается влево на 1, новое значение d попадает в LSB.
Verilog
- Мастерство VHDL и Verilog: написание чистой комбинационной и последовательной логики
- Цепь с переключателем: практическое руководство по базовым электрическим цепям
- Интегральные схемы: основы цифровых логических элементов
- Программируемые логические контроллеры (ПЛК): современное цифровое управление для промышленных систем
- Понимание булевой алгебры: от логических основ к цифровым схемам
- Мастерство упрощения логики с картами Карно
- Цифровая логика с обратной связью: от детерминированных гейтов к мультивибраторам
- Параметризованный Mod-N счётчик на Verilog: модуль и тестбенч
- Счётчик Грея на Verilog: 4-битный генератор кода Грея
- Достигайте идеальных финишей с точными шлифовальными станками Okamoto