Previous

Register Inference

Foundation Express infers registers using the wait and if statements.

A register is a simple, one-bit memory device, either a flip-flop or a latch. A flip-flop is an edge-triggered memory device. A latch is a level-sensitive memory device.

Use the wait statement to imply flip-flops in a synthesized circuit. Foundation Express creates flip-flops for all signals and some variables that are assigned values in a process with a wait statement.

The if statement can be used to imply registers (flip-flops or latches) for signals and variables in the branches of the if statement.

To infer registers, describe latches and flip-flops, and learn to efficiently use registers, familiarize yourself with the following subsections of this chapter.

Inferring Registers

To infer registers, you describe clocked signals and use wait and if statements. Recommended models for different types of inferred registers and current Express restrictions must also be considered.

Describing Clocked Signals

Foundation Express can infer asynchronous memory elements from VHDL descriptions written in a natural style.

Use the wait and if statements to test for the rising or falling edge of a signal. The most common uses of the wait and if statement follow.

   process  
   begin  
     wait until (edge);   
     ...  
   end process;  
   ...  
   
   process (sensitivity_list)  
   begin  
     if (edge)   
       ...  
     end if;  
   end process;

Another form follows.

   process (sensitivity_list)
   begin
     if (...) then
       ...
     elsif (...)
       ...
     elsif (edge) then
       ...
     end if;
   end process;

An edge expression tests for the positive or negative edge of a signal. The syntax of an edge expression follows.

   SIGNAL'event      and SIGNAL = '1'  -- rising edge
   NOT SIGNAL'stable and SIGNAL = '1'  -- rising edge
   
   SIGNAL'event      and SIGNAL = '0'  -- falling edge
   NOT SIGNAL'stable and SIGNAL = '0'  -- falling edge

In a wait statement, edge can also be the following.

   signal = '1'  -- rising edge
   signal = '0'  -- falling edge

An edge expression must be the only condition of an if or an elsif statement. You can have only one edge expression in an if statement, and the if statement must not have an else clause. An edge expression cannot be part of another logical expression nor used as an argument.

The following examples show illegal syntax. These lines illustrate three incorrect uses of the edge expression. In the first group, the edge expression is part of a larger Boolean expression. In the second group, the edge expression is used as an argument. In the third group, the edge expression is used as an intermediate condition.

   if (edge and RST = '1') 

Edge must be the only condition.

   Any_function(edge);

Edge cannot be an argument.

   if X > 5 then
     sequential_statement;
   elsif edge then
     sequential_statement;
   else
    ; ;sequential_statement;
   end if;

Do not use edge as an intermediate expression.

Wait versus if Statements

Sometimes you can use the wait and if statements interchangeably. The if statement is usually preferred, because it provides greater control over the inferred register's capabilities, as described in the next section.

IEEE VHDL requires that a process with a wait statement must not have a sensitivity list.

An if edge statement can appear anywhere in a process. The sensitivity list of the process must contain all signals read in the process, including the edge signal. In general, the following guidelines apply.

Recommended Use of Register Inference Capabilities

The register inference capability can support styles of description other than those described here. However, for best results, follow the recommendations below.

   LATCH:  process(sensitivity_list)
             begin
               if LATCH_ENABLE then
                      ...
               end if;
             end process;
   
   LATCH_ASYNC_SET:  
                      ...
   attribute async_set_reset of SET : signal is "true";
                      ...
           process(sensitivity_list)
             begin
               if SET then
                  Q <= '1';
               elsif LATCH_ENABLE then
                      ...
               end if;
             end process;
   
   FF:     process(CLK)
             begin
               if edge then
                   ...
               end if;
             end process;
   
   FF_ASYNC_RESET:  
           process(RESET, CLK)
             begin
               if RESET then
                  Q <= '0';
               elsif edge then
                  Q <= ...;
               end if;
             end process;
   
   FF_SYNC_RESET:  
           process(RESET, CLK)
             begin
               if edge ;then
                 if RESET then
                   Q <= '0';
                 else
                   Q <= ...;
                 end if;
               end if;
             end process;

Examples of these templates are provided in the “Describing Latches” section and the “Describing Flip-flops” section in this chapter.

Restrictions on Register Capabilities

The following restrictions apply to register capabilities.

Delays in Registers

If you use delay specifications with values that may be registered, these values might cause the simulation to behave differently from the logic synthesized by Foundation Express. For example, the description in the example below contains delay information that causes Foundation Express to synthesize a circuit that behaves unexpectedly.

   component flip_flop ( 
       D, clock: in BIT;
       Q:        out BIT;);
   end component;
   
   process ( A, C, D, clock );
     signal B: BIT;
   begin
   B <= A after 100ns;
   
   F1: flip_flop port map ( A, C, clock ),
   F2: flip_flop port map ( B, D, clock );
   end process;

In the example above, fewer than 100 nanoseconds, output D is one or more clock cycles behind output C when the circuit is simulated. However, because Foundation Express ignores the delay information, A and B change values at the same time and so do C and D. This behavior is not the same as in the simulated circuit.

When you use delay information in your designs, make sure the delays do not affect registered values. In general, you can safely include delay information in your description if it does not change the value that gets clocked into a flip-flop.

Describing Latches

Foundation Express infers latches from incompletely specified conditional expressions. In the following example, the if statement infers a latch because there is no else clause. The inferred latch uses CLK as its clock and DATA as its data input, as shown in the figure following the example.

   process(GATE, DATA)
   begin
     if (GATE = '1') then
       Q <= DATA;
     end if;
   end process;

Figure 8.1 Circuit for Latch Inference

Automatic Latch Inferencing

A signal or variable that is not driven under all conditions becomes a latched value. As shown in the example below, TEMP becomes a latched value because it is assigned only when PHI is 1. The resulting circuit follows the example.

   if(PHI = '1') then
     TEMP <= A;
   end if;

Figure 8.2 Circuit for Automatically Inferred Latch

To avoid inferred latches, assign a value to the signal under all conditions, as shown in the following example. The resulting circuit follows the example.

   if (PHI = '1') then
     TEMP <= A;
   else
     TEMP <= '0';
   end if;

Figure 8.3 Circuit for Fully Specified Signal: No Latch Inference

Restrictions on Latch Inference Capabilities

You cannot read a conditionally assigned variable after the if statement in which it is assigned. A conditionally assigned variable is assigned a new value under some, but not all, conditions.

Therefore, a variable must always have a value before it is read. The example below shows illegal syntax.

   signal X, Y: BIT;
   . . .
   process
     variable VALUE: BIT;
   begin
   
      if (condition) then
         VALUE := X;
      end if;
   
      Y <= VALUE;  -- Illegal
   end;  

In simulation, latch inference occurs because signals and variables can hold state over time. A signal or variable holds its value until that value is reassigned. Foundation Express inserts a latch to duplicate this holding of state in hardware.

Variables declared locally within a subprogram do not hold their value over time. Every time a subprogram is used, its variables are initialized again. Therefore, Foundation Express does not infer latches for variables declared in subprograms. In the following example, no latches are inferred. The resulting circuit is shown in the figure following the example.

   function MY_FUNC(DATA, GATE : BIT) return BIT is
        variable STATE: BIT;
   begin
        if GATE then
             STATE := DATA;
        end if;
        return STATE;
   end;
   . . .
   Q <= MY_FUNC(DATA, GATE);

Figure 8.4 Circuit for Function without Inferred Latch

Design with Two-Phase Clocks

By using the latch inference capability, you can describe network structures, such as two-phase systems in a technology independent manner. The example below shows a simple two-phase system with clocks PHI_1 and PHI_2. The resulting circuit follows the example.

   entity LATCH_VHDL is
     port(PHI_1, PHI_2, A : in BIT; 
          t: out BIT);
   end LATCH_VHDL;
   
   architecture EXAMPLE of LATCH_VHDL is
     signal TEMP, LOOP_BACK: BIT;
   begin
     process(PHI_1, A, LOOP_BACK)
     begin
       if(PHI_1 = '1') then
         TEMP <= A and LOOP_BACK;
       end if;
     end process;
   
     process(PHI_2, TEMP)
     begin
       if(PHI_2 = '1') then
         LOOP_BACK <= not TEMP;
       end if;
     end process;
     t <= LOOP_BACK;
   end EXAMPLE;

Figure 8.5 Circuit for Two-Phase Clocks

Foundation Express does not automatically infer dual-phase latches (devices with master and slave clocks). To use these devices, you must instantiate them as components, as described in the “Describing Designs” chapter.

Describing Flip-flops

The example below shows how an edge construct creates a flip-flop. The resulting circuit follows the example.

   process(CLK, DATA)
   begin
     if (rising_edge) then
       Q <= DATA;
     end if;
   end process;  

Figure 8.6 Circuit for Inferred Flip-flop

The example below shows how to specify a flip-flop with an asynchronous reset. The resulting circuit follows the example.

   process(RESET_LOW, CLK, SYNC_DATA)
   begin
     if RESET_LOW = `0' then
       Q <= '0';
     elsif (rising_edge) then
       Q <= SYNC_DATA;
     end if;
   end process; 

Figure 8.7 Circuit for Inferred Flip-flop with Asynchronous Reset

The following notes show how the flip-flop in the previous example is wired.

The example below shows an inferred flip-flop with an asynchronous reset, where the reset condition is not computable. The resulting circuit follows the example.

   process (CLK, ANY_SIGNAL, ASYNC_DATA, SYNC_DATA)
     begin
       if (ANY_SIGNAL) then
         Q <= ASYNC_DATA;
       elsif (rising_edge) then
         Q <= SYNC_DATA;
       end if;
     end process;

Figure 8.8 Circuit for Inferred Flip-flop with Asynchronous Set or Clear

The following example shows a synchronous finite state machine with asynchronous reset. The resulting circuit follows the example.

   package MY_TYPES is
     type STATE_TYPE is (S0, S1, S2, S3);
   end MY_TYPES;
   
   use WORK.MY_TYPES.ALL;
   
   entity STATE_MACHINE is
     port(CLK, INC, A, B: in BIT; RESET: in Boolean;
          t: out BIT);
   end STATE_MACHINE;
   
   architecture EXAMPLE of STATE_MACHINE is
     signal CURRENT_STATE, NEXT_STATE: STATE_TYPE;
   begin
     SYNC: process(CLK, RESET)
     begin
       if (RESET) then
         CURRENT_STATE <= S0;
       elsif (rising_edge) then
         CURRENT_STATE <= NEXT_STATE;
       end if;
     end process SYNC;
   
   FSM: process(CURRENT_STATE, A, B)
   begin
      t <= A;            -- Default assignment
      NEXT_STATE <= S0;  -- Default assignment
   
      if (INC = '1') then
         case CURRENT_STATE is
           when S0 =>
             NEXT_STATE <= S1;
           when S1 =>
             NEXT_STATE <= S2;
             t <= B;
           when S2 =>
             NEXT_STATE <= S3;
           when S3 =>
             null;
         end case;
      end if;
    end process FSM;
   end EXAMPLE;

Figure 8.9 Circuit for a Synchronous Finite State Machine with Asynchronous Reset

Attributes

New attributes used to assist register inference are discussed in this section. The attributes are defined in a VHDL library called Synopsys ATTRIBUTES package.

   attribute async_set_reset : string;
   attribute sync_set_reset : string;
   attribute async_set_reset_local : string;
   attribute sync_set_reset_local : string;
   attribute async_set_reset_local_all : string;
   attribute sync_set_reset_local_all : string;
   attribute one_hot : string;
   attribute one_cold : string;

NOTE

The examples below that use reset and set are only valid for 9k designs.


async_set_reset

The async_set_reset attribute is attached to single-bit signals using the attribute construct. Foundation Express checks signals with the async_set_reset attribute set to TRUE to determine whether these signals asynchronously set or reset a latch in the entire design.

The syntax of async_set_reset follows.

   attribute async_set_reset of signal_name,. : signal is "true";

Latch with Asynchronous Set or Clear Inputs

The asynchronous clear signal for a latch is inferred by driving the Q pin of your latch to 0. The asynchronous set signal for a latch is inferred by driving the Q pin of your latch to 1. Although Foundation Express does not require that the clear (set) be the first condition in your conditional branch, it is best to write your VHDL in this manner.

The example below shows how to specify a latch with an asynchronous clear input. To specify a latch with an asynchronous set, change the logic as indicated by the comments. The resulting circuit follows the example.

   attribute async_set_reset of clear : signal is "true";
   process(clear, gate, a)
   begin
     if (clear = `1') then
       q <= `0';
     elsif (gate = '1') then
       q <= a;
     end if;
   end process;

Figure 8.10 Circuit for Inferred Latch with Asynchronous Clear

sync_set_reset

The sync_set_reset attribute is attached to single-bit signals with the attribute constructs. Foundation Express checks signals with the sync_set_reset attribute set to TRUE to determine whether these signals synchronously set or reset a flip-flop in the entire design.

The syntax of sync_set_reset follows.

   attribute sync_set_reset of signal_name,... : signal is "true";

Flip-flop with Synchronous Reset Input

The example below shows how to specify a flip-flop with a synchronous reset. The resulting circuit follows the example.

   attribute sync_set_reset of RESET, SET : signal is "true";
   process(RESET, CLK)
   begin
     if (rising_edge) then
       if RESET = `1' then
         Q <= '0';
       else
         Q <= DATA_A;
       end if;
     end if;
   end process;  
   
   process (SET, CLK)
   begin
     if (rising_edge) then
       if SET = `1' then
         T <= '1';
       else
         T <= DATA_B;
       end if;
     end if;
   end process;

Figure 8.11 Circuit for an Inferred Flip-flop with Synchronous Reset Input

async_set_reset_local

The async_set_reset_local attribute is attached to the label of a process with a value of a double-quoted list of single-bit signals. Every signal in the list is treated as though it has the async_set_reset attribute attached in the specified process.

The syntax of async_set_reset_local follows.

   attribute async_set_reset_local of process_label : label is
    "signal_name,...";

The example shows an asynchronous set/reset on a single block. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_async_set_reset_local is
   port(reset, set, gate: in std_logic; y, t: out std_logic);
   end e_async_set_reset_local;
   
   architecture rtl of e_async_set_reset_local is
   attribute async_set_reset_local of direct_set_reset : label 
   is "reset, set";
   begin
   
   direct_set_reset: process (reset, set)
   begin
       if (reset = '1') then
         y <= '0';             -- asynchronous reset
       elsif (set = '1') then
         y <= '1';             -- asynchronous set
       end if;
   end process direct_set_reset;
   
   gated_data: process (gate, reset, set)
   begin
       if (gate = '1') then
         if (reset = '1') then
           t <= '0';             -- gated data
         elsif (set = '1') then
           t <= '1';             -- gated data
         end if;
       end if;
   end process gated_set_reset;
   
   end rtl;

Figure 8.12 Circuit for an Asynchronous Set/Reset on a Single Block

sync_set_reset_local

The sync_set_reset_local attribute is attached to the label of a process with a value of a double-quoted list of single-bit signals. Every signal in the list is treated as though it has the sync_set_reset attribute attached in the specified process.

The syntax of sync_set_reset_local follows.

   attribute sync_set_reset_local of process_label : label is "signal_name,..."

The following example shows synchronous set/reset on a single block. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_sync_set_reset_local is
   port(clk, reset, set, gate : in std_logic; y, t: out std_logic);
   end e_sync_set_reset_local;
   
   architecture rtl of e_sync_set_reset_local is
   attribute sync_set_reset_local of clocked_set_reset : label is "reset, set";
   begin
   
     clocked_reset: process (clk, reset, set)
     begin
       if (rising_edge) then
         if (reset = '1') then
           y <= '0';             -- synchronous reset
         else
           y <= '1';               -- synchronous set
         end if;
       end if;
     end process clocked_set_reset;
   
     gated_data: process (clk, gate, reset, set)
     begin
       if (rising_edge) then
         if (gate = '1') then
           if (reset = '1') then
             t <= '0';             -- gated data
           elsif (set = '1') then
             t <= '1';             -- gated data
           end if;
         end if;
       end if;
     end process gated_set_reset;
   
   end rtl;

Figure 8.13 Circuit for a Synchronous Set/Reset on a Single Block

async_set_reset_local_all

The async_set_reset_local_all attribute is attached to a process label. The attribute async_set_reset_local_all specifies that all the signals in the process are used to detect an asynchronous set or reset condition for inferred latches or flip-flops.

The syntax of async_set_reset_local_all follows.

   attribute async_set_reset_local_all of process_label,... : label is "true";

The following example shows an asynchronous set/reset on part of a design. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_async_set_reset_local_all is
   port(reset, set, gate, gate2: in std_logic; y, t, w: out std_logic);
   end e_async_set_reset_local_all;
   
   architecture rtl of e_async_set_reset_local_all is
   attribute async_set_reset_local_all of
             direct_set_reset, direct_set_reset_too: label is "true";
   begin
     direct_set_reset: process (reset, set)
     begin
       if (reset = '1') then
         y <= '0';             -- asynchronous reset
       elsif (set = '1') then
         y <= '1';             -- asynchronous set
       end if;
     end process direct_set_reset;
   
     direct_set_reset_too: process (gate, reset, set)
     begin
       if (gate = '1') then
         if (reset = '1') then
           t <= '0';             -- asynchronous reset
         elsif (set = '1') then
           t <= '1';             -- asynchronous set
         end if;
       end if;
     end process direct_set_reset_too;
   
     gated_data: process (gate2, reset, set)
     begin
       if (gate = '1') then
         if (reset = '1') then
           w <= '0';             -- gated data
         elsif (set = '1') then
           w <= '1';             -- gated data
         end if;
       end if;
     end process gated_set_reset;
   
   end rtl;

Figure 8.14 Circuit for an Asynchronous Set/Reset on Part of a Design

sync_set_reset_local_all

The sync_set_reset_local_all attribute is attached to a process label. The attribute sync_set_reset_local_all specifies that all the signals in the process are used to detect a synchronous set or reset condition for inferred latches or flip-flops.

The syntax of sync_set_reset_local_all follows.

   attribute sync_set_reset_local_all of process_label,... : label is "true";

The following example shows a synchronous set/reset on a part of a design. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_sync_set_reset_local_all is
   port(clk, reset, set, gate, gate2: in std_logic; y, t, w: out std_logic);
   end e_sync_set_reset_local_all;
   
   architecture rtl of e_sync_set_reset_local_all is
   attribute sync_set_reset_local_all of
             clocked_set_reset, clocked_set_reset_too: label is "true";
   begin
   
     clocked_set_reset: process (clk, reset, set)
     begin
       if (rising_edge) then
         if (reset = '1') then
           y <= '0';             -- synchronous reset
         elsif (set = '1') then
           y <= '1';             -- synchronous set
         end if;
       end if;
     end process clocked_set_reset;
   
     clocked_set_reset_too: process (clk, gate, reset, set)
     begin
       if (rising_edge) then
         if (gate = '1') then
           if (reset = '1') then
             t <= '0';             -- synchronous reset
           elsif (set = '1') then
             t <= '1';             -- synchronous set
           end if;
         end if;
       end if;
     end process clocked_set_reset_too;
   
     gated_data: process (clk, gate2, reset, set)
     begin
       if (rising_edge) then
         if (gate = '1') then
           if (reset = '1') then
             w <= '0';             -- gated data
           elsif (set = '1') then
             w <= '1';             -- gated data
           end if;
         end if;
       end if;
     end process gated_set_reset;
   
   end rtl;

Figure 8.15 Circuit for a Synchronous Set/Reset on a Part of a Design


NOTE

Use the one_hot and one_cold directives to implement D-type flip-flops with asynchronous set and reset signals. These two attributes tell Foundation Express that only one of the objects in the list are active at a time. If you are defining active high signals, use one_hot. For active low, use one_cold. Each attribute has two objects specified.


one_hot

The one_hot directive takes one argument of a double-quoted list of signals separated by commas. This attribute indicates that the group of signals are one_hot (at any time, no more than one signal can have a Logic 1 value). Check that the group of signals are really one_hot, because Foundation Express does not produce any logic to check this assertion.

The syntax of one_hot follows.

   attribute one_hot signal_name,... : label is "true";

The following example shows how to use one_hot for set and reset. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_one_hot is
   port(reset, set, reset2, set2: in std_logic; y, t: out std_logic);
   attribute async_set_reset of reset, set : signal is "true";
   attribute async_set_reset of reset2, set2 : signal is "true";
   attribute one_hot of reset, set : signal is "true";
   end e_one_hot;
   
   architecture rtl of e_one_hot is
   begin
     direct_set_reset: process (reset, set )
     begin
       if (reset = '1') then
         y <= '0';             -- asynchronous reset by "reset"
       elsif (set = '1') then
         y <= '1';             -- asynchronous set by "set"
       end if;
     end process direct_set_reset;
     direct_set_reset_too: process (reset2, set2 )
     begin
       if (reset2 = '1') then
         t <= '0';             -- asynchronous reset by "reset2"
       elsif (set2 = '1') then
         t <= '1';             -- asynchronous set by "~reset2 set2"
       end if;
     end process direct_set_reset_too;
   
   -- synopsys synthesis_off
   process (reset, set)
   begin
     assert not (reset='1' and set='1')
       report "One-hot violation"
       severity Error;
   end process;
   -- synopsys synthesis_on
   end rtl;

Figure 8.16 Circuit for one_hot for Set and Reset

one_cold

The one_cold directive is similar to the one_hot directive. one_cold indicates that no more than one signal in the group can have a Logic 0 value at any time.

The syntax of one_cold follows.

attribute one_cold signal_name,... : label is "true";

The following example shows how to use one_cold for set and reset. The resulting circuit follows the example.

   library IEEE;
   library synopsys;
   use IEEE.std_logic_1164.all;
   use synopsys.attributes.all;
   
   entity e_one_cold is
   port(reset, set, reset2, set2: in std_logic; y, t: out std_logic);
   attribute async_set_reset of reset, set : signal is "true";
   attribute async_set_reset of reset2, set2 : signal is "true";
   attribute one_cold of reset, set : signal is "true";
   end e_one_cold;
   
   architecture rtl of e_one_cold is
   begin
   
     direct_set_reset: process (reset, set )
     begin
       if (reset = '0') then
         y <= '0';             -- asynchronous reset by "not reset"
       elsif (set = '0') then
         y <= '1';             -- asynchronous set by "not set"
       end if;
     end process direct_set_reset;
   
     direct_set_reset_too: process (reset2, set2 )
     begin
       if (reset2 = '0') then
         t <= '0';             -- asynchronous reset by "not reset2"
       elsif (set2 = '0') then
         t <= '1';           -- asynchronous set by "(not reset2) (not set2)"
       end if;
     end process direct_set_reset_too;
   
   -- synopsys synthesis_off
   process (reset, set)
   begin
     assert not (reset='0' and set='0')
       report "One-cold violation"
       severity Error;
   end process;
   -- synopsys synthesis_on
   
   end rtl;

Figure 8.17 Circuit for one_cold for Set and Reset

Foundation Express Latch and Flip-flop Inference

Foundation Express infers latches and flip-flops as follows.

Foundation Express generates a brief report on inferred latches, flip-flops, or three-state devices.

Efficiently Using Registers

Organize your HDL description so that you build only as many flip-flops as the design requires. The following example shows a description where too many flip-flops are implied. The resulting circuit follows the example.

   library IEEE;
   use IEEE.std_logic_1164.all;
   use IEEE.std_logic_unsigned.all;
   
   entity ex8_13 is
   port ( clk , reset : in std_logic;
          and_bits , or_bits , xor_bits : out std_logic
   );
   end ex8_13;
   
   architecture rtl of ex8_13 is
   begin
   process
   variable count : std_logic_vector (2 downto 0);
   begin
        wait until rising_edge;
        if (reset = '1') then
             count := "000";
        else count := count + 1;
        end if;
        and_bits <= count(2) and count(1) and count(0);
        or_bits <= count(2) or count(1) or count(0);
        xor_bits <= count(2) xor count(1) xor count(0);
   end process;
   end rtl;

Figure 8.18 Circuit with Six Implied Registers

In the example of the circuit with six implied registers, the outputs AND_BITS, OR_BITS, and XOR_BITS depend solely on the value of COUNT. Because COUNT is registered, the three outputs do not need to be registered. To avoid implying extra registers, assign the outputs from within a process that does not have a wait statement. The following example shows a description with two processes, one with a wait statement and one without. The resulting circuit follows the example.

This description style lets you choose the signals that are registered and those that are not. This technique of separating combinatorial logic from registered or sequential logic is useful when describing finite state machines.

   use work.ARITHMETIC.all;
   entity COUNT is
     port(CLOCK, RESET: in BIT; 
          AND_BITS, OR_BITS, XOR_BITS : out BIT);
   end COUNT;
   
   architecture RTL of COUNT is
     signal COUNT : UNSIGNED (2 downto 0);
   begin
   
     REG: process                  -- Registered logic
     begin
       wait until rising_edge;
       if (RESET = '1') then
          COUNT <= "000";
       else
          COUNT <= COUNT + 1;
       end if;
     end process;
   
     COMBIN: process(COUNT)        -- Combinational logic
     begin
       AND_BITS <= COUNT(2) and COUNT(1) and COUNT(0);
       OR_BITS <= COUNT(2) or COUNT(1) or COUNT(0);
       XOR_BITS <= COUNT(2) xor COUNT(1) xor COUNT(0);
     end process;
   end RTL;

Figure 8.19 Circuit with Three Implied Registers

Using Synchronous and Asynchronous Processes

If you want to keep some of the values computed by a process in flip-flops while allowing other values to change between clock edges, split your algorithm between two processes, one with a wait statement and one without. Put the registered (synchronous) assignments into the wait process. Put the other (asynchronous) assignments into the other process. Use signals to communicate between the two processes.

For example, suppose you want to build a design with the following characteristics.

The implementation of this design requires two processes. The process with a wait statement synchronizes the CONTROL value. The other process multiplexes the output, based on the synchronized control. The signal SYNC_CONTROL communicates between the two processes.

The example below shows the code and a schematic of one possible implementation.

   entity SYNC_ASYNC is
      port (CLOCK:   in BIT;
            CONTROL: in INTEGER range 0 to 3;
            A:       in BIT_VECTOR(0 to 3);
            t:      out BIT);
   end SYNC_ASYNC;
   
   architecture EXAMPLE of SYNC_ASYNC is
     signal SYNC_CONTROL: INTEGER range 0 to 3;
   begin
   
     process
     begin
       wait until rising_edge;
       SYNC_CONTROL <= CONTROL;
     end process;
   
   process (A, SYNC_CONTROL)
     begin
       t <= A(SYNC_CONTROL);
     end process;
   end EXAMPLE;

Figure 8.20 Circuit for Two Processes: One Synchronous, One Asynchronous

Next