Usando la señal en diferentes módulos vhdl

2

Estoy intentando conectar un microcontrolador (cortex m3) y un fpga (actel a3p060). Soy capaz de leer / escribir con éxito con el bus de datos de 16 bits. Mis módulos en vhdl están estructurados de la siguiente manera:

  1. Módulo superior (interfaz con el controlador)
  2. sub módulo donde tengo un divisor de frecuencia.

La idea es generar diferentes frecuencias alimentadas por el controlador al fpga. En el módulo principal, estoy pasando una señal llamada como Load_Divider que se verificará en el módulo divisor de frecuencia de la siguiente manera:

process(Load_Division)
if(Load_Division='1')
   Data_Buffer<=DataBus;
   Load_Divider <='0';
end if;
end process;

if(Counter = X"0000") then
   Counter <= Data_Buffer; //reloading counter

Y en el módulo principal:

case Address is
   "00100"=>Load_Divider <='1'; // generating load signal when proper address is found

Pero lo que sucede es que mi Load_Divider no va a "0" cuando se maneja desde el módulo secundario.

¿No es posible conducir una señal desde dos módulos?

    
pregunta badz

3 respuestas

2

Es posible conducir una señal desde dos módulos.

Sin embargo, no es sencillo; los dos módulos tienen que cooperar: si uno acciona '1' y el otro '0' al mismo tiempo, ha creado un cortocircuito en la fuente de alimentación y puede dañar el dispositivo. En la simulación, afortunadamente, ¡los resultados son menos dramáticos!

Dos formas de hacerlo; y la razón para no usar ninguno de ellos dentro de un FPGA.

La primera forma es el "Y cableado" tradicional, donde hay un '1' débil conectado permanentemente a la señal. Tradicionalmente esta era una resistencia conectada a + 5V; en VHDL puede decir Load_Divider <='H'; en el diseño de nivel superior. H y L son versiones débiles de '1' y '0'.

Ahora todos los controladores pueden bajarlo o apagarlo

if condition then 
   Load_Divider <='0';
else
   Load_Divider <='Z';
end if;

('Z' significa el estado de alta impedancia Z o alta, es decir, apagar el controlador).

Si TODOS los módulos manejan Z, la salida es 'H' (igual a '1').

La segunda forma se llama un bus tri-estatal. Aquí cualquiera de los módulos puede conducir 0, 1 o Z en el bus. Sin embargo, usted, el diseñador, DEBE asegurarse de que cuando un módulo esté manejando '0' o '1', TODOS los otros módulos estén manejando 'Z', para evitar el cortocircuito y los daños mencionados anteriormente. Eso requiere la cooperación de todos los módulos de alguna manera:

if my_turn then 
   Load_Divider <= my_signal;   -- 0 or 1
else
   Load_Divider <='Z';
end if;

Cualquiera de estas técnicas son formas válidas de comunicarse entre FPGA separados y otros chips (memorias, CPU) en su tablero. Pero dentro de un FPGA no hay señales de tri-estado (solo en sus pines de E / S), por lo que si utiliza cualquiera de las técnicas anteriores, las herramientas de síntesis lo convierten en una señal equivalente sin los tri-estados.

Por ejemplo, la primera técnica (cableada-AND) podría traducirse a

Load_Divider_1 <= '0';   -- module 1
Load_Divider_2 <= '1';   -- module 2
Load_Divider <= Load_Divider_1 and Load_Divider_2;

donde puede ver que cada señal tiene un solo controlador. Entonces, ¿por qué no escribir eso en primer lugar?

    
respondido por el Brian Drummond
1

Cuando necesito hacer esto, cada módulo tiene su propia señal separada, luego hago lo que quiera en el módulo de nivel superior.

Algo como

signal sig_a, sig_b, sig_final: std_logic;

foo_a: entity foo PORT MAP (
    clk => clk,
    rst => reset,
    out => out_a
    );

foo_b: entity foo PORT MAP (
    clk => clk,
    rst => reset,
    out => out_b
    );

-- for active-high, use or:
sig_final <= sig_a or sig_b;

-- for active-low, use and;
sig_final <= sig_a and sig_b;

-- if you have to override bad entity logic:
sig_final <= sig_a or sig_b when reset = '0' else '0';

-- if you have something really complex and that has to be registered:
determine_sig: process(clk, reset)
begin
    if reset = '1' then
        sig_final <= '0';
    else if rising_edge(clk) then
        -- do something wild and wooly based on sig_a, sig_b, state variables, phase of the moon, etc.
    end if;
end process;
Las señales

son baratas y le permiten ser explícito con su código. Casi nunca hay necesidad de revolcarse con conductores fuertes y débiles, y NUNCA utilice el estado de alta impedancia ('Z') para señales internas.

    
respondido por el akohlsmith
1

Puedes tener múltiples drivers de una señal. Sin embargo, debe proporcionar una función de resolución para la señal que determina cuál es la salida si más de una fuente controla la misma señal al mismo tiempo.

Normalmente, definiría una función de resolución en un paquete y luego incluiría el paquete en ambos módulos. El ejemplo más citado es el de std_logic en el paquete std_logic_1164 que puede verse aquí . Ese ejemplo es probablemente un poco más complejo de lo que necesitas. Un ejemplo más simple sería un AND:

package my_package is
    function wired_and (input : std_logic_vector) return std_logic;
end my_package;

package body my_package is
    function wired_and (input : std_logic_vector) return std_logic is
        --setting this to '1' ensures that even if there is only one
        --driver, the AND will output the correct value
        variable output : std_logic := '1';

    begin
        --AND each input driver with all of the others
        for i in input'range loop
            output := output and input(i);
        end loop;

        return output;
    end wired_and;
end my_package;

La función toma una matriz, el std_logic_vector llamado input , que contiene todos los controladores múltiples. Y genera un solo bit, el std_logic llamado output .

En lugar de usar esto para asignar un valor a su señal:

Load_Divider <= '0';

Usted usaría esto:

Load_Divider <= wired_and('0');

Aunque eso puede ser un poco molesto y puede ser propenso a errores. En general, es más fácil declarar un subtype que utiliza automáticamente la función de resolución como esta:

subtype my_type is wired_and std_logic;

Y declara tu señal así:

signal Load_Divider : my_type;

De esa manera, siempre que haya múltiples controladores de esa señal (incluso si hay más de dos en el ejemplo anterior), se llamará automáticamente a la función de resolución y se emitirá el valor apropiado.

    
respondido por el embedded.kyle

Lea otras preguntas en las etiquetas