Salidas incorrectas en la entidad VHDL

4

Tengo una lección sobre VHDL en una de mis clases universitarias y tengo que escribir entity simple que generará reloj desde una fuente de 1MHz. Estoy usando CoolRunner-II CPLD Starter Kit con ISE Webpack 13.1.

Cuando ejecuto la simulación de mi código, tengo resultados extraños. No tengo ni idea, dónde está el problema. Mi entidad VHDL tiene este aspecto:

entity clock is
  Port ( clk_in : in  STD_LOGIC;
    clk_1M : out  STD_LOGIC;
    clk_500k : out  STD_LOGIC;
    clk_100k : out  STD_LOGIC;
    clk_1k : out  STD_LOGIC;
    clk_1hz: out STD_LOGIC);
end clock;

La entrada es una señal de 1 MHz desde el oscilador y quiero crear una señal de salida de 1 MHz, 500 kHz, 100 kHz, 1 kHz y 1 Hz. Definí varias señales:

signal c100k: std_logic_vector(3 downto 0) := (others => '0' );
signal c1k:  std_logic_vector(9 downto 0) := (others => '0' );
signal c1hz: std_logic_vector(9 downto 0) := (others => '0' );
--
signal c500k_out: std_logic := '0';
signal c100k_out: std_logic := '0';
signal c1k_out: std_logic := '0';
signal c1hz_out: std_logic := '0';

Y finalmente, mi código es:

process (clk_in) begin
  if clk_in'event and clk_in = '1' then
    -- 500kHz
    c500k_out <= not c500k_out;
  end if;
end process;

process (clk_in) begin
  if clk_in'event and clk_in = '1' then
    -- 100kHz
    c100k <= c100k + '1';
    if c100k = X"A" then
      c100k <= (others => '0' );
      c100k_out <= '1';
    else
      c100k_out <= '0';
    end if;
  end if;
end process;

--
-- Code for 1kHz and 1Hz is same as 100kHz
--

clk_1M <= clk_in;           -- Clock source 1Mhz
clk_500k <= c500k_out;  -- Clock source 500kHz
clk_100k <= c100k_out;  -- Clock source 100kHz
clk_1k <= c1k_out;      -- Clock source 1kHz
clk_1hz <= c1hz_out;        -- Clock source 1Hz

Cuando ejecuto la simulación, obtuve resultados impares:

¿Qué está mal con mi código?

    
pregunta vasco

4 respuestas

3

Lo primero que veo, que probablemente no esté causando tu problema, es la falta de cualquier tipo de reinicio. ModelSim no declara automáticamente que todas las señales sean '0', y tratar de decir s < = no s cuando s no es 1 o 0 no le dará lo que quiere. Los veo declarándolos a todos '0' en la parte superior, pero un circuito adecuado tendría una entrada de restablecimiento que manejará brevemente al inicio de su simulación.

Su proceso de contador básico se ve mal; Básicamente, cuando el conteo llega a diez, se está emitiendo un '1' y durante los otros 10/10 del tiempo se está emitiendo un '0' (para el ejemplo de 100 k, el ejemplo de 1Hz sería un pulso de 1us alto y un 999us Tiempo bajo. Creo que lo que quieres es algo como esto:

gen_clk100: process(clk, rst)
begin
    if rising_edge(clk) then
        if count = 10 then
            clk100 <= not clk100;
            count <= 0;
        else
            count <= count + 1;
        end if;
    end if;

    if rst = '1' then
        clk100 <= '0';
        count <= 0;
    end if;
end process;

Note varias cosas:

  • No estoy incrementando todo el tiempo. Incremento si el conteo no está al máximo, e incremento de lo contrario.

  • Estoy alternando el reloj de salida cuando se alcanza el conteo máximo

  • He incluido un reinicio asíncrono (con borrado sincrónico): esto garantiza que sus señales se inicialicen correctamente y no tengan problemas de metastabilidad cuando se libere el reinicio.

También mencionas que las otras secciones son iguales. Creo que tienes un problema con varios controladores, como mencionó Yann. Verifique y vuelva a verificar su código para asegurarse de que no está asignando la salida en dos procesos diferentes, porque eso es exactamente lo que la simulación dice que está haciendo. Es mejor hacer un módulo de contador genérico o ...

¿Por qué tantos contadores? Todos los divisores de frecuencia se pueden manejar con un solo conteo y luego "eliminando" las condiciones para hacer las divisiones que le interesan. También puede tener un solo contador y usar el operador mod (módulo) para manejar cada divisor caso.

Finalmente, también usaría tipos reales o enteros para el recuento en lugar de std_logic_vector s, pero eso es solo yo.

    
respondido por el akohlsmith
3

Está asignando señales clk_1M, clk_500k, clk_100k, clk_1k y clk_1hz en diferentes procesos en el banco de pruebas. Al mismo tiempo, usted ha creado una instancia de su DUT que (como sugiere Yann Vernier) conduce las mismas señales. Descomente los procesos del banco de pruebas (a excepción de clk_in!) Y estará bien.

Además, le aconsejaría que agregue una señal de reinicio asíncrono a la entidad de reloj para que sea sintetizable.

    
respondido por el Per E
2

Tienes varios drivers. No se muestran en los fragmentos de código publicados, pero son obvios en los archivos que no están en un fragmento .

Mirando el archivo test_clock.vhd, crea una instancia de su unidad bajo prueba. En el mapa de puertos, asigna una salida de reloj () a clk_1M. Más tarde, tienes este fragmento de código:

clk_1M_process :process
   begin
        clk_1M <= '0';
        wait for clk_1M_period/2;
        clk_1M <= '1';
        wait for clk_1M_period/2;
   end process;

Este código también asigna un valor a clk_1M; por lo tanto, tiene varios controladores en sus señales.

Otras señales tienen problemas similares, por lo que no las revisaré aquí.

    
respondido por el user3624
1

No lo veo en los fragmentos de código, pero la simulación se parece mucho a que tienes varios controladores para algunas señales. Cuando están de acuerdo, obtienes un nivel lógico, pero siempre que no estén de acuerdo, obtienes X, un conflicto en la simulación, que probablemente no sea sintetizable (si lo fuera, significaría un cortocircuito). Una suposición es que es posible que haya cometido un error en algún lugar al copiar el proceso de división del reloj y que un componente que podría crear una instancia le serviría bien.

    
respondido por el Yann Vernier

Lea otras preguntas en las etiquetas