Делитель часов VHDL с десятичными знаками

Я пытаюсь замедлить тактовую частоту 50 МГц до 25,175 МГц для использования в контроллере VGA. У меня уже есть делитель часов, но у меня возникают проблемы с замедлением часов, когда результирующее деление текущей тактовой частоты и желаемой тактовой частоты не является целым числом. т.е. 50000000/25175000 ~ 1,98. Делитель часов компилируется и запускается, но ничего не выводит, если деление представляет собой десятичное число. Вот мой код:

    LIBRARY IEEE;
    USE  IEEE.STD_LOGIC_1164.ALL;

    ENTITY Clockdiv IS PORT (
        Clkin: IN STD_LOGIC;
        Clk: OUT STD_LOGIC);
    END Clockdiv;

    ARCHITECTURE Behavior OF Clockdiv IS
        CONSTANT max: INTEGER := 50000000/25175000;
        CONSTANT half: INTEGER := max/2;
        SIGNAL count: INTEGER RANGE 0 TO max;
    BEGIN
        PROCESS
        BEGIN
            WAIT UNTIL Clkin'EVENT and Clkin = '1';

            IF count < max THEN
                count <= count + 1;
            ELSE
                count <= 0;
            END IF;

            IF count < half THEN
                Clk <= '0';
            ELSE
                Clk <= '1';
            END IF;
        END PROCESS;
    END Behavior;

Я искал в Google и обнаружил, что использование типа данных REAL позволит вам использовать десятичные дроби, но когда я изменил используемые переменные на REAL, Quartus выдает мне ошибку: Error (10414): VHDL Unsupported Feature error at Clockdiv.vhd(12): cannot synthesize non-constant real objects or values.

Затем, если я изменю "count" на тип CONSTANT, я получу ошибку: Error (10477): VHDL error at Clockdiv.vhd(18): name "count" must represent signal.

Кто-нибудь знает, как я могу замедлить часы до 25,175 МГц? Кроме того, кто-нибудь знает, как замедлить часы, чтобы компилятор был доволен результирующим делением, являющимся десятичным значением?

Спасибо


person Eric Townsend    schedule 18.06.2012    source источник
comment
На какой доске вы работаете? Он может поставляться с менеджером цифровых часов (DCM), который может предложить лучший результат деления и более простую реализацию. Я знаю, что они есть на платах Spartan 3a от Xilinx.   -  person Paul Seeb    schedule 18.06.2012
comment
Для этого я использую плату Altera DE1. FPGA на этой плате имеет 4 PLL, но, насколько мне известно, у него нет цифрового диспетчера часов, как упоминал Пол Сиб. Итак, я думаю, что мой следующий вопрос: как мне использовать PLL в Quartus для использования в качестве делителя тактовой частоты?   -  person Eric Townsend    schedule 19.06.2012
comment
если у вас есть PLL, вы можете сделать часы с более высокой / более низкой частотой, пока аппаратное обеспечение может достичь желаемой частоты. Я думаю, что большинство DCM делают это именно так. Например, удвоение тактовой частоты достигается путем XOR ваших часов с тактовым сигналом, сдвинутым по фазе на 90 градусов.   -  person Paul Seeb    schedule 20.06.2012
comment
Дополнительную информацию о PLL можно найти здесь: altera.com/literature/hb/ cyc2/cyc2_cii51007.pdf Я предполагаю, что Quartus, вероятно, также имеет какой-то хороший волшебный способ их настройки.   -  person sonicwave    schedule 20.06.2012
comment
Отлично, я понял, как использовать PLL на этом чипе. Теперь он работает отлично. Большое спасибо всем за вашу помощь!   -  person Eric Townsend    schedule 21.06.2012


Ответы (2)


Вещественные числа, как правило, не поддаются синтезу, поэтому вам нужно придумать целочисленное решение.

Это соотношение довольно сложное, потому что оно почти 2:1, но не совсем. Большинство схем делителя тактового сигнала на основе фронта работают только с одним фронтом исходного тактового сигнала, поэтому наименьшее соотношение, на которое вы можете разделить, равно 2. В этом случае вам придется работать с обоими фронтами тактового сигнала.

Как только вы это сделаете, вам нужно иметь счетчик, который увеличивается на знаменатель вашего отношения и превышает числитель, а затем выводит фронт часов.

PROCESS
    BEGIN
        WAIT UNTIL Clkin'EVENT;

        IF count < max THEN
            count <= count + DENOMINATOR;
        ELSE
            count <= 0;
        END IF;

        IF count > NOMINATOR THEN
            Clk <= ~Clk;
        END IF;
    END PROCESS;

Для этого отношения я думаю, что наименьший способ, которым вы можете его представить, это 2000/1007.

Проблема в том, что вы получите тактовую частоту, которая в основном составляет 25 МГц, но иногда (каждые 2000/7 итераций) вы получаете дополнительное преимущество. Это не будет тактовая частота 25,175 МГц. Получение 25,175 МГц с 50 МГц невозможно без PLL.

person Paul S    schedule 18.06.2012
comment
Хотите уточнить, как работает код? Зачем добавлять знаменатель? И зачем сравнивать больше, чем числитель, когда вы хотите переключить часы? - person Unknown123; 27.10.2019

Я написал множество контроллеров VGA, и просто использование тактовой частоты 25 МГц никогда не было большой проблемой. Однако, если вы абсолютно хотите приблизиться, ваша FPGA, вероятно, имеет какой-то диспетчер часов (я знаком только с устройствами Xilinx), который позволит вам синтезировать выходные часы путем умножения и деления входных часов.

Кроме того, хотя использование производных/гейтированных часов (часов, в которых вы напрямую устанавливаете значение в процессе), вероятно, будет работать для вас в этом случае, это может привести к множеству проблем, которые трудно отладить. Лучшим решением является создание включения тактовых импульсов, а затем запуск всего на одних и тех же (быстрых) тактовых частотах.

И последнее, хотя это, вероятно, в большей степени вопрос предпочтительного стиля, но я обычно использую операторы синхронизированного процесса вместо операторов WAIT (показанных ниже с триггером нарастающего фронта, синхронным сбросом и включением часов). Я считаю, что его легче читать и понимать, и я менее склонен к написанию несинтезируемых конструкций, таких как wait for 10ns;, или операторов с несколькими WAIT.

process(clk)
begin
    if(rising_edge(clk)) then
        if(sync_reset = '1') then
            --Reset logic
        elsif(clk_enable = '1') then
            --Actual functionality
        end if;
    end if;
end process;
person sonicwave    schedule 18.06.2012
comment
Операторы ожидания абсолютно синтезируемы. Могут быть случаи, когда синтезатор не может реализовать то, о чем вы просили (например, вы делаете вывод о регистрах, чувствительных к обоим краям, что может быть проблемой для кода в моем ответе), но во многих случаях использование OP нормально инструменты (Synopsys Design-Compiler для одного). - person Paul S; 27.06.2012
comment
Достаточно честно, я подправил свой ответ. Вероятно, на меня это повлияло в 90% случаев, когда я видел, как он использовался, люди спрашивали, почему их wait for xxx ns; код не может быть синтезирован;) - person sonicwave; 28.06.2012
comment
Аааа, согласен. wait for xxx ns; не имеет надежды быть синтезированным. - person Paul S; 28.06.2012
comment
Одним из преимуществ стиля wait until clk'event and clk == '1' является то, что при моделировании процесс не просыпается при отрицательных перепадах только для того, чтобы не выполнить if rising_edge и снова вернуться в спящий режим. Однако это очень-очень незначительно. - person Paul S; 28.06.2012