Home » Programming » 9. Dataflow Modeling – Concurrent Statements

9. Dataflow Modeling – Concurrent Statements

Behavioral modeling can be done with sequential statements using the process construct or with concurrent statements. The first method was described in the previous section and is useful to describe complex digital systems. In this section, we will use concurrent statements to describe behavior. This method is usually called dataflow modeling. The dataflow modeling describes a circuit in terms of its function and the flow of data through the circuit. This is different from the structural modeling that describes a circuit in terms of the interconnection of components.

 

Concurrent signal assignments are event triggered and executed as soon as an event on one of the signals occurs. In the remainder of the section we will describe several concurrent constructs for use in dataflow modeling.

 

  1. Simple Concurrent signal assignments.

 

We have discussed several concurrent examples earlier in the tutorial. In this section we will review the different types of concurrent signal assignments.

 

A simple concurrent signal assignment is given in the following examples,

 

Sum <= (A xor B) xor Cin;

Carry <= (A and B);

Z <= (not X) or Y after 2 ns;

 

The syntax is as follows:

 

Target_signal <= expression;

 

in which the value of the expression transferred to the target_signal. As soon as an event occurs on one of the signals, the expression will be evaluated. The type of the target_signal has to be the same as the type of the value of the expression.

 

Another example is given below of a 4-bit adder circuit. Notice that we specified the package: IEEE.std_logic_unsigned in order to be able to use the “+” (addition) operator.

 

Example of a Four bit Adder using concurrent/behavioral modeling
library ieee;

use IEEE.std_logic_1164.all;

use IEEE.std_logic_unsigned.all;

 

entity ADD4 is

port (

A: in STD_LOGIC_VECTOR (3 downto 0);

B: in STD_LOGIC_VECTOR (3 downto 0);

CIN: in STD_LOGIC;

SUM: out STD_LOGIC_VECTOR (3 downto 0);

COUT: out STD_LOGIC

);

end ADD4;

 

architecture ADD4_concurnt of ADD4 is

 

— define internal SUM signal including the carry

signal SUMINT: STD_LOGIC_VECTOR(4 downto 0);

 

begin

— <<enter your statements here>>

SUMINT <= (‘0’ & A) + (‘0’ & B) + (“0000” & CIN);

COUT <= SUMINT(4);

SUM <= SUMINT(3 downto 0);

end ADD4_concurnt;

 

 

 

  1. Conditional Signal assignments

 

The syntax for the conditional signal assignment is as follows:

 

Target_signal <= expression when Boolean_condition else

expression when Boolean_condition else

     :

expression;

 

The target signal will receive the value of the first expression whose Boolean condition is TRUE. If no condition is found to be TRUE, the target signal will receive the value of the final expression. If more than one condition is true, the value of the first condition that is TRUE will be assigned.

 

An example of a 4-to-1 multiplexer using conditional signal assignments is shown below.

 

entity MUX_4_1_Conc is

port (S1, S0, A, B, C, D: in std_logic;

Z: out std_logic);

end MUX_4_1_Conc;

architecture concurr_MUX41 of MUX_4_1_Conc is

begin

Z <= A when S1=’0’ and S0=’0’ else

B when S1=’0’ and S0=’1’ else

C when S1=’1’ and S0=’0’ else

D;

end concurr_MUX41;

 

The conditional signal assignment will be re-evaluated as soon as any of the signals in the conditions or expression change. The when-else construct is useful to express logic function in the form of a truth table. An example of the same multiplexer as above is given below in a more compact form.

 

entity MUX_4_1_funcTab is

port (A, B, C, D: in std_logic;

        SEL: in std_logic_vector (1 downto 0);

Z: out std_logic);

end MUX_4_1_ funcTab;

architecture concurr_MUX41 of MUX_4_1_ funcTab is

begin

Z <= A when SEL = ”00” else

B when SEL = ”01” else

C when SEL = “10” else

D;

end concurr_MUX41;

 

 

Notice that this construct is simpler than the If-then-else construct using the process statement or the case statement. An alternative way to define the multiplexer is the case construct inside a process statement, as discussed earlier.

 

  1. Selected Signal assignments

 

The selected signal assignment is similar to the conditional one described above. The syntax is as follows,

 

with choice_expression select

           target_name <= expression when choices,

           target_name <= expression when choices,

:

target_name <= expression when choices;

 

The target is a signal that will receive the value of an expression whose choice includes the value of the choice_expression. The expression selected is the first with a matching choice. The choice can be a static expression (e.g. 5) or a range expression (e.g. 4 to 9). The following rules must be followed for the choices:

 

  • No two choices can overlap
  • All possible values of choice_expression must be covered by the set of choices, unless an others choice is present.

 

An example of a 4-to-1 multiplexer is given below.

 

entity MUX_4_1_Conc2 is

port (A, B, C, D: in std_logic;

           SEL: in std_logic_vector(1 downto 0);

Z: out std_logic);

end MUX_4_1_Conc2;

architecture concurr_MUX41b of MUX_4_1_Conc2 is

begin

     with SEL select

Z <= A when “00”,

B when “01”,

C when “10”,

D when “11”;

end concurr_MUX41b;

 

The equivalent process statement would make use of the case construct. Similarly to the when-else construct, the selected signal assignment is useful to express a function as a truth table, as illustrated above.

 

The choices can express a single value, a range or combined choices as shown below.

 

 

target <= value1 when “000”,

value2 when “001” | “011” | “101” ,

value3 when others;

 

In the above example, all eight choices are covered and only once. The others choice must the last one used.

 

Notice that the Xilinx Foundation Express does not allow a vector as choice_expression such as std_logic_vector’(A,B,C).

 

As an example, lets consider a full adder with inputs A, B and C and outputs sum and cout,

 

entity FullAdd_Conc is

port (A, B, C: in std_logic;

sum, cout: out std_logic);

end FullAdd_Conc;

architecture FullAdd_Conc of FullAdd_Conc is

     —define internal signal: vector INS of the input signals

     signal INS: std_logic_vector (2 downto 0);

 

begin

–define the components of vector INS of the input signals

INS(2) <= A;

INS(1) <= B;

INS(0) <= C;

 

with INS select

(sum, cout) <= std_logic_vector’(“00”) when “000”,

std_logic_vector’(“10”) when “001”,

std_logic_vector’(“10”) when “010”,

std_logic_vector’(“01”) when “011”,

std_logic_vector’(“10”) when “100”,

std_logic_vector’(“01”) when “101”,

std_logic_vector’(“01”) when “110”,

std_logic_vector’(“11”) when “111”,

std_logic_vector’(“11”) when others;

 

end FullAdd_Conc; ]

 

Notice: In the example above we had to define an internal vector INS(A,B,C) of the input signals to use as part of the with-select-when statement. This was done because the Xilinx Foundation does not support the construct std_logic_vector’(A,B,C).

Leave a Reply

Your email address will not be published. Required fields are marked *

Name *
Email *
Website

April 2024
M T W T F S S
1234567
891011121314
15161718192021
22232425262728
2930  

Archives