controladores de señales múltiples VHDL

1

Estoy tratando de aprender buenas metodologías de diseño de vhdl. Estaba tratando de encontrar algunos consejos sobre múltiples controladores de señal. Desafortunadamente sin éxito. Mi pregunta es si es una buena idea tener una señal con varias unidades (o la evitaré casi siempre).

Mi problema: - Tengo algún módulo de transmisión. Me gustaría tener algún indicador (solo por ejemplo, solo uno) que informe que hay nuevos datos. Un proceso establece el indicador si hay nuevos datos disponibles, otro un indicador claro después de leer.

En este caso tengo dos procesos que controlan una señal resuelta. El problema que puedo ver aquí es la concurrencia. ¿Existe un buen patrón de desarrollo para un problema como este? ¿Debo evitar y nunca usar controladores de señal múltiple?

    
pregunta e2p

2 respuestas

1

No puede tener varios controladores para una señal determinada

A partir de su descripción, parece que está tratando de resolver algún tipo de apretón de manos entre sus dos procesos. Si bien puede haber una solución más elegante, sin haber visto su código, supongamos que realmente necesita un protocolo de enlace. Incluso si no lo necesita ahora, puede hacerlo más tarde.

Para ayudar a la discusión, modelaré el comportamiento utilizando dos componentes (o entidades) en lugar de procesos, para que el diagrama sea más claro.

Suponga que tiene una entidad que recibe datos y otra que procesa los datos. También suponga que solo desea recibir datos nuevos mientras el procesador está inactivo (es decir, ha terminado de trabajar en el último conjunto de datos).

Para esto, necesitarás un apretón de manos. La primera entidad (llámela data_memory ) necesita saber cuándo data_processor es idle , y data_processor necesita saber cuándo la memoria tiene data_rdy .

Esto se parece a tu publicación:

  

Me gustaría tener algún indicador (solo por ejemplo, uno) que informe que hay nuevos datos. Un proceso establece el indicador si hay nuevos datos disponibles, otro un indicador claro después de leer. [sic]

Aquí tenemos un indicador data_rdy que se establece cuando hay nuevos datos disponibles y se borra una vez que se lee y procesa:

Paralainstanciadedata_memory,solopodemossincronizarlosdatosdirectamentedesdedata_inaldata_processorsiemprequelahabilitacióndeescriturawrenseaalta.Elindicadordata_rdylepermitealprocesadorsabercuándolosnuevosdatosestánlistosyenespera.

--data_memory.vhdlibraryieee;useieee.std_logic_1164.all;entitydata_memoryisport(data_in:instd_logic_vector(7downto0);wren:instd_logic;rdy_read:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);data_rdy:outstd_logic);enddata_memory;architectureBehavioralofdata_memoryisbeginprocess(clk)beginif(rising_edge(clk))thenif(wren='1')then--inpractice,wewouldaddaqueueheredata_out<=data_in;endif;data_rdy<=wrenandrdy_read;endif;endprocess;endBehavioral;

Elprocesadordedatosluegousalosdatoscuandolaseñaldata_rdyesalta:

--data_processor.vhdlibraryieee;useieee.std_logic_1164.all;entitydata_processorisport(data_in:instd_logic_vector(7downto0);data_rdy:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);idle:outstd_logic);enddata_processor;architectureBehavioralofdata_processorissignalprocess_wait_cycle:std_logic_vector(63downto0):=(others=>'1');beginprocess(clk)beginif(rising_edge(clk))thenif(data_rdy='1')then--inpractice,wewouldactuallydosomethingwiththedata;--herewe'lljustmakeacopyandsenditoutdata_out<=data_in;process_wait_cycle<=(others=>'0');idle<='0';elseprocess_wait_cycle<=process_wait_cycle(62downto0)&'1';idle<=process_wait_cycle(63);endif;endif;endprocess;endBehavioral;

Elregistrodedesplazamientoprocess_wait_cycleseusaaquísolocomounmedioparaconsumiralgunosciclosderelojparasimularuntiempodeprocesamiento.Cuandosecompletaelprocesamiento,laentidadestableceelindicadoridlealto,queluegovuelvealaentradadelbloquedata_memory.

Finalmente,podemosunirestosdosenunainstanciadenivelsuperior:

--transmission.vhdlibraryieee;useieee.std_logic_1164.all;entitytransmissionisport(data_in:instd_logic_vector(7downto0);wren:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);data_status:outstd_logic);endtransmission;architectureBehavioraloftransmissionis--Componentdata_memorycomponentdata_memoryisport(data_in:instd_logic_vector(7downto0);wren:instd_logic;rdy_read:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);data_rdy:outstd_logic);endcomponent;--Componentdata_processorcomponentdata_processorisport(data_in:instd_logic_vector(7downto0);data_rdy:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);idle:outstd_logic);endcomponent;--Signalssignaldata_rdy:std_logic:='0';signalprocessor_ready:std_logic:='0';signaldata_from_mem:std_logic_vector(7downto0):=X"00";

begin

    data_status <= data_rdy;

    -- data_memory instance
    data_memory_inst : data_memory
    port map (
        data_in  => data_in,
        wren     => wren,
        rdy_read => processor_ready,
        clk      => clk,
        data_out => data_from_mem,
        data_rdy => data_rdy );

    -- data_processor instance
    data_processor_inst : data_processor
    port map (
        data_in  => data_from_mem,
        data_rdy => data_rdy,
        clk      => clk,
        data_out => data_out,
        idle     => processor_ready );

end Behavioral;

Y simular:

Aquípuedeverquelosdatossoloseusancuandowrenyidlesonaltos,loqueindicaquetantoelprocesadorestáinactivocomosiingresannuevosdatos.

Encasodequeestéinteresadoenelarchivodesimulación:

--Transmissionsimlibraryieee;useieee.std_logic_1164.all;useieee.math_real.all;useieee.numeric_std.all;entitytransmission_simis--Port();endtransmission_sim;architectureBehavioraloftransmission_simiscomponenttransmissionisport(data_in:instd_logic_vector(7downto0);wren:instd_logic;clk:instd_logic;data_out:outstd_logic_vector(7downto0);data_status:outstd_logic);endcomponent;signaldata_in:std_logic_vector(7downto0):=X"AB";
signal wren        : std_logic := '0';
signal clk         : std_logic := '0';
signal data_out    : std_logic_vector (7 downto 0) := X"00";
signal data_status : std_logic := '0';

constant PERIOD : time := 10 ns;
constant DUTY   : real := 0.5;

begin

    uut : transmission
    port map (
        data_in     => data_in,
        wren        => wren,
        clk         => clk,
        data_out    => data_out,
        data_status => data_status );

    process
    begin
        loop
            clk <= '0';
            wait for (PERIOD - (PERIOD * DUTY));
            clk <= '1';
            wait for (PERIOD - (PERIOD * DUTY));
        end loop;
    end process;

    process
        variable seed1, seed2: positive;
        variable rand: real;
        variable range_of_rand : real := 255.0;
    begin
        wait for (PERIOD*10);
        wren <= '1';
        wait for (PERIOD*10);
        wren <= '0';
        wait for (PERIOD*10);
        uniform(seed1, seed2, rand);
        data_in <= std_logic_vector(to_unsigned(integer(rand*range_of_rand), data_in'length));
    end process;

end Behavioral;
    
respondido por el Blair Fonville
0

Sí, evita los controladores múltiples.

Puede tener dos señales: una que es alta para un reloj después de datos nuevos y otra que es alta para un reloj después de leer. Luego en un proceso puedes hacerlo

if rising_edge(CLK) then 
    if write_sig = '1' then
        flag <= '1';
    elsif read_sig = '1' then
        flag <= '0';
    end if;
end if;

Depende de usted decidir la prioridad de configurar o borrar la bandera, pero establecer la prioridad en la configuración de la bandera parece ser lo más sensato.

    
respondido por el Ethan

Lea otras preguntas en las etiquetas