Делитель частоты: классика на счётчике
Учимся получать из быстрого системного такта медленные сигналы — например, мигание светодиода раз в секунду.
Делитель частоты — схема на счётчике, которая из тактового сигнала высокой частоты формирует сигнал меньшей частоты, переключаясь раз в N тактов.
Системный такт FPGA обычно очень быстрый — 50, 100 или даже 200 МГц. Но человеку нужны медленные события: мигание светодиода раз в секунду, обновление дисплея, тики часов. Напрямую замедлить такт нельзя, зато можно поделить его счётчиком — это одна из первых практических схем, которую собирает каждый FPGA-инженер.
Идея деления
Принцип прост: считаем такты и переключаем выход каждые N тактов. Если входная частота 100 МГц (10^8 тактов в секунду), а нужен сигнал 1 Гц (одно переключение в секунду), счётчик должен досчитать до половины — потому что один полный период выхода состоит из «высокого» и «низкого» полупериодов. Сколько считать — простой расчёт:
# Расчёт предела счётчика для делителя частоты
f_in = 100_000_000 # входная частота, Гц (100 МГц)
f_out = 1 # желаемая частота на выходе, Гц (1 Гц — мигание раз в сек)
# выход переключается дважды за период (вкл/выкл), поэтому делим на 2
half_period_ticks = f_in // (2 * f_out)
bits_needed = (half_period_ticks).bit_length()
print(f"Считать до: {half_period_ticks} тактов")
print(f"Нужна разрядность счётчика: {bits_needed} бит")
print(f"Проверка: {f_in} / (2 * {half_period_ticks}) = {f_in/(2*half_period_ticks):.1f} Гц")Вывод:
Считать до: 50000000 тактов Нужна разрядность счётчика: 26 бит Проверка: 100000000 / (2 * 50000000) = 1.0 Гц
Итак, чтобы из 100 МГц получить 1 Гц, надо переключать выход каждые 50 миллионов тактов, а счётчику нужно минимум 26 бит. Эти числа — прямой вход в Verilog-модуль.
Делитель на Verilog
Теперь сам модуль. Счётчик считает до предела, затем сбрасывается и инвертирует выходной сигнал:
module clk_divider #(
parameter integer MAX = 50_000_000 - 1 // 50 млн тактов на полупериод
)(
input wire clk, // быстрый системный такт (100 МГц)
input wire rst,
output reg slow // медленный выход (1 Гц)
);
reg [25:0] counter; // 26 бит хватает на 50 млн
always @(posedge clk) begin
if (rst) begin
counter <= 0;
slow <= 0;
end else if (counter == MAX) begin
counter <= 0; // досчитали — сбрасываем
slow <= ~slow; // и переключаем выход
end else begin
counter <= counter + 1;
end
end
endmoduleЛогика прозрачна: пока счётчик не дошёл до MAX — инкремент; дошёл — обнуляем счётчик и инвертируем slow. Так slow переключается ровно раз в полупериод, давая на выходе 1 Гц.
Как работает под капотом
Важно понимать: делитель не «замедляет» сам такт — он остаётся 100 МГц. Делитель создаёт новый сигнал, который меняется медленно, но по-прежнему синхронизирован с быстрым тактом. Промоделируем маленький делитель на 3 (переключение каждые 3 такта) на Python:
# Делитель: переключаем выход каждые MAX+1 тактов
MAX = 2 # переключение каждые 3 такта (0,1,2)
counter = 0
slow = 0
print("такт | counter | slow")
print("-----+---------+-----")
for tick in range(10):
print(f" {tick} | {counter} | {slow}")
if counter == MAX:
counter = 0
slow = 1 - slow # инвертируем выход
else:
counter += 1Вывод:
такт | counter | slow -----+---------+----- 0 | 0 | 0 1 | 1 | 0 2 | 2 | 0 3 | 0 | 1 4 | 1 | 1 5 | 2 | 1 6 | 0 | 0 7 | 1 | 0 8 | 2 | 0 9 | 0 | 1
Выход slow переключается каждые 3 такта, его период — 6 тактов, то есть частота в 6 раз ниже входной. Точно так же 26-битный счётчик даёт 1 Гц из 100 МГц.
Частые ошибки
- Забыть про деление на 2. Полный период выхода — это два полупериода, поэтому считают до
f_in/(2·f_out), а неf_in/f_out. - Узкий счётчик. Для больших коэффициентов деления нужна большая разрядность; узкий счётчик переполнится и даст неверную частоту.
- Делать «новый такт» и тактировать им другую логику. Тактировать схему делёным сигналом как обычным проводом — плохая практика; для смены частоты используют специальные тактовые ресурсы (PLL), а делёный сигнал чаще применяют как разрешение (clock enable).
Итог
- Делитель частоты на счётчике формирует медленный сигнал из быстрого такта.
- Считать нужно до
f_in/(2·f_out)— период состоит из двух полупериодов. - Разрядность счётчика подбирают под коэффициент деления.
- Сам такт не замедляется — создаётся новый синхронный сигнал.