Electronic – VHDL Question: Sequential Execution Within a Process

vhdl

I've inherited some VHDL code I need to extend. There's a piece in there that looks like a bug to me, but while I'm long-time C developer, I've no experience in VHDL. I understand that processes essentially run in parallel, but within a process, does order matter? In the following code, a CPLD is receiving serial ADC data from a microcontroller. The data stream contains the results from two separate 8-bit conversions and is being loaded into two registers, one bit at a time. However it looks like at the end of receiving the first byte of ADC data, the MSB of this byte is being overwritten with the MSB from the second byte before it's loaded into its register. Is this a bug? I've removed some of the code to make the sample more readable.

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;

Best Answer

Not knowing all the details, in principle it is not a bug. This is a process that occurs whenever there is a falling edge on the associated clock. You can imagine that all signal reads happen right before the edge, and all the writes happen at the edge.

So having inside a clocked process:

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).

The order of the above assignments does not matter, and can be represented by the following schematic:

schematic

simulate this circuit – Schematic created using CircuitLab

As you can see in the above schematic, each Flip-Flop has a 'queued' value Dand it becomes the output Q at the clock's edge. a has b queued, and c has a queued. So in a single clock, b can't propagate all the way to c (it requires 2 clock cycles). So specifying the signal 'queuing' in code does not need any particular order.

In your specific example, when ADC_Counter is 13, ADC_temp(7) has ADC_Data queued, and ADC_Reg_1 has ADC_Temp queued. ADC_Reg_1 is not getting corrupted with the new data bit, in the same way that our c is not getting corrupted with b.

Note: This would be different if talking about variables (you'd be using the := operator instead of <=), but your code only contains signals.