[Перевод] Делители часов

Счетчики и их использование в делителях частоты

Для стабильной работы последовательным схемам нужен надежный тактовый сигнал для обеспечения стабильной синхронизации по времени. Для обеспечения стабильного источника частоты схемы генератора тактовых сигналов используют кварцевый резонатор. Драйверные схемы усиливают сигнал от кристалла (или генератора) в цифровой сигнал, который распространяется на остальные, например, запоминающие устройства в цифровой системе.

Большинству цифровых схем требуется несколько (или даже десятки) различных тактовых сигналов для управления различными подсистемами. Например, система на основе ППВМ может использовать тактовую частоту 48 кГц для создания аудиопотока, тактовую частоту 1 кГц для запуска таймера, тактовую частоту 10 МГц для запуска небольшого процессора и тактовую частоту 12 кГц для запуска контроллера двигателя. Было бы слишком дорого использовать отдельные внешние схемы осциллятора для создания такого количества различных тактовых сигналов, поэтому системы обычно производят необходимые им тактовые сигналы всего из одного или двух основных тактовых входов. Например, Blackboard использует только один внешний источник тактовой частоты 100 МГц.

Схема делителя тактовой частоты создает низкочастотные тактовые сигналы из входного источника тактовой частоты. Делитель подсчитывает входные тактовые циклы и устанавливает выходной тактовый сигнал на низком уровне, а затем на высоком уровне в течение некоторого количества входных тактовых циклов. Например, делитель тактовой частоты может установить выходной сигнал на низком уровне, подсчитывая пять 100 МГц-х входных тактовых циклов, затем установить сигнал на высоком уровне, подсчитывая еще пять циклов, и так далее в бесконечно повторяющейся последовательности для создания тактовой частоты 10 МГц.

Обратите внимание, что в ППВМ (например, чипе ZYNQ на Blackboard) тактовые сигналы, которые управляют триггерами, могут поступать только из двух источников: основного тактового входа или напрямую с выхода триггера. Тактовый сигнал не может поступать из какого-либо логического вентиля или логической схемы.

Простой делитель «пополам» может использовать один триггер, как показано ниже. Обратите внимание, что в коде Verilog выход «clk_div» приводится к типу reg в операторе порта модуля. Это необходимо сделать, поскольку «clk_div» назначается в операторе процедурного назначения, а все цели процедурного назначения должны иметь тип reg. Также стоит упомянуть, что выходы модуля могут иметь тип wire или reg, но входы должны иметь тип wire.

Рисунок 1. Триггер с инверторной обратной связью может делить тактовую частоту на 2.

Рисунок 1. Триггер с инверторной обратной связью может делить тактовую частоту на 2.

module dividebytwo (
    input clk, rst,
    output reg clk_div
    );

always @ (posedge(clk), posedge(rst))
begin
    if (rst) clk_div <= 0;
    else clk_div <= !clk_div;
end
endmodule

Счетчик n-бит может выдавать n разделенных тактовых сигналов, причем каждый последующий бит колеблется на половине частоты своего менее значимого соседа. Каждый бит делит входной тактовый сигнал на «степень 2», где показатель степени равен (номер бита + 1) в счетчике.

Рисунок 2. Биты двоичного счетчика делят входной тактовый сигнал увеличивающейся степенью числа 2.

Рисунок 2. Биты двоичного счетчика делят входной тактовый сигнал увеличивающейся степенью числа 2.

В коде Verilog ниже — шина «counterout» приводится к типу reg, поэтому любой или все биты счетчика могут использоваться в качестве тактовых сигналов другими схемами.

module counter1(
    input clk, rst,
    output reg [7:0] counterout
    );
    
 always @ (posedge(clk), posedge(rst))
 begin
     if (rst) counterout <= 0;
     else counterout <= counterout + 1;
end
endmodule

Более общая схема на основе счетчика может подсчитывать любое количество тактовых циклов, переключать выходной бит, а затем сбрасывать себя, чтобы создать свободно работающий делитель тактовой частоты. Обратите внимание, что триггеры в ППВМ (например, чип на вашей плате) могут использовать только тактовые импульсы, поступающие с основного тактового входа или напрямую с выхода другого триггера. Схема ниже делит основной входной тактовый импульс 100 МГц на 100 000, чтобы получить тактовый импульс 1 кГц.

Рисунок 3. Общая схема делителя тактовой частоты

Рисунок 3. Общая схема делителя тактовой частоты

Поведенческий блок на Verilog для делителя тактовой частоты сильно напоминает код на Verilog для счетчика — разница в одном дополнительном операторе «if» для проверки того, равно ли текущее значение счетчика конечному значению счетчика — если они равны, значение счетчика устанавливается в ноль. Обратите внимание, что конечное значение счетчика должно быть равно половине общей константы деления тактовой частоты. Это позволяет конечному значению счетчика переключать T-FF, при этом выход T-FF подается на низкий уровень в течение половины желаемого периода тактовой частоты, а затем на высокий уровень в течение половины желаемого периода тактовой частоты. Выход T-FF может напрямую использоваться в качестве часов другой схемой. Обратите внимание также, что использованное конечное значение счетчика на самом деле равно (конечный счет — 1), поскольку счёт начинается с 0.

Код ниже делит входной тактовый сигнал на 50 000, и поэтому константа счетчика терминала устанавливается на 25 000 (на самом деле на 25 000 — 1). Если бы эта схема была реализована на Blackboard, где входной тактовый сигнал составляет 100 МГц, результирующий выходной сигнал был бы 2 кГц.

Попробуйте написать код на Verilog для делителя тактовой частоты, а потом сравнить свою работу с примером кода здесь.

module ClkDivider (
    input clk, rst,
    output reg clk_div
    );
	
localparam terminalcount = (25000 - 1);
reg [15:0] count;
wire tc;

assign tc = (count == terminalcount);	// Place a comparator on the counter output

always @ (posedge(clk), posedge(rst))
begin
    if (rst) count <= 0;
    else if (tc) count <= 0;		// Reset counter when terminal count reached
    else count <= count + 1;
end

always @ (posedge(clk), posedge(rst))
begin
    if (rst) clk_div <= 0;
    else if (tc) clk_div = !clk_div;	// T-FF with tc as input signal
end
endmodule

Habrahabr.ru прочитано 1741 раз