Chapter start Previous page Next page 10.13 Concurrent StatementsA concurrent statement [VHDL LRM9] is one of the following statements: concurrent_statement ::= block_statement | process_statement | [ label : ] [ postponed ] procedure_call ; | [ label : ] [ postponed ] assertion ; | [ label : ] [ postponed ] conditional_signal_assignment | [ label : ] [ postponed ] selected_signal_assignment | component_instantiation_statement | generate_statement The following sections describe each of these statements in turn. 10.13.1 Block StatementA block statement has the following format [VHDL LRM9.1]: block_statement ::= block_label: block [(guard_expression)] [is] [generic (generic_interface_list); [generic map (generic_association_list);]] [port (port_interface_list); [port map (port_association_list);]] {block_declarative_item} begin {concurrent_statement} end block [block_label] ; Blocks may have their own ports and generics and may be used to split an architecture into several hierarchical parts (blocks can also be nested). As a very general rule, for the same reason that it is better to split a computer program into separate small modules, it is usually better to split a large architecture into smaller separate entity-architecture pairs rather than several nested blocks. A block does have a unique
feature: It is possible to specify a guard expression for a block. This
creates a special signal, When you make an assignment
statement to a signal, you define a driver for that signal. If you make
assignments to guarded signals in a block, the driver for that signal is
turned off, or disconnected, when the The following example shows
two drivers, library ieee; use ieee.std_logic_1164.all; entity bus_drivers is end; architecture Structure_1 of bus_drivers is signal TSTATE: STD_LOGIC bus; signal A, B, OEA, OEB : STD_LOGIC:= '0'; begin process begin OEA <= '1' after 100 ns, '0' after 200 ns; OEB <= '1' after 300 ns; wait; end process; B1 : block (OEA = '1') disconnect all : STD_LOGIC after 5 ns; -- Only needed for float time. begin TSTATE <= guarded not A after 3 ns; end block; B2 : block (OEB = '1') disconnect all : STD_LOGIC after 5 ns; -- Float time = 5 ns. begin TSTATE <= guarded not B after 3 ns; end block; end; 1 2 3 4 5 6 7 Time(fs) + Cycle tstate a b oea oeb b1.GUARD b2.GUARD ---------------------- ------ ---- ---- ---- ---- -------- -------- 0+ 0: 'U' '0' '0' '0' '0' FALSE FALSE 0+ 1: * 'Z' '0' '0' '0' '0' FALSE FALSE 100000000+ 0: 'Z' '0' '0' *'1' '0' * TRUE FALSE 103000000+ 0: * '1' '0' '0' '1' '0' TRUE FALSE 200000000+ 0: '1' '0' '0' *'0' '0' * FALSE FALSE 200000000+ 1: * 'Z' '0' '0' '0' '0' FALSE FALSE 300000000+ 0: 'Z' '0' '0' '0' *'1' FALSE * TRUE 303000000+ 0: * '1' '0' '0' '0' '1' FALSE TRUE Notice the creation of implicit guard signals b1.GUARD and b2.GUARD for each guarded block. There is another, equivalent, method that uses the high-impedance value explicitly as in the following example: architecture Structure_2 of bus_drivers is signal TSTATE : STD_LOGIC; signal A, B, OEA, OEB : STD_LOGIC := '0'; begin process begin OEA <= '1' after 100 ns, '0' after 200 ns; OEB <= '1' after 300 ns; wait; end process; process(OEA, OEB, A, B) begin if (OEA = '1') then TSTATE <= not A after 3 ns; elsif (OEB = '1') then TSTATE <= not B after 3 ns; else TSTATE <= 'Z' after 5 ns; end if; end process; end; This last method is more widely
used than the first, and what is more important, more widely accepted by
synthesis tools. Most synthesis tools are capable of recognizing the value
10.13.2 Process StatementA process statement has the following format [VHDL LRM9.2]: process_statement ::= [process_label:] [postponed] process [(signal_name {, signal_name})] [is] {subprogram_declaration | subprogram_body | type_declaration | subtype_declaration | constant_declaration | variable_declaration | file_declaration | alias_declaration | attribute_declaration | attribute_specification | use_clause | group_declaration | group_template_declaration} begin {sequential_statement} end [postponed] process [process_label]; The following process models a 2:1 MUX (combinational logic): entity Mux_1 is port (i0, i1, sel : in BIT := '0'; y : out BIT); end; architecture Behave of Mux_1 is begin process (i0, i1, sel) begin -- i0, i1, sel = sensitivity set case sel is when '0' => y <= i0; when '1' => y <= i1; end case; end process; end; This process executes whenever an event occurs on any of the signals in the process sensitivity set (i0, i1, sel). The execution of a process occurs during a simulation cycle--a delta cycle. Assignment statements to signals may trigger further delta cycles. Time advances when all transactions for the current time step are complete and all signals updated. The following code models a two-input AND gate (combinational logic): entity And_1 is port (a, b : in BIT := '0'; y : out BIT); end; architecture Behave of And_1 is begin process (a, b) begin y <= a and b; end process; end; The next example models a
D flip-flop (sequential logic). The entity FF_1 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_1 is begin process (clk) begin if clk'EVENT and clk = '1' then q <= d; end if; end process; end; The behavior of the next example
is identical to the previous model. Notice that the entity FF_2 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_2 is begin process begin -- The equivalent process has a wait at the end: if clk'event and clk = '1' then q <= d; end if; wait on clk; end process; end; If we use a entity FF_3 is port (clk, d: in BIT := '0'; q : out BIT); end; architecture Behave of FF_3 is begin process begin -- No sensitivity set with a wait statement. wait until clk = '1'; q <= d; end process; end; If you include ports (interface
signals) in the sensitivity set of a 10.13.3 Concurrent Procedure CallA concurrent procedure
call appears outside a package And_Pkg is procedure V_And(a,b:BIT; signal c:out BIT); end; package body And_Pkg is procedure V_And(a,b:BIT; signal c:out BIT) is begin c <= a and b; end; end And_Pkg; use work.And_Pkg.all; entity Proc_Call_2 is end; architecture Behave of Proc_Call_2 is signal A, B, Y : BIT := '0'; begin V_And (A, B, Y); -- Concurrent procedure call. process begin wait; end process; -- Extra process to stop. end; 10.13.4 Concurrent Signal AssignmentThere are two forms
of concurrent signal assignment statement. A selected signal assignment
statement is equivalent to a selected_signal_assignment ::= with expression select name|aggregate <= [guarded] [transport|[reject time_expression] inertial] waveform when choice {| choice} {, waveform when choice {| choice} } ; The following design unit,
Selected_1, uses a selected signal assignment. The equivalent unit, Selected_2,
uses a entity Selected_1 is end; architecture Behave of Selected_1 is signal y,i1,i2 : INTEGER; signal sel : INTEGER range 0 to 1; begin with sel select y <= i1 when 0, i2 when 1; end; entity Selected_2 is end; architecture Behave of Selected_2 is signal i1,i2,y : INTEGER; signal sel : INTEGER range 0 to 1; begin process begin case sel is when 0 => y <= i1; when 1 => y <= i2; end case; wait on i1, i2; end process; end; The other form of concurrent
signal assignment is a conditional signal assignment statement that, in
its most general form, is equivalent to an conditional_signal_assignment ::= name|aggregate <= [guarded] [transport|[reject time_expression] inertial] {waveform when boolean_expression else} waveform [when boolean_expression]; Notice that in VHDL-93 the
entity Conditional_1 is end; architecture Behave of Conditional_1 is signal y,i,j : INTEGER; signal clk : BIT; begin y <= i when clk = '1' else j; -- conditional signal assignment end; entity Conditional_2 is end; architecture Behave of Conditional_2 is signal y,i : INTEGER; signal clk : BIT; begin process begin if clk = '1' then y <= i; else y <= y ; end if; wait on clk; end process; end; A concurrent signal assignment statement can look just like a sequential signal assignment statement, as in the following example: entity Assign_1 is end; architecture Behave of Assign_1 is signal Target, Source : INTEGER; begin Target <= Source after 1 ns; -- looks like signal assignment end; However, outside a entity Assign_2 is end; architecture Behave of Assign_2 is signal Target, Source : INTEGER; begin process begin Target <= Source after 1 ns; wait on Source; end process; end; Every process is executed once
during initialization. In the previous example, an initial value will be
scheduled to be assigned to entity Assign_3 is end; architecture Behave of Assign_3 is signal Target, Source : INTEGER; begin process begin wait on Source; Target <= Source after 1 ns; end process; end; 10.13.5 Concurrent Assertion StatementA concurrent assertion
statement is equivalent to a passive concurrent_assertion_statement ::= [ label : ] [ postponed ] assertion ; If the assertion condition
contains a signal, then the equivalent 10.13.6 Component InstantiationA component instantiation statement in VHDL is similar to placement of a component in a schematic--an instantiated component is somewhere between a copy of the component and a reference to the component. Here is the definition [VHDL LRM9.6]: component_instantiation_statement ::= instantiation_label: [component] component_name |entity entity_name [(architecture_identifier)] |configuration configuration_name [generic map (generic_association_list)] [port map (port_association_list)] ; We examined component instantiation using a component_name in Section 10.5. If we instantiate a component in this way we must declare the component (see BNF [10.9]). To bind a component to an entity-architecture pair we can use a configuration, as illustrated in Figure 10.1, or we can use the default binding as described in Section 10.7. In VHDL-93 we have another alternative--we can directly instantiate an entity or configuration. For example: entity And_2 is port (i1, i2 : in BIT; y : out BIT); end; architecture Behave of And_2 is begin y <= i1 and i2; end; entity Xor_2 is port (i1, i2 : in BIT; y : out BIT); end; architecture Behave of Xor_2 is begin y <= i1 xor i2; end; entity Half_Adder_2 is port (a,b : BIT := '0'; sum, cry : out BIT); end; architecture Netlist_2 of Half_Adder_2 is use work.all; -- need this to see the entities Xor_2 and And_2 begin X1 : entity Xor_2(Behave) port map (a, b, sum); -- VHDL-93 only A1 : entity And_2(Behave) port map (a, b, cry); -- VHDL-93 only end; 10.13.7 Generate StatementA generate statement [VHDL LRM9.7] simplifies repetitive code: generate_statement ::= generate_label: for generate_parameter_specification |if boolean_expression generate [{block_declarative_item} begin] {concurrent_statement} end generate [generate_label] ; Here is an example (notice the labels are required): entity Full_Adder is port (X, Y, Cin : BIT; Cout, Sum: out BIT); end; architecture Behave of Full_Adder is begin Sum <= X xor Y xor Cin; Cout <= (X and Y) or (X and Cin) or (Y and Cin); end; entity Adder_1 is port (A, B : in BIT_VECTOR (7 downto 0) := (others => '0'); Cin : in BIT := '0'; Sum : out BIT_VECTOR (7 downto 0); Cout : out BIT); end; architecture Structure of Adder_1 is use work.all; component Full_Adder port (X, Y, Cin: BIT; Cout, Sum: out BIT); end component; signal C : BIT_VECTOR(7 downto 0); begin AllBits : for i in 7 downto 0 generate LowBit : if i = 0 generate FA : Full_Adder port map (A(0), B(0), Cin, C(0), Sum(0)); end generate; OtherBits : if i /= 0 generate FA : Full_Adder port map (A(i), B(i), C(i-1), C(i), Sum(i)); end generate; end generate; Cout <= C(7); end; The instance names within
a :adder_1(structure):allbits(6):otherbits:fa: |
|||||
|
|||||
|