Как создать счетчик для отображения 6 цифр с использованием анодов?

Я пытаюсь написать цифровые часы на vhdl для fpga, работающего на частоте 100 МГц. Я могу записать это на 4 анода, создав счетчик, как показано ниже (count1 = 249999), цифры кажутся довольно четкими. Однако, когда я хочу отобразить время в формате ЧЧ:ММ:СС (когда я хочу использовать 6 анодов вместо 4), я не могу четко отображать цифры. Когда я сильно увеличиваю значение count1, светодиоды начинают мигать, когда я уменьшаю значение count1, цифры трудно идентифицировать.

Есть ли какой-либо теоретический способ определить значение этого счетчика (counter1)? Можно ли четко показать 6 цифр так, как я пытаюсь?

Спасибо с этого момента.

код, отвечающий за отображение 4-х анодов:

anode_clock : process(count1, clk_in, A_counter) -- counter to display all digits using anodes
begin 
    if(rising_edge(clk_in)) then
        count1 <= count1 + 1;
        if(count1 = 249999) then  -- ATTENTION HERE
            A_counter <= A_counter + 1;
            count1 <= 0;
        end if;
    end if;
end process;

anode_display : process (A_counter, tmp_AN, min0, min1, hour0) begin -- matching anodes to display
    AN <= tmp_AN;
    case A_counter is
        when 0 =>
            tmp_AN <= "1110";
            if (min0 = 0) then
                DISP <= "1000000";
            elsif min0 = 1 then
                DISP <= "1111001";
            elsif min0 = 2 then
                DISP <= "0100100";
            elsif min0 = 3 then
                DISP <= "0110000";
            elsif min0 = 4 then
                DISP <= "0011001";
            elsif min0 = 5 then
                DISP <= "0010010";
            elsif min0 = 6 then
                DISP <= "0000010";
            elsif min0 = 7 then
                DISP <= "1111000";
            elsif min0 = 8 then
                DISP <= "0000000";
            elsif min0 = 9 then
                DISP <= "0010000";
            end if;
        when 1 =>
            tmp_AN <= "1101";
            if (min1 = 0) then
                DISP <= "1000000";
            elsif min1 = 1 then
                DISP <= "1111001";
            elsif min1 = 2 then
                DISP <= "0100100";
            elsif min1 = 3 then
                DISP <= "0110000";
            elsif min1 = 4 then
                DISP <= "0011001";
            elsif min1 = 5 then
                DISP <= "0010010";
            elsif min1 = 6 then
                DISP <= "1000000";
            end if;
        when 2 =>
            tmp_AN <= "1011";
            if (hour0 = 0) then
                DISP <= "1000000";
            elsif hour0 = 1 then
                DISP <= "1111001";
            elsif hour0 = 2 then
                DISP <= "0100100";
            elsif hour0 = 3 then
                DISP <= "0110000";
            elsif hour0 = 4 then
                DISP <= "0011001";
            elsif hour0 = 5 then
                DISP <= "0010010";
            elsif hour0 = 6 then
                DISP <= "0000010";
            elsif hour0 = 7 then
                DISP <= "1111000";
            elsif hour0 = 8 then
                DISP <= "0000000";
            elsif hour0 = 9 then
                DISP <= "0010000";
            elsif hour0 = 10 then
                DISP <= "1000000";
            elsif hour0 = 11 then
                DISP <= "1111001";
            elsif hour0 = 12 then
                DISP <= "0100100";
            elsif hour0 = 13 then
                DISP <= "1000000";
            end if;
        when 3 =>
            tmp_AN <= "0111";
            if (hour0 = 10) then
                DISP <= "1111001";
            elsif hour0 = 11 then
                DISP <= "1111001";
            elsif hour0 = 12 then
                DISP <= "1111001";
            else 
                DISP <= "1000000";
            end if;
    end case;
end process;

вывод (как я хотел):введите описание изображения здесь

код, отвечающий за отображение 6 анодов(цифры не читаются):

anode_clock : process(count1, clk_in, A_counter) -- counter to display all digits using anodes
begin 
    if(rising_edge(clk_in)) then
        count1 <= count1 + 1;
        if(count1 = 125000) then -- experimental value: 249999
            A_counter <= A_counter + 1;
            count1 <= 0;
        end if;
    end if;
end process;

anode_display : process (A_counter, tmp_AN, sec0,sec1, min0, min1, hour0) begin -- matching anodes to display
    AN <= tmp_AN;
    case A_counter is
        when 0 =>
            tmp_AN <= "111110";
            if (sec0 = 0) then
                DISP <= "1000000";
            elsif sec0 = 1 then
                DISP <= "1111001";
            elsif sec0 = 2 then
                DISP <= "0100100";
            elsif sec0 = 3 then
                DISP <= "0110000";
            elsif sec0 = 4 then
                DISP <= "0011001";
            elsif sec0 = 5 then
                DISP <= "0010010";
            elsif sec0 = 6 then
                DISP <= "0000010";
            elsif sec0 = 7 then
                DISP <= "1111000";
            elsif sec0 = 8 then
                DISP <= "0000000";
            elsif sec0 = 9 then
                DISP <= "0010000";
            end if;
        when 1 =>
            tmp_AN <= "111101";
            if (sec1 = 0) then
                DISP <= "1000000";
            elsif sec1 = 1 then
                DISP <= "1111001";
            elsif sec1 = 2 then
                DISP <= "0100100";
            elsif sec1 = 3 then
                DISP <= "0110000";
            elsif sec1 = 4 then
                DISP <= "0011001";
            elsif sec1 = 5 then
                DISP <= "0010010";
            elsif sec1 = 6 then
                DISP <= "1000000";
            end if;
        when 2 =>
            tmp_AN <= "111011";
            if (min0 = 0) then
                DISP <= "1000000";
            elsif min0 = 1 then
                DISP <= "1111001";
            elsif min0 = 2 then
                DISP <= "0100100";
            elsif min0 = 3 then
                DISP <= "0110000";
            elsif min0 = 4 then
                DISP <= "0011001";
            elsif min0 = 5 then
                DISP <= "0010010";
            elsif min0 = 6 then
                DISP <= "0000010";
            elsif min0 = 7 then
                DISP <= "1111000";
            elsif min0 = 8 then
                DISP <= "0000000";
            elsif min0 = 9 then
                DISP <= "0010000";
            end if;
        when 3 =>
            tmp_AN <= "110111";
            if (min1 = 0) then
                DISP <= "1000000";
            elsif min1 = 1 then
                DISP <= "1111001";
            elsif min1 = 2 then
                DISP <= "0100100";
            elsif min1 = 3 then
                DISP <= "0110000";
            elsif min1 = 4 then
                DISP <= "0011001";
            elsif min1 = 5 then
                DISP <= "0010010";
            elsif min1 = 6 then
                DISP <= "1000000";
            end if;
        when 4 =>
            tmp_AN <= "101111";
            if (hour0 = 0) then
                DISP <= "1000000";
            elsif hour0 = 1 then
                DISP <= "1111001";
            elsif hour0 = 2 then
                DISP <= "0100100";
            elsif hour0 = 3 then
                DISP <= "0110000";
            elsif hour0 = 4 then
                DISP <= "0011001";
            elsif hour0 = 5 then
                DISP <= "0010010";
            elsif hour0 = 6 then
                DISP <= "0000010";
            elsif hour0 = 7 then
                DISP <= "1111000";
            elsif hour0 = 8 then
                DISP <= "0000000";
            elsif hour0 = 9 then
                DISP <= "0010000";
            elsif hour0 = 10 then
                DISP <= "1000000";
            elsif hour0 = 11 then
                DISP <= "1111001";
            elsif hour0 = 12 then
                DISP <= "0100100";
            elsif hour0 = 13 then
                DISP <= "1000000";
            end if;
        when 5 =>
            tmp_AN <= "011111";
            if (hour0 = 10) then
                DISP <= "1111001";
            elsif hour0 = 11 then
                DISP <= "1111001";
            elsif hour0 = 12 then
                DISP <= "1111001";
            else 
                DISP <= "1000000";
            end if;
    end case;
end process;

вывод (цифры не такие, как я хотел, что-то не так с отображением счетчика):введите описание изображения здесь

Вы уверены, что аноды - это то слово, которое вам нужно? Анод — это всего лишь один вывод двухполюсника.
ммм, у вас довольно быстрые часы (100 МГц), но вы должны научить их использовать 6 полубайтов BCD (4 бита), а не 4 двоичных байта (8). Затем поместите темно-красный прозрачный пластиковый фильтр для улучшения контраста. Я вижу 88061817. Это цифра BCD или HEX?
@ThePhoton Я знаю физический смысл. Насколько мне известно, для семисегментных дисплеев анод — это просто цифра. Например, на моей FPGA есть 8 анодов для моих семи сегментов. Я могу ошибаться, и буду признателен, если вы скажете мне, если я ошибаюсь.
@TonyStewart.EEsince'75 ну, мои знания fpga и vhdl довольно ограничены. Я могу писать коды, как указано выше, но не знаю, как реализовать ваше предложение. Можете ли вы сказать мне какой-либо источник о том, как это сделать?
Если значения светодиодов являются просто адресами памяти, тогда погуглите математический код для вывода часов BCD с точным вводом часов для внутреннего счетчика idc-online.com/technical_references/pdfs/electronic_engineering и en.wikipedia.org/wiki/Binary-coded_decimal/…
Должен ли я угадать, являются ли значения светодиодов просто адресами памяти или жестко закодированными двоичными кодированными цифрами на двоичном счетчике или что? У меня картинки не увеличиваются.
Полный код @TonyStewart.EEsince'75 можно найти здесь: repl.it/IAEN. Можете ли вы определить причину по этому полному коду?
@ErenL, если бы вы написали «4 анода 7-сегментного дисплея с общим катодом» или даже просто упомянули 7-сегментные дисплеи до того, как использовали слово « анод» , это было бы более понятно.

Ответы (3)

Это неотъемлемое ограничение мультиплексирования: поскольку вы вводите только одну цифру за раз, ваш дисплей становится тусклее по мере увеличения количества цифр. Тем не менее, вы должны быть в состоянии нормально управлять 8 цифрами.

Я бы попытался явно обернуть ваш счетчик, чтобы убедиться, что вы вводите определенную цифру в любой момент времени:

    if(count1 = 249999) then  -- ATTENTION HERE
        A_counter <= A_counter + 1;
        if(A_counter < 6) then -- 6 or 4, depending on how many digits you drive
            A_counter <= A_counter + 1;
        else
            counter <= 0;
        end if;
        count1 <= 0;
    end if;

Похоже, что в 6-значном коде A_COUNTER постоянно зацикливается, что означает, что есть как минимум 2 состояния, состояние 6 и состояние 7, которые явно не декодируются. Попробуйте явно отключить все сегменты для состояний 6 и 7. Если A_COUNTER больше 3 бит, вам нужно выяснить, что происходит с дисплеем, когда A_COUNTER не от 0 до 5.

Поскольку активация дисплея активна на низком уровне (0 = включено), вполне вероятно, что все сегменты включены по умолчанию, когда вы не говорите им выключить, как это может происходить в состояниях 6 и 7.

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

Я не уверен, что есть дополнительные случаи 6 и 7. Но поскольку 2 неиспользуемые цифры (крайние слева) включены со всеми горящими сегментами, кажется, что некоторые цифры/сегменты горят по умолчанию, если вы их не выключите. Если дел всего 6, и для каждого включена 1 цифра, то не должно быть времени, чтобы разряды 6 и 7 горели, а горят. Я считаю, что и строка, и сегмент получают (00000000,00000000) по умолчанию в течение некоторого короткого интервала и включают все цифры и все сегменты.

Проверьте это, выводя значения включения цифр с 8 двоичными цифрами (11xxxxxx), а не с 6 (xxxxxx), чтобы 2 верхние неиспользуемые цифры были отключены. Крайние 2 цифры будут тусклее, но все еще частично освещены.

Когда есть незакодированные случаи, Xilinx выдает ошибку. Вы уверены, что есть состояние 6 и состояние 7. Потому что counter1 определяется как целочисленный диапазон от 0 до 5.
Обновленный ответ.

В вашем коде есть некоторые проблемы, которые я бы посоветовал вам исправить, чтобы упростить отладку. Во-первых, вы несколько раз продублировали декодирование катода [сегмента] - это нужно сделать только один раз - я бы предложил процесс, который имеет текущую десятичную цифру в качестве сигнала в списке чувствительности и устанавливает сегменты. Тогда основной процесс, управляемый часами, будет намного проще без дублированного декодирования. На практике инструменты синтеза, вероятно, будут эффективно отображать такое декодирование в таблицу циклов ОЗУ на FPGA - они могут быть не в состоянии сделать это для вашего кода, например

Маршрутизация, управляемая основным тактовым сигналом, затем циклически устанавливает соответствующий десятичный сигнал и анодный сигнал. Мой подход состоял бы в том, чтобы инициализировать выход анода на «111110» и циклически сдвигать его влево на каждом тактовом цикле в синхронизированном процессе и вводить логику для установки соответствующего цифрового сигнала для отображения.

Что не ясно, так это то, какие часы вы используете для управления этим процессом. Вероятно, он не должен работать на частоте системных часов 100 МГц или около того, если управляет светодиодами - я бы посоветовал использовать его на частоте около 1 кГц или около того.