One important aspect of VHDL you should clearly understand is the relationship between sequential statements (in a process or subprogram) and the scheduling of signal and variable assignments. Signals within processes have fundamentally different behavior from variables. Variables are assigned new values immediately, while signal assignments are scheduled and do not occur until the current process (or subprogram) has been suspended. When you describe complex logic using sequential assignments, you must carefully consider which type of object (signal or variable) is appropriate for that part of your design.

 

Let's look at an example where signal assignments would be appropriate. In this example, an 8-bit serial cyclic-redundancy-check (CRC) generator, signals are required because we are attempting to construct a chain of registers. Each register in the chain is clocked from a common source, and data moves from one register to the next only when there is an event on Clk. We might describe the data as being "scheduled."

 

-------------------------------------------------------------------------

-- 8-bit Serial CRC Generator.

--

library ieee;

use ieee.std_logic_1164.all;

 

entity crc8s is

   port (Clk,Set, Din: in std_logic;

         CRC_Sum: out std_logic_vector(15 downto 0));

end crc8s;

 

architecture behavior of crc8s is

    signal X: std_logic_vector(15 downto 0);

begin

    process(Clk,Set)

    begin

        if Set = '1' then

            X <= "1111111111111111";

        elsif rising_edge(Clk) then

            X(0)  <= Din xor X(15);

            X(1)  <= X(0);

            X(2)  <= X(1);

            X(3)  <= X(2);

            X(4)  <= X(3);

            X(5)  <= X(4) xor Din xor X(15);

            X(6)  <= X(5);

            X(7)  <= X(6);

            X(8)  <= X(7);

            X(9)  <= X(8);

            X(10) <= X(9);

            X(11) <= X(10);

            X(12) <= X(11) xor Din xor X(15);

            X(13) <= X(12);

            X(14) <= X(13);

            X(15) <= X(14);

        end if;

    end process;

    CRC_Sum <= X;

end behavior;

 

Because the data moving from register to register is scheduled, this example would not work if X was described using a variable instead of a signal.  If a variable was substituted for X, the assignments for each stage of the CRC generation would be immediate and thus would not describe a chain of registers.

 

Note also that the assignment of X to CRC_Sum must be placed outside the process. If we were to write the assignment to CRC_Sum within the process, as in:

 

            . . .

            X(14) <= X(13);

            X(15) <= X(14);

        end if;

 

       CRC_Sum <= X;

 

    end process;

 

end behavior;

 

the result would not be what we intend. This is because the assignment of CRC_Sum will be subject to the execution and signal assignment rules of a process. In this case, the assignment of a final value to X will be delayed until the process suspends, and CRC_Sum will not be updated until the next time the process executes. (As it turns out, the next time the process executes may well be on the falling edge of the clock, meaning that CRC_Sum would be delayed by half a clock cycle.)