ch10.13.htm
来自「介绍asci设计的一本书」· HTM 代码 · 共 427 行 · 第 1/2 页
HTM
427 行
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="Adobe PageMill 2.0 Mac">
<TITLE> 10.13 Concurrent Statements</TITLE>
</HEAD><!--#include file="top.html"--><!--#include file="header.html"--><br><!--#include file="AmazonAsic.html"-->
<P><A NAME="pgfId=219992"></A><A HREF="CH10.htm">Chapter start</A> <A HREF="CH10.12.htm">Previous
page</A> <A HREF="CH10.14.htm">Next page</A></P>
<H2>10.13 Concurrent Statements</H2>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=5058"></A>A concurrent statement
[<A HREF="../../VHDL/LRM/HTML/1076_9.HTM#9">VHDL LRM9</A>] is one of the following
statements:</P>
<PRE>concurrent_statement ::=
block_statement
| process_statement
| [ label : ] <U>[ <B>postponed</B> ]</U> procedure_call ;
| [ label : ] <U>[ <B>postponed</B> ]</U> assertion ;
| [ label : ] <U>[ <B>postponed</B> ]</U> conditional_signal_assignment
| [ label : ] <U>[ <B>postponed</B> ]</U> selected_signal_assignment
| component_instantiation_statement
| generate_statement</PRE>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=538776"></A>The following sections
describe each of these statements in turn.</P>
<H3><A NAME="pgfId=538778"></A>10.13.1 Block Statement</H3>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=10842"></A>A block statement
has the following format [<A HREF="../../VHDL/LRM/HTML/1076_9.HTM#9.1">VHDL LRM9.1</A>]:</P>
<PRE>block_statement ::=
<I>block_</I>label: <B>block</B> [(<I>guard_</I>expression)] <U>[<B>is</B>]</U>
[<B>generic</B> (<I>generic_</I>interface_list);
[<B>generic</B> <B>map</B> (<I>generic_</I>association_list);]]
[<B>port</B> (<I>port_</I>interface_list);
[<B>port</B> <B>map</B> (<I>port_</I>association_list);]]
{block_declarative_item}
<B>begin</B>
{concurrent_statement}
<B>end</B> <B>block</B> [<I>block_</I>label] ;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=15909"></A>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.</P>
<P><P CLASS="Body"><A NAME="pgfId=15912"></A>A block does have a unique
feature: It is possible to specify a guard expression for a block. This
creates a special signal, <CODE>GUARD</CODE> , that you can use within the
block to control execution [<A HREF="../../VHDL/LRM/HTML/1076_9.HTM#9.5">VHDL LRM9.5</A>].
It also allows you to model three-state buses by declaring guarded signals
(signal kinds register and bus).</P>
<P><P CLASS="Body"><A NAME="pgfId=17198"></A>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 <CODE>GUARD</CODE> signal is <CODE>FALSE</CODE>
. The use of guarded signals and guarded blocks can become quite complicated,
and not all synthesis tools support these VHDL features.</P>
<P><P CLASS="Body"><A NAME="pgfId=465498"></A>The following example shows
two drivers, <CODE>A</CODE> and <CODE>B</CODE> , on a three-state bus <CODE>TSTATE</CODE>
, enabled by signals <CODE>OEA</CODE> and <CODE>OEB</CODE> . The drivers
are enabled by declaring a guard expression after the block declaration
and using the keyword <CODE>guarded</CODE> in the assignment statements.
A disconnect statement [<A HREF="../../VHDL/LRM/HTML/1076_5.HTM#5.3">VHDL LRM5.3</A>]
models the driver delay from driving the bus to the high-impedance state
(time to "float").</P>
<PRE><B>library</B> ieee; <B>use</B> ieee.std_logic_1164.<B>all</B>;
<B>entity</B> bus_drivers <B>is</B> <B>end</B>;
<B>architecture</B> Structure_1 <B>of</B> bus_drivers <B>is</B>
<B>signal</B> TSTATE: STD_LOGIC <B>bus</B>; <B>signal</B> A, B, OEA, OEB : STD_LOGIC:= '0';
<B>begin</B>
<B>process</B> <B>begin</B> OEA <= '1' <B>after</B> 100 ns, '0' <B>after</B> 200 ns;
OEB <= '1' <B>after</B> 300 ns; <B>wait</B>; <B>end</B> <B>process</B>;
B1 : <B>block</B> (OEA = '1')
<B>disconnect</B> <B>all </B>: STD_LOGIC <B>after</B> 5 ns; -- Only needed for float time.
<B>begin</B> TSTATE <= <B>guarded</B> <B>not</B> A <B>after</B> 3 ns; <B>end</B> <B>block</B>;
B2 : <B>block</B> (OEB = '1')
<B>disconnect</B> <B>all </B>: STD_LOGIC <B>after</B> 5 ns; -- Float time = 5 ns.
<B>begin</B> TSTATE <= <B>guarded</B> <B>not</B> B <B>after</B> 3 ns; <B>end</B> <B>block</B>;
<B>end</B>;
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</PRE>
<P><P CLASS="Body"><A NAME="pgfId=465573"></A>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:</P>
<PRE><B>architecture</B> Structure_2 <B>of</B> bus_drivers <B>is</B>
<B>signal</B> TSTATE : STD_LOGIC; <B>signal</B> A, B, OEA, OEB : STD_LOGIC := '0';
<B>begin</B>
<B>process</B> <B>begin</B>
OEA <= '1' <B>after</B> 100 ns, '0' <B>after</B> 200 ns; OEB <= '1' <B>after</B> 300 ns; <B>wait</B>; <B>end</B> <B>process</B>;
<B>process</B>(OEA, OEB, A, B) <B>begin</B>
<B> if </B> (OEA = '1') <B>then</B> TSTATE <= <B>not</B> A <B>after</B> 3 ns;
<B> elsif</B> (OEB = '1') <B>then</B> TSTATE <= <B>not</B> B <B>after</B> 3 ns;
<B> else</B> TSTATE <= 'Z' <B>after</B> 5 ns;
<B> end</B> <B>if</B>;
<B>end</B> <B>process</B>;
<B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=465873"></A>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
<CODE>'Z'</CODE> on the RHS of an assignment statement as a cue to synthesize
a three-state driver. It is up to you to make sure that multiple drivers
are never enabled simultaneously to cause contention.</P>
<H3><A NAME="pgfId=1958"></A>10.13.2 Process Statement</H3>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=10533"></A>A process statement
has the following format [<A HREF="../../VHDL/LRM/HTML/1076_9.HTM#9.2">VHDL LRM9.2</A>]:</P>
<PRE>process_statement ::=
[process_label:]
<U>[<B>postponed</B>]</U> <B>process</B> [(<I>signal_</I>name {, <I>signal_</I>name})]
<U>[is]</U> {subprogram_declaration | subprogram_body
| type_declaration | subtype_declaration
| constant_declaration | variable_declaration
| file_declaration | alias_declaration
| attribute_declaration | attribute_specification
| use_clause
<U>| group_declaration </U> <U>| group_template_declaration</U>}
<B>begin </B>
{sequential_statement}
<B>end</B> <U>[postponed]</U> <B>process</B> [<I>process_</I>label];</PRE>
<P><P CLASS="Body"><A NAME="pgfId=209412"></A>The following process models
a 2:1 MUX (combinational logic):</P>
<PRE><B>entity</B> Mux_1 <B>is</B> <B>port</B> (i0, i1, sel : <B>in</B> BIT := '0'; y : <B>out</B> BIT); <B>end</B>;
<B>architecture</B> Behave <B>of</B> Mux_1 <B>is</B>
<B>begin</B> <B>process</B> (i0, i1, sel) <B>begin</B> -- i0, i1, sel = sensitivity set
<B>case</B> sel <B>is</B> <B>when</B> '0' => y <= i0; <B>when</B> '1' => y <= i1; <B>end</B> <B>case</B>;
<B>end</B> <B>process</B>; <B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=366192"></A>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.</P>
<P><P CLASS="Body"><A NAME="pgfId=222849"></A>The following code models
a two-input AND gate (combinational logic):</P>
<PRE><B>entity</B> And_1 <B>is</B> <B>port</B> (a, b : <B>in</B> BIT := '0'; y : <B>out</B> BIT); <B>end</B>;
<B>architecture</B> Behave <B>of</B> And_1 <B>is</B>
<B>begin process</B> (a, b) <B>begin</B> y <= a <B>and</B> b; <B>end</B> <B>process</B>; <B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=209706"></A>The next example models a
D flip-flop (sequential logic). The<CODE> process </CODE>statement is executed
whenever there is an event on <CODE>clk</CODE> . The <CODE>if</CODE> statement
updates the output <CODE>q</CODE> with the input <CODE>d</CODE> on the rising
edge of the signal <CODE>clk</CODE> . If the <CODE>if</CODE> statement condition
is false (as it is on the falling edge of <CODE>clk</CODE> ), then the assignment
statement <CODE>q <= d</CODE> will not be executed, and <CODE>q</CODE>
will keep its previous value. The process thus requires the value of <CODE>q</CODE>
to be stored between successive process executions, and this implies sequential
logic.</P>
<PRE><B>entity</B> FF_1 <B>is</B> <B>port</B> (clk, d: <B>in</B> BIT := '0'; q : <B>out</B> BIT); <B>end</B>;
<B>architecture</B> Behave <B>of</B> FF_1 <B>is</B>
<B>begin process</B> (clk) <B>begin</B>
<B>if</B> clk'EVENT <B>and</B> clk = '1' <B>then</B> q <= d; <B>end</B> <B>if</B>;
<B>end</B> <B>process</B>; <B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=209720"></A>The behavior of the next example
is identical to the previous model. Notice that the <CODE>wait</CODE> statement
is at the end of the equivalent process with the signals in the sensitivity
set (in this case just one signal, <CODE>clk</CODE> ) included in the sensitivity
list (that follows the keyword <CODE>on</CODE> ).</P>
<PRE><B>entity</B> FF_2 <B>is</B> <B>port</B> (clk, d: <B>in</B> BIT := '0'; q : <B>out</B> BIT); <B>end</B>;
<B>architecture</B> Behave <B>of</B> FF_2 <B>is</B>
<B>begin process</B> <B>begin</B> -- The equivalent process has a wait at the end:
<B>if</B> clk'event <B>and</B> clk = '1' <B>then</B> q <= d; <B>end</B> <B>if</B>; <B>wait</B> <B>on</B> clk;
<B>end</B> <B>process</B>; <B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=209548"></A>If we use a <CODE>wait</CODE>
statement in a <CODE>process</CODE> statement, then we may not use a process
sensitivity set (the reverse is true: If we do not have a sensitivity set
for a process, we must include a <CODE>wait</CODE> statement or the process
will execute endlessly):</P>
<PRE><B>entity</B> FF_3 <B>is</B> <B>port</B> (clk, d: <B>in</B> BIT := '0'; q : <B>out</B> BIT); <B>end</B>;
<B>architecture</B> Behave <B>of</B> FF_3 <B>is</B>
<B>begin process</B> <B>begin</B> -- No sensitivity set with a wait statement.
<B>wait</B> <B>until</B> clk = '1'; q <= d;
<B>end</B> <B>process</B>; <B>end</B>;</PRE>
<P><P CLASS="Body"><A NAME="pgfId=2050"></A>If you include ports (interface
signals) in the sensitivity set of a <CODE>process</CODE> statement, they
must be ports that can be read (they must be of mode <CODE>in</CODE> , <CODE>inout</CODE>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?