ch11.05.htm

来自「介绍asci设计的一本书」· HTM 代码 · 共 199 行

HTM
199
字号
<HTML>

<HEAD>

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

  

  <TITLE> 11.5&nbsp;&nbsp;&nbsp;Procedures and Assignments</TITLE>

</HEAD><!--#include file="top.html"--><!--#include file="header.html"--><br><!--#include file="AmazonAsic.html"-->





<P><A NAME="pgfId=6800"></A><HR ALIGN="LEFT"></P>



<P><A HREF="CH11.htm">Chapter&nbsp;start</A></P>



<P><A HREF="CH11.04.htm">Previous page</A></P>



<P><A HREF="CH11.06.htm">Next page</A></P>



<H1>11.5&nbsp;&nbsp;&nbsp;Procedures and Assignments</H1>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=6802"></A>A Verilog<B> procedure</B>

[Verilog LRM&nbsp;9.9] is an <CODE>always</CODE> or <CODE>initial</CODE>

statement, a <CODE>task</CODE> , or a <CODE>function</CODE> . The statements

within a sequential block (statements that appear between a <CODE>begin</CODE>

and an <CODE>end</CODE> ) that is part of a procedure execute sequentially

in the order in which they appear, but the procedure executes concurrently

with other procedures. This is a fundamental difference from computer programming

languages. Think of each procedure as a microprocessor running on its own

and at the same time as all the other microprocessors (procedures). Before

I discuss procedures in more detail, I shall discuss the two different types

of assignment statements:</P>



<UL>

  <LI><A NAME="pgfId=6807"></A>continuous assignments that appear outside

  procedures

  <LI><A NAME="pgfId=6808"></A>procedural assignments that appear inside

  procedures

</UL>



<P><P CLASS="Body"><A NAME="pgfId=6809"></A>To illustrate the difference

between these two types of assignments, consider again the example used

in <A HREF="CH11.04.htm">Section&nbsp;11.4</A>:</P>



<PRE>

<B>module</B> holiday_1(sat, sun, weekend);

&nbsp;&nbsp;<B>input</B> sat, sun; <B>output</B> weekend;

&nbsp;&nbsp;<B>assign</B> weekend = sat | sun; // Assignment outside a procedure.

<B>endmodule</B></PRE>



<P><P CLASS="Body"><A NAME="pgfId=72228"></A>We can change weekend to a<CODE>

reg</CODE> instead of a <CODE>wire</CODE> , but then we must declare weekend

and use a procedural assignment (inside a procedure--an <CODE>always</CODE>

statement, for example) instead of a continuous assignment. We also need

to add some delay (one time tick in the example that follows); otherwise

the computer will never be able to get out of the <CODE>always</CODE> procedure

to execute any other procedures:</P>



<PRE>

<B>module</B> holiday_2(sat, sun, weekend);

&nbsp;&nbsp;<B>input</B> sat, sun; <B>output</B> weekend; <B>reg</B> weekend;

&nbsp;&nbsp;<B>always</B> #1 weekend = sat | sun; // Assignment inside a procedure.

<B>endmodule</B></PRE>



<P><P CLASS="Body"><A NAME="pgfId=82807"></A>We shall cover the continuous

assignment statement in the next section, which is followed by an explanation

of sequential blocks and procedural assignment statements. Here is some

skeleton code that illustrates where we may use these assignment statements:</P>



<PRE>

<B>module</B> assignments

//... Continuous assignments go here.

<B>always</B> // beginning of a procedure

&nbsp;&nbsp;<B>begin</B> // beginning of sequential block

&nbsp;&nbsp;//... Procedural assignments go here.

&nbsp;&nbsp;<B>end</B>

<B>endmodule</B></PRE>



<P><P CLASS="Body"><A NAME="pgfId=89899"></A><A HREF="CH11.06.htm#pgfId=82965">Table&nbsp;11.4

</A>at the end of <A HREF="CH11.06.htm">Section&nbsp;11.6</A> summarizes

assignment statements, including two more forms of assignment--you may want

to look at this table now.</P>



<H2><A NAME="pgfId=114445"></A>11.5.1&nbsp;&nbsp;&nbsp;Continuous Assignment

Statement</H2>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=914"></A>A <B>continuous assignment

statement</B> [Verilog LRM&nbsp;6.1] assigns a value to a<CODE> wire </CODE>in

a similar way that a real logic gate drives a real wire,</P>



<PRE>

<B>module</B> assignment_1();

<B>wire</B> pwr_good, pwr_on, pwr_stable; <B>reg</B> Ok, Fire;

<B>assign</B> pwr_stable = Ok &amp; (!Fire);

<B>assign</B> pwr_on = 1;  

<B>assign</B> pwr_good = pwr_on &amp; pwr_stable;

<B>initial</B> <B>begin</B> Ok = 0; Fire = 0; #1 Ok = 1; #5 Fire = 1; end

<B>initial</B> <B>begin</B> $monitor(&quot;TIME=%0d&quot;,$time,&quot; ON=&quot;,pwr_on, &quot; STABLE=&quot;,

&nbsp;&nbsp;&nbsp;&nbsp;pwr_stable,&quot; OK=&quot;,Ok,&quot; FIRE=&quot;,Fire,&quot; GOOD=&quot;,pwr_good);

&nbsp;&nbsp;#10 $finish; <B>end</B> 

<B>endmodule</B> 

TIME=0 ON=1 STABLE=0 OK=0 FIRE=0 GOOD=0

TIME=1 ON=1 STABLE=1 OK=1 FIRE=0 GOOD=1

TIME=6 ON=1 STABLE=0 OK=1 FIRE=1 GOOD=0</PRE>



<P><P CLASS="Body"><A NAME="pgfId=8416"></A>The assignment statement in

this next example models a three-state bus:</P>



<PRE>

<B>module</B> assignment_2; <B>reg</B> Enable; <B>wire</B> [31:0] Data;

/* The following single statement is equivalent to a declaration and continuous assignment. */

<B>wire</B> [31:0] DataBus = Enable ? Data : 32'bz;

<B>assign</B> Data = 32'b10101101101011101111000010100001;

&nbsp;&nbsp;<B>initial begin</B>

&nbsp;&nbsp;&nbsp;&nbsp;$monitor(&quot;Enable=%b DataBus=%b &quot;, Enable, DataBus);

&nbsp;&nbsp;&nbsp;&nbsp;Enable = 0; #1; Enable = 1; #1; <B>end</B> 

<B>endmodule</B> 

Enable = 0 DataBus =zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

Enable = 1 DataBus =10101101101011101111000010100001</PRE>



<H2><A NAME="pgfId=7060"></A>11.5.2&nbsp;&nbsp;&nbsp;Sequential Block</H2>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=940"></A>A <B>sequential block</B>

[Verilog LRM&nbsp;9.8] is a group of statements between a <B>begin</B> and

an <B>end</B>. We may declare new variables within a sequential block, but

then we must name the block. A sequential block is considered a statement,

so that we may nest sequential blocks.</P>



<P><P CLASS="Body"><A NAME="pgfId=83141"></A>A sequential block may appear

in an <B>always statement</B> [Verilog LRM9.9.2], in which case the block

executes repeatedly. In contrast, an <B>initial statement</B> [Verilog LRM9.9.1]

executes only once, so a sequential block within an <CODE>initial</CODE>

statement only executes once--at the beginning of a simulation. It does

not matter where the <CODE>initial</CODE> statement appears--it still executes

first. Here is an example:</P>



<PRE>

<B>module</B> always_1; <B>reg</B> Y, Clk;

<B>always</B> // Statements in an always statement execute repeatedly:

<B>begin</B>: my_block // Start of sequential block.

&nbsp;&nbsp;@(<B>posedge</B> Clk) #5 Y = 1; // At +ve edge set Y=1,

&nbsp;&nbsp;@(<B>posedge</B> Clk) #5 Y = 0; // at the NEXT +ve edge set Y=0.

<B>end</B> // End of sequential block.

<B>always</B> #10 Clk = ~ Clk; // We need a clock.

<B>initial</B> Y = 0; // These initial statements execute 

<B>initial</B> Clk = 0; // only once, but first. 

<B>initial</B> $monitor(&quot;T=%2g&quot;,$time,&quot;  Clk=&quot;,Clk,&quot;  Y=&quot;,Y);

<B>initial</B> #70 $finish;

<B>endmodule</B>

T= 0  Clk=0  Y=0

T=10  Clk=1  Y=0

T=15  Clk=1  Y=1

T=20  Clk=0  Y=1

T=30  Clk=1  Y=1

T=35  Clk=1  Y=0

T=40  Clk=0  Y=0

T=50  Clk=1  Y=0

T=55  Clk=1  Y=1

T=60  Clk=0  Y=1</PRE>



<H2><A NAME="pgfId=972"></A>11.5.3&nbsp;&nbsp;&nbsp;Procedural Assignments</H2>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=976"></A>A <B>procedural assignment</B>

[Verilog LRM&nbsp;9.2] is similar to an assignment statement in a computer

programming language such as C. In Verilog the value of an expression on

the RHS of an assignment within a procedure (a procedural assignment) updates

a <CODE>reg</CODE> (or memory element) on the LHS. In the absence of any

<EM>timing controls</EM> (see <A HREF="CH11.06.htm">Section&nbsp;11.6</A>),

the <CODE>reg</CODE> is updated immediately when the statement executes.

The <CODE>reg</CODE> holds its value until changed by another procedural

assignment. Here is the BNF definition:</P>



<PRE>

blocking_assignment ::= reg-lvalue = [delay_or_event_control] expression</PRE>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=22541"></A>(Notice this BNF definition

is for a blocking assignment--a type of procedural assignment--see <A HREF="CH11.06.htm#pgfId=83894">Section&nbsp;11.6.4</A>.) Here is an example of

a procedural assignment (notice that a <CODE>wire</CODE> can only appear

on the RHS of a procedural assignment):</P>



<PRE>

<B>module</B> procedural_assign; <B>reg</B> Y, A;

<B>always</B> @(A) 

&nbsp;&nbsp;Y = A; // Procedural assignment.

<B>initial</B> <B>begin</B> A=0; #5; A=1; #5; A=0; #5; $finish; end 

<B>initial</B> $monitor(&quot;T=%2g&quot;,$time,,&quot;A=&quot;,A,,,&quot;Y=&quot;,Y);

<B>endmodule</B> 

T= 0 A=0  Y=0

T= 5 A=1  Y=1

T=10 A=0  Y=0</PRE>



<P><HR ALIGN="LEFT"></P>



<P><A HREF="CH11.htm">Chapter&nbsp;start</A></P>



<P><A HREF="CH11.04.htm">Previous page</A></P>



<P><A HREF="CH11.06.htm">Next page</A>

</BODY>



<!--#include file="Copyright.html"--><!--#include file="footer.html"-->

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?