ch10.13.htm

来自「介绍asci设计的一本书」· HTM 代码 · 共 427 行 · 第 1/2 页

HTM
427
字号
<HTML>

<HEAD>

  <META NAME="GENERATOR" CONTENT="Adobe PageMill 2.0 Mac">

  

  <TITLE> 10.13&nbsp;	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&nbsp;&nbsp;start</A>&nbsp;&nbsp;&nbsp;<A HREF="CH10.12.htm">Previous

page</A>&nbsp;&nbsp;<A HREF="CH10.14.htm">Next&nbsp;&nbsp;page</A></P>



<H2>10.13&nbsp; 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&nbsp; 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 &quot;float&quot;).</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 &lt;= '1' <B>after</B> 100 ns, '0' <B>after</B> 200 ns; 

OEB &lt;= '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 &lt;= <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 &lt;= <B>guarded</B> <B>not</B> B <B>after</B> 3 ns; <B>end</B> <B>block</B>;

<B>end</B>;

&nbsp;

                             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 &lt;= '1' <B>after</B> 100 ns, '0' <B>after</B> 200 ns; OEB &lt;= '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&nbsp;&nbsp;&nbsp;</B> (OEA = '1') <B>then</B> TSTATE &lt;= <B>not</B> A <B>after</B> 3 ns; 

<B>	elsif</B> (OEB = '1') <B>then</B> TSTATE &lt;= <B>not</B> B <B>after</B> 3 ns; 

<B>	else</B> TSTATE &lt;= '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&nbsp; 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>&nbsp;<B>process</B>&nbsp; [(<I>signal_</I>name&nbsp;{,&nbsp;<I>signal_</I>name})]

<U>[is]</U>&nbsp;{subprogram_declaration	|&nbsp;subprogram_body

&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;type_declaration	|&nbsp;subtype_declaration

&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;constant_declaration	|&nbsp;variable_declaration

&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;file_declaration	|&nbsp;alias_declaration

&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;attribute_declaration	|&nbsp;attribute_specification

&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;use_clause

&nbsp;&nbsp;&nbsp;&nbsp;<U>|&nbsp;group_declaration&nbsp;</U>	<U>|&nbsp;group_template_declaration</U>}

<B>begin </B>

	{sequential_statement}

<B>end</B>&nbsp;<U>[postponed]</U>&nbsp;<B>process</B>&nbsp;[<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' =&gt; y &lt;= i0; <B>when</B> '1' =&gt; y &lt;= 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 &lt;= 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&nbsp;&lt;=&nbsp;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 &lt;= 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 &lt;= 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 &lt;= 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 + -
显示快捷键?