¿Es normal que un divisor de reloj hecho con el contador de johnson en anillo tenga un aumento momentáneo cuando cambie el período?

2

He hecho un divisor de clk usando un contador de johnson de anillo con D flip flop en VHDL. El punto es que la salida de la señal hace un aumento momentáneo e inesperado durante un cambio de período. Como puede ver en el círculo rojo, hay un aumento momentáneo cerca del cambio de período que no puedo explicar: Además,apuntandoconelcursorenesasubida,modelsimnopercibe1enelcuadrodelaizquierda.Yestohacequetodoseamásextraño.

Elsiguienteeselcódigo:

libraryieee;useieee.std_logic_1164.all;useieee.std_logic_arith.all;useieee.std_logic_unsigned.all;entityeven_dividerisport(clk:instd_logic;divide_by:instd_logic_vector(4downto0);out_clk:outstd_logic);endeven_divider;architectureeven_divider_behaviourofeven_dividerissignalfiloFlottante:std_logic;componentMultiplexer_VHDLisport(due,quattro,sei,otto,dieci,dodici,quattordici,sedici:instd_logic;Sel:instd_logic_vector(4downto0);Output:outstd_logic);endcomponent;componentffdisport(clk:instd_logic;din:instd_logic;reset:instd_logic;dout:outstd_logic);endcomponent;signaldInternal:std_logic_vector(7downto0);signaldFirst:std_logic;signalreset:std_logic;signalresetN:std_logic;signalring_wire:std_logic;signalselection:std_logic_vector(4downto0);beginprocess(clk,divide_by)beginifdivide_by'eventthen--selection<="11111";
    reset <= '1';
    ring_wire <= dFirst;
    selection <= divide_by;
else
    selection <= divide_by;
    ring_wire <= dFirst;
    reset <= '0';
end if;
end process;
f0 : ffd port map(clk, ring_wire, reset, dInternal(0));
f1 : ffd port map(clk, dInternal(0), reset, dInternal(1));
f2 : ffd port map(clk, dInternal(1), reset, dInternal(2));
f3 : ffd port map(clk, dInternal(2), reset, dInternal(3));
f4 : ffd port map(clk, dInternal(3), reset, dInternal(4));
f5 : ffd port map(clk, dInternal(4), reset, dInternal(5));
f6 : ffd port map(clk, dInternal(5), reset, dInternal(6));
f7 : ffd port map(clk, dInternal(6), reset, dInternal(7));
multiplexer : Multiplexer_VHDL port map(dInternal(0), dInternal(1), dInternal(2),     dInternal(3), dInternal(4), dInternal(5), dInternal(6), dInternal(7), selection, dFirst);
out_clk <= not dFirst;
end even_divider_behaviour;

El siguiente es el código D flip flop:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity ffd is
    port(
        clk : in std_logic;
        din : in std_logic;
        reset : in std_logic;
        dout : out std_logic
    );
end ffd;

architecture ffd_behaviour of ffd is
begin
process(clk, reset)
variable qvar : std_logic := '0';
begin
    if rising_edge(reset) then
        qvar := '0';
    elsif rising_edge(clk) then
        qvar := din;
    end if;
dout <= qvar;
end process;
end ffd_behaviour;

El siguiente es el código del multiplexor:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Multiplexer_VHDL is
   port
   (
      due, quattro, sei, otto, dieci, dodici, quattordici, sedici : in std_logic; 
      Sel : in std_logic_vector(4 downto 0);

      Output : out std_logic
   );
end entity Multiplexer_VHDL;


architecture Behavioral of Multiplexer_VHDL is
begin 
   process (due, quattro, sei, otto, dieci, dodici, quattordici, sedici, Sel) is
   begin
      case Sel is
         when "00010"  => Output <= not due;
         when "00100"  => Output <= not quattro;
         when "00110"  => Output <= not sei;
         when "01000"  => Output <= not otto;
         when "01010"  => Output <= not dieci;
         when "01100"  => Output <= not dodici;
         when "01110"  => Output <= not quattordici;
     when "10000"  => Output <= not sedici;
         when others => Output <= '0';
      end case;
   end process;
end architecture Behavioral;

El siguiente es el código de banco de pruebas:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;


entity even_dividerTB is

end even_dividerTB;

architecture even_dividerTB_behaviour of even_dividerTB is
component even_divider is
    port(
        clk : in std_logic;
        divide_by : in std_logic_vector(4 downto 0);
        out_clk : out std_logic
    );
end component;
signal clk : std_logic;
signal divide_by : std_logic_vector(4 downto 0);
signal out_clk : std_logic;
--signal dExternal_out : std_logic_vector(7 downto 0);
begin
process
begin
clk <= '0'; wait for 10 ns;
clk <= '1'; wait for 10 ns;
end process;
process
begin
divide_by <= "01000"; wait for 300 ns;
divide_by <= "00010"; wait for 300 ns;
end process;
ed : even_divider port map(clk, divide_by, out_clk);
end even_dividerTB_behaviour;
    
pregunta StackUser

1 respuesta

3

El simulador le está mostrando que tiene un problema potencial.

Para cada uno de sus pasos de tiempo internos, el simulador evalúa un evento de cambio de señal a la vez y repite las evaluaciones hasta que todas las señales alcancen un valor estable.

Cuando cambia la entrada de selección en su multiplexor, el simulador evalúa los 5 bits por separado y, al hacerlo, descubrió que la salida cambia de estado más de una vez. Esto lo indica al mostrar un pulso de "ancho cero" en la pantalla de salida. Dado que esta salida transitoria no persistió después de que se realizaron todas las evaluaciones para ese paso de tiempo, no representa un cambio de señal real.

En una implementación física real, con retrasos de puerta variables y sesgos variables entre las múltiples señales de un bus, puede o no ver un error real. El simulador le está mostrando que hay al menos la posibilidad de un fallo en su diseño.

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas