ch11.05.htm
来自「介绍asci设计的一本书」· HTM 代码 · 共 199 行
HTM
199 行
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="Adobe PageMill 2.0 Mac">
<TITLE> 11.5 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 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 Procedures and Assignments</H1>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=6802"></A>A Verilog<B> procedure</B>
[Verilog LRM 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 11.4</A>:</P>
<PRE>
<B>module</B> holiday_1(sat, sun, weekend);
<B>input</B> sat, sun; <B>output</B> weekend;
<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);
<B>input</B> sat, sun; <B>output</B> weekend; <B>reg</B> weekend;
<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
<B>begin</B> // beginning of sequential block
//... Procedural assignments go here.
<B>end</B>
<B>endmodule</B></PRE>
<P><P CLASS="Body"><A NAME="pgfId=89899"></A><A HREF="CH11.06.htm#pgfId=82965">Table 11.4
</A>at the end of <A HREF="CH11.06.htm">Section 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 Continuous Assignment
Statement</H2>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=914"></A>A <B>continuous assignment
statement</B> [Verilog LRM 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 & (!Fire);
<B>assign</B> pwr_on = 1;
<B>assign</B> pwr_good = pwr_on & 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("TIME=%0d",$time," ON=",pwr_on, " STABLE=",
pwr_stable," OK=",Ok," FIRE=",Fire," GOOD=",pwr_good);
#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;
<B>initial begin</B>
$monitor("Enable=%b DataBus=%b ", Enable, DataBus);
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 Sequential Block</H2>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=940"></A>A <B>sequential block</B>
[Verilog LRM 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.
@(<B>posedge</B> Clk) #5 Y = 1; // At +ve edge set Y=1,
@(<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("T=%2g",$time," Clk=",Clk," Y=",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 Procedural Assignments</H2>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=976"></A>A <B>procedural assignment</B>
[Verilog LRM 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 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 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)
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("T=%2g",$time,,"A=",A,,,"Y=",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 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 + -
显示快捷键?