Divisor de reloj VHDL

1

Creé un divisor de reloj con el siguiente código. Seguí los pasos en el libro del profesor chu.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity clock_divider is
Port ( reset : in  STD_LOGIC;
       clk : in  STD_LOGIC;--Clock in
       out_red : out  STD_LOGIC);--Reduced freq clock out
end clock_divider;

architecture Behavioral of clock_divider is

constant DVSR : INTEGER := 5000000;--for 1 ms tick at 50mhz clk input
signal ms_reg, ms_next : unsigned (22 downto 0);
signal ms_tick : std_logic;--tick at every 1ms

begin

process (clk)
begin
  if (clk'event and clk = '1') then
    ms_reg <= ms_next;
  end if;
end process;

ms_next <= 
       (others => '0') when (reset = '1' or ms_reg = DVSR) else
          ms_reg + 1;

ms_tick <= 
       '1' when ms_reg = DVSR else '0';

out_red <= ms_tick;
end Behavioral;

out_red es mi reloj de frecuencia reducido. Banco de pruebas muestra clock_out colgando a 0. ¿Alguien puede averiguar dónde me equivoqué?

    
pregunta Chanuka Perera

3 respuestas

1

Su código funciona si inicia DVSR a 50000 en lugar de 5000000. Generará un pulso cada 1 ms con un ancho de período de clk, esto será 0.000 ... 01% alto y 99.99..99% bajo Para generar un reloj con 50% de altura, 50% de baja, haría lo siguiente.

library ieee;
use ieee.std_logic_1164.all;

entity clock_divider is

  generic (
    divider : positive := 50000);       -- for 1 ms tick at 50mhz clk input

  port (
    reset, clk : in  std_logic;         -- reset and clock in
    out_red    : out std_logic);        -- Reduced freq clock out
end entity clock_divider;

architecture implementation of clock_divider is
 signal ClockDiv : natural range 0 to divider/2 := 0;    -- clock divide counter
 signal clk_out  : std_logic;
begin  -- architecture implementation

 clock_div_p : process (clk, reset) is

 begin  -- process clock_div_p
   if reset = '1' then                 -- asynchronous reset (active high)
     ClockDiv <= 0;
     clk_out  <= '0';
   elsif clk'event and clk = '1' then  -- rising clock edge
     if (ClockDiv = divider/2) then    -- switch polarity every half period
       ClockDiv <= 0;
       clk_out  <= not clk_out;
     else
       ClockDiv <= ClockDiv +1;
       clk_out  <= clk_out;
     end if;
   end if;
 end process clock_div_p;

 out_red <= clk_out;

end architecture implementation;
    
respondido por el user36399
0

Asegúrese de tener el número correcto de bits en sus variables con una declaración:

assert 2**ms_reg'length > DVSR report "Insufficient bits in ms_reg" severity failure;

O, use un tipo natural para almacenar sus señales ms_reg y ms_next (suponiendo que los 32 bits definitivamente serán suficientes) - deje que el compilador se preocupe por cuántos bits asignar - el optimizador puede extraer ese hecho de la Lógica (en mi experiencia).

    
respondido por el Martin Thompson
-1

No puedes incrementar std_logic_vector directamente. Debe convertirlo en entero, incrementar el entero y volver a convertir todo en un proceso.

Necesitas la biblioteca ieee.numeric_std. Luego, en un proceso de conversión a entero:

to_integer(unsigned(S));

y de vuelta a std_logic_vector:

std_logic_vector(to_unsigned(num, len));

También debo señalar que esto parece un mal diseño. No debes poner la lógica en el camino de una señal de reloj. En los FPGA, por ejemplo, hace que se produzcan pequeños pulsos (unos pocos ps), lo que puede activar su lógica síncrona y hacer que se cargue un estado indefinido en los flip-flops. En su lugar, debe usar un PLL para generar sus diversas señales de reloj.

    
respondido por el user2534517

Lea otras preguntas en las etiquetas