¿Cómo crear un contador para mostrar 6 dígitos usando ánodos?

3

Estoy tratando de escribir un reloj digital en vhdl para un fpga que se ejecute en 100 mhz. Puedo escribirlo en 4 ánodos al crear un contador como se muestra a continuación (conteo 1 = 249999), los dígitos parecen bastante claros. Sin embargo, cuando quiero mostrar la hora en el formato HH: MM: SS (cuando quiero usar 6 ánodos en lugar de 4), no pude mostrar los dígitos claramente. Cuando incremento mucho el valor de count1, los LED comienzan a parpadear, cuando disminuyo el valor de count1, los dígitos parecen difíciles de identificar.

¿Hay alguna forma teórica de determinar este valor de contador (contador1)? ¿Es posible mostrar 6 dígitos claramente en la forma en que lo estoy intentando?

Gracias desde ahora.

el código responsable de mostrar 4 ánodos:

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;

la salida (como quería):

el código responsable de mostrar 6 ánodos (los dígitos no son claros para leer):

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;

la salida (los dígitos no son como yo quería, algo se ve mal con el contador de pantalla):

    
pregunta ErenL

3 respuestas

1

Esta es una limitación inherente de la multiplexación: dado que solo está manejando un solo dígito a la vez, su pantalla se debilita a medida que aumenta el número de dígitos. Sin embargo, deberías poder manejar 8 dígitos bien.

Intentaré ajustar su contador explícitamente para asegurarme de que maneja un dígito específico en un momento dado:

    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;
    
respondido por el Dmitry Grigoryev
2

Parece que en el código de 6 dígitos tiene un ciclo A_COUNTER continuamente, lo que significa que hay al menos 2 estados, el estado 6 y el estado 7, que no se descodifican explícitamente. Intente apagar explícitamente todos los segmentos para los estados 6 y 7. Si A_COUNTER tiene más de 3 bits, deberá averiguar qué sucede en la pantalla cuando A_COUNTER no es de 0 a 5.

Dado que las habilitaciones de la pantalla están activas en nivel bajo (0 = activado), es probable que todos los segmentos se activen de forma predeterminada cuando no se les dice que se desactiven, como puede ocurrir en los estados 6 y 7.

Como enfoque de diagnóstico, tal vez puedas aumentar COUNT1 tan grande que los dígitos cambien extremadamente lentamente, para que puedas ver los pasos de iluminación en cámara lenta.

No estoy seguro de que haya casos adicionales 6 y 7. Pero como los 2 dígitos no utilizados (extremo izquierdo) están encendidos con todos los segmentos encendidos, parece que algunos dígitos / segmentos están encendidos de manera predeterminada si no enciende apagar. Si solo hay 6 casos, y 1 dígito está habilitado para cada uno, entonces no debe haber tiempo para que estén encendidos los dígitos 6 y 7, pero están activados. Creo que tanto la fila como el segmento están recibiendo (00000000,00000000) de forma predeterminada durante un breve intervalo y activando todos los dígitos y todos los segmentos.

Pruebe esto generando valores de habilitación de dígitos con 8 dígitos binarios (11xxxxxx) en lugar de 6 (xxxxxx), de modo que los 2 dígitos superiores no utilizados estén apagados. Los 2 dígitos más a la izquierda serán más tenues, pero aún parcialmente iluminados.

    
respondido por el Entrepreneur
1

Hay algunos problemas con tu código que te sugiero que corrijas para simplificar la depuración. En primer lugar, ha duplicado la decodificación del [cátodo] del cátodo varias veces (esto solo debe hacerse una vez), sugeriría un proceso que tenga el dígito decimal actual como una señal en la lista de sensibilidad y establezca los segmentos. El proceso principal impulsado por el reloj sería mucho más simple sin la decodificación duplicada. En la práctica, las herramientas de síntesis probablemente mapearán de manera eficiente dicha decodificación a una tabla de bucle de RAM en el FPGA; es posible que no puedan hacer eso con su código, por ejemplo,

El enrutamiento principal accionado por el reloj luego realiza ciclos redondos configurando la señal decimal apropiada y la señal de ánodo. Mi enfoque sería iniciar la salida del ánodo a "111110" y cambiar cíclicamente esta izquierda en cada ciclo de reloj en el proceso cronometrado y poner en lógica para configurar la señal de dígitos apropiada para mostrar.

Lo que no está claro es qué reloj está usando para conducir este proceso. Probablemente no debería estar a 100 MHz o menos del reloj del sistema si se encienden los LED: sugeriría ejecutarlo a aproximadamente 1 kHz o así.

    
respondido por el John

Lea otras preguntas en las etiquetas