Pregunta de VHDL: Ejecución secuencial dentro de un proceso

3

He heredado un código VHDL que necesito extender. Hay una pieza ahí dentro que me parece un error, pero mientras soy un desarrollador de C desde hace mucho tiempo, no tengo experiencia en VHDL. Entiendo que los procesos se ejecutan esencialmente en paralelo, pero dentro de un proceso, ¿importa el pedido? En el siguiente código, un CPLD está recibiendo datos ADC en serie de un microcontrolador. El flujo de datos contiene los resultados de dos conversiones separadas de 8 bits y se está cargando en dos registros, un bit a la vez. Sin embargo, parece que al final de la recepción del primer byte de datos ADC, la MSB de este byte se sobrescribe con la MSB del segundo byte antes de que se cargue en su registro. ¿Es esto un error? He eliminado parte del código para que la muestra sea más legible.

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity CPLD is port(
   ADC_Clk              : in  std_logic;
   ADC_Data             : in  std_logic;
end CPLD;

architecture arch_CPLD of CPLD is
   signal   ADC_Counter : std_logic_vector (7 downto 0);
   signal   ADC_Reg_1   : std_logic_vector (7 downto 0);
   signal   ADC_Temp    : std_logic_vector (7 downto 0);

begin

-- Shift in data from two 8-bit ADC channels
--   ADC_Counter incremented by another process on rising edge of ADC_Clk
ADC_Shift: process(ADC_Clk)
begin
   if (falling_edge(ADC_Clk))  then

      -- Shift in 8 bits from ADC data channel 1
      if    (ADC_Counter = 5 ) then   -- skip over sync bits
            ADC_Temp(7) <= ADC_Data;  -- get MSB of data
      elsif (ADC_Counter = 6 ) then
            ADC_Temp(6) <= ADC_Data;

      -- code omitted for clarity :      getting bits 5 to 1      

      elsif (ADC_Counter = 12 ) then
            ADC_Temp(0) <= ADC_Data;  -- get LSB of data

      -- shift in 8 bits from ADC data channel 2      
      elsif (ADC_Counter = 13 ) then
             ADC_Temp(7) <= ADC_Data; -- BUG? Overwriting MSB with next byte?
             ADC_Reg_1 <= ADC_Temp;   -- first byte of data to Register 1

      elsif (ADC_Counter = 14 ) then  -- continue getting second byte
            ADC_Temp(6) <= ADC_Data;

      -- code omitted for clarity

      end if;
   end if;
end process ADC_Shift;
end arch_CPLD;
    
pregunta Allen Moore

2 respuestas

5

Sin conocer todos los detalles, en principio no es un error. Este es un proceso que ocurre cuando hay un flanco descendente en el reloj asociado. Puedes imaginar que todas las lecturas de señales ocurren justo antes del borde, y todas las escrituras ocurren en el borde.

Por lo tanto, tener dentro de un proceso sincronizado :

a <= b; -- after the edge, a will have the contents of b
c <= a; -- after the edge, c will have the contents of a (NOT THE CONTENTS OF b).

El orden de las asignaciones anteriores no importa, y puede representarse mediante el siguiente esquema:

simular este circuito : esquema creado usando CircuitLab

Como puede ver en el esquema anterior, cada Flip-Flop tiene un valor 'en cola' D y se convierte en la salida Q en el borde del reloj. a tiene b en cola, y c tiene a en cola. Así que en un solo reloj, b no puede propagarse hasta c (requiere 2 ciclos de reloj). Por lo tanto, especificar la señal "en cola" en el código no necesita ningún orden en particular.

En su ejemplo específico, cuando ADC_Counter es 13 , ADC_temp(7) tiene ADC_Data en cola, y ADC_Reg_1 tiene ADC_Temp en cola. ADC_Reg_1 no se está corrompiendo con el nuevo bit de datos, de la misma manera que nuestro c no se corrompe con b .

Nota : esto sería diferente si se habla de variables (estaría usando el operador := en lugar de <= ), pero su código solo contiene señales.

    
respondido por el apalopohapa
2

Si ADC_Temp fuera una variable, tendrías razón. Sin embargo, es una señal, y las señales son el mecanismo de comunicación entre procesos de VHDL; un (¡muy!) poco como canalizaciones a un programador en C

Por lo tanto, el valor OLD en ADC_Temp está disponible en la asignación a ADC_Reg_1, a pesar de esta asignación después de una asignación a ADC_Temp.

Lo que realmente sucede con la primera asignación en el sentido de que se pospone: está programado para que se lleve a cabo una vez que el proceso se haya suspendido, por lo que el antiguo valor ADC_Temp aún se conserva en el momento de la segunda asignación.

La organización de asignaciones de señales de esta manera a veces se denomina "joya de la corona" de VHDL y elimina las condiciones de carrera que afectan a otras tecnologías de simulación. Más información aquí y here ...

    
respondido por el Brian Drummond

Lea otras preguntas en las etiquetas