¿Por qué no funciona mi simple contador VHDL? ¿A dónde fueron mis señales?

3

Soy un principiante completo con VHDL y casi un principiante con lógica digital y tengo un problema para leer un libro que estoy leyendo. En particular, un ejercicio solicita construir un contador con una habilitación y un interruptor de reinicio. Lo implementé de una manera y el compilador (Xilinx ISE) se quejó de ello lo suficiente como para tomar el camino de menor resistencia y cambiarlo a algo que pensé que era subóptimo. Pero ahora me gustaría saber qué está mal con mi código original.

Aquí está el ejemplo 'trabajando':

-- EXAMPLE 1
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity clocks is
    Port ( 
           switch0 : in  STD_LOGIC;
           switch1 : in  STD_LOGIC;
           LEDs : out  STD_LOGIC_VECTOR (7 downto 0);
           clk  : in STD_LOGIC
           );
end clocks;

architecture Behavioral of clocks is
 signal counter : STD_LOGIC_VECTOR( 29 downto 0 ) := ( others => '0' );
begin

LEDs <= counter( 29 downto 22 );

clk_proc: process( clk, switch1, switch0 )
    begin
        if rising_edge( clk ) then
            if switch0 = '1' then
                counter <= counter + 1;
            elsif switch1 = '1' then
                counter <= ( others => '0' );
            end if;
        end if;
    end process;

end Behavioral;

Básicamente, establece el interruptor 0 y el contador comienza a contar. Borrar el switch0 y deja de contar. Establezca el switch1 mientras el switch0 está despejado y el contador se reiniciará a 0. Establezca el switch1 mientras el switch0 esté configurado y el contador no se reinicie.

Lo que realmente quería era que el interruptor de reinicio1 pudiera borrar el contador incluso si se configuraba el interruptor0. Quería que el flanco ascendente del interruptor de reinicio1 restableciera el contador de nuevo a 0, mientras que el contador sigue subiendo si el interruptor de habilitación 0 aún está configurado.

Pensé que podría acercarme un poco más cambiando el proceso a esto:

-- EXAMPLE 2
clk_proc: process( clk, switch1, switch0 )
    begin
        if rising_edge( clk ) then
            if switch1 = '1' then
                counter <= ( others => '0' );
            elsif switch0 = '1' then
                counter <= counter + 1;
            end if;
        end if;
    end process;

Pero, extrañamente, en el chip Spartan 6 que estoy usando, ¿el interruptor de habilitación0 sigue anulando el interruptor de reinicio1? Entonces intenté esto:

-- EXAMPLE 3
clk_proc: process( clk, switch1, switch0 )
    begin
        if rising_edge( switch1 ) then
            counter <= ( others => '0' );
        else
            if rising_edge( clk ) then
                if switch0 = '1' then
                    counter <= counter + 1;
                end if;
            end if;
        end if;
    end process;

Este debería ser exactamente lo que quiero, pero Xilinx ISE está aún menos satisfecho con esto: recibo estas advertencias del compilador:

WARNING:Xst:647 - Input <switch0> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved. 
WARNING:Xst:647 - Input <clk> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:Xst:2404 -  FFs/Latches <counter<1:30>> (without init value) have a constant value of 0 in block <clocks>. 
WARNING:Par:288 - The signal clk_IBUF has no load.  PAR will not attempt to route this signal. 
WARNING:Par:288 - The signal switch0_IBUF has no load.  PAR will not attempt to route this signal. 
WARNING:Par:288 - The signal switch1_IBUF has no load.  PAR will not attempt to route this signal. 
WARNING:Par:283 - There are 3 loadless signals in this design. This design will cause Bitgen to issue DRC warnings.

switch0 nunca se usa? Tampoco es clk? ¿A dónde fueron? Y cuando lo ejecuté en mi Spartan 6, hizo lo mismo que el ejemplo 'de trabajo'. Intenté esto también:

-- EXAMPLE 4
clk_proc: process( clk, switch1, switch0 )
    begin
        if rising_edge( switch1 ) then
            counter <= ( others => '0' );
        end if;
        if rising_edge( clk ) then
            if switch0 = '1' then
                counter <= counter + 1;
            end if;
        end if;
    end process;

Esto ni siquiera se integrará en la implementación. Recibo estas advertencias / errores:

WARNING:Xst:647 - Input <clk> is never used. This port will be preserved and left unconnected if it belongs to a top-level block or it belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:Xst:3002 - This design contains one or more registers/latches that are directly
   incompatible with the Spartan6 architecture. The two primary causes of this is
   either a register or latch described with both an asynchronous set and
   asynchronous reset, or a register or latch described with an asynchronous
   set or reset which however has an initialization value of the opposite 
   polarity (i.e. asynchronous reset with an initialization value of 1).

¿Alguien me puede dar una idea de qué se trata de estos procesos re-trabajados que no son kosher? Entiendo que hay muchas cosas que se pueden codificar en VHDL pero que no se pueden traducir a un diseño de hardware, y la segunda de mis revisiones parece caer en esa categoría, pero ¿puede alguien explicarme lo que está pasando aquí? ? ¿Qué pasa con un pestillo con restablecimientos async y conjuntos? ¿Qué hay de malo con los bloques anidados if-then-end? ¿Qué estoy haciendo mal aquí?

ACTUALIZACIÓN: como en la respuesta, los ejemplos 3 y 4 nunca podrían haber funcionado porque un proceso no puede cronometrarse varias veces; solo puede tener una señal con un evento rising_edge () o 'en él. Resulta que el ejemplo 2 realmente funciona y hace lo que yo quiero que haga. Lo pasé por el simulador y me pareció bien, y cuando lo sinteticé nuevamente para el hardware, funcionó bien en mi Spartan 6. ¿Debo haber hecho algo extraño la primera vez que lo probé?

    
pregunta Ted Middleton

1 respuesta

6

el parámetro rising_edge () es solo para señales de reloj. Una opción sería la siguiente:

clk_proc: process( clk, switch1, switch0 )
begin
    if switch1 = '1' then
        counter <= ( others => '0' );
    elseif rising_edge( clk ) then
        if switch0 = '1' then
            counter <= counter + 1;
        end if;
    end if;
end process;

Esto se conoce como un proceso de reinicio asíncrono, lo que significa que reiniciará el contador siempre que el reinicio (switch1) sea alto, independientemente del estado del reloj. Un proceso de restablecimiento sincrónico se vería igual que su segundo ejemplo:

clk_proc: process( clk, switch1, switch0 )
begin
    if rising_edge( clk ) then
        if switch1 = '1' then
            counter <= ( others => '0' );
        elsif switch0 = '1' then
            counter <= counter + 1;
        end if;
    end if;
end process;

Sin embargo, dijiste que tu segundo ejemplo no funcionó como se esperaba. Mi sospecha es que esto se debe a que las señales que lo activan son conmutadores en lugar de señales lógicas sincronizadas. Los interruptores en realidad no cambian instantáneamente, sino que se activan y desactivan varias veces antes de establecerse. Necesita implementar algún tipo de proceso de rebote para producir una señal que esté sincronizada con su reloj y que pueda controlar su temporizador.

También vale la pena mencionar que el diseño de FPGA es lot más fácil si simulas cosas primero. Xilinx ISE incluye un simulador: ¡crea un banco de pruebas y úsalo! Eso le permite ver fácilmente lo que está sucediendo en su implementación antes de que se acerque al hardware.

    
respondido por el LeoR

Lea otras preguntas en las etiquetas

Comentarios Recientes

El depurador simple le permite capturar su señal, pero NO la pasa a la base de datos. SQL Server proporciona su transmisor de red y retransmite o restablece las bibliotecas DBX de forma predeterminada. Utilizando esos, puede pasar las señales a través de su aplicación incluso si su aplicación no es compatible con ese entorno. ¿Qué pasa si los objetos están en formato DBX, con el% de constantes NDB establecido en lo que se llama un enlace de 32 o 64 bits? Hace mucho tiempo que pensamos en lo que se requiere para... Lees verder