ch10.16.htm

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

HTM
545
字号
<HTML>

<HEAD>

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

  

  <TITLE> 10.16&nbsp;	An Engine Controller</TITLE>

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





<P><A NAME="pgfId=65561"></A><A HREF="CH10.htm">Chapter&nbsp;&nbsp;start</A>&nbsp;&nbsp;&nbsp;<A

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



<H2>10.16&nbsp; An Engine Controller</H2>



<P><P CLASS="BodyAfterHead"><A NAME="pgfId=426080"></A>This section describes

part of a controller for an automobile engine. Table&nbsp;10.21 shows a

temperature converter that converts digitized temperature readings from

a sensor from degrees Centigrade to degrees Fahrenheit.</P>



<P><TABLE BORDER="1" CELLSPACING="2" CELLPADDING="2">

<TR>

<TH COLSPAN="2" ALIGN="LEFT"><P ALIGN=LEFT><P CLASS="TableTitle"><A NAME="pgfId=428261"></A>TABLE&nbsp;10.21&nbsp;&nbsp;&nbsp;&nbsp;A

temperature converter.</TH></TR>

<TR>

<TD ROWSPAN="2" VALIGN="TOP"><PRE><B>library</B> IEEE; 

<B>use</B> IEEE.STD_LOGIC_1164.<B>all</B>; -- type STD_LOGIC, rising_edge

<B>use</B> IEEE.NUMERIC_STD.<B>all</B> ; -- type UNSIGNED, &quot;+&quot;, &quot;/&quot; 

<B>entity</B> tconv <B>is generic </B>TPD : TIME:= 1 ns;

	<B>port</B> (T_in : <B>in</B> UNSIGNED(11 <B>downto</B> 0);

	clk, rst : <B>in</B> STD_LOGIC; T_out : <B>out</B> UNSIGNED(11 <B>downto</B> 0)); 

<B>end</B>;

<B>architecture</B> rtl <B>of</B> tconv <B>is</B>

<B>signal</B> T : UNSIGNED(7 <B>downto</B> 0);

<B>constant</B> T2 &nbsp;: UNSIGNED(1 <B>downto</B> 0) := &quot;10&quot; ;

<B>constant</B> T4 &nbsp;: UNSIGNED(2 <B>downto</B> 0) := &quot;100&quot; ;

<B>constant</B> T32 : UNSIGNED(5 <B>downto</B> 0) := &quot;100000&quot; ;

<B>begin</B> 

<B>	process</B>(T) <B>begin</B> T_out &lt;= T + T/T2 + T/T4 + T32 <B>after</B> TPD;

<B>	end</B> <B>process</B>;

<B>end</B> rtl;</PRE>

</TD>

<TD ROWSPAN="2"><P><P CLASS="TableLeft"><A NAME="pgfId=463945"></A><CODE>T_in</CODE> = temperature

in degC</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=463911"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=463912"></A><CODE>T_out</CODE> =

temperature in degF</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=428335"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=464581"></A>The conversion formula

from Centigrade to Fahrenheit is:</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=465025"></A>T(degF) = (9/5) x T(degC)

+ 32</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=464585"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=463931"></A>This converter uses the

approximation:</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=463932"></A>9/5 = 1.75 = 1 + 0.5

+ 0.25</TD></TR>

<TR></TR>

</TABLE>

<P CLASS="Body"><A NAME="pgfId=445069"></A>To save area the temperature

conversion is approximate. Instead of multiplying by 9/5 and adding 32 (so

0 degC becomes 32 degF and 100 degC becomes 212 degF) we multiply by 1.75

and add 32 (so 100 degC becomes 207 degF). Since 1.75 = 1 + 0.5 + 0.25,

we can multiply by 1.75 using shifts (for divide by 2, and divide by 4)

together with a very simple constant addition (since 32 = &quot;100000&quot;).

Using shift to multiply and divide by powers of 2 is free in hardware (we

just change connections to a bus). For large temperatures the error approaches

0.05/1.8 or approximately 3 percent. We play these kinds of tricks often

in hardware computation. Notice also that temperatures measured in degC

and degF are defined as unsigned integers of the same width. We could have

defined these as separate types to take advantage of VHDL's type checking.</P>



<P><P CLASS="Body"><A NAME="pgfId=464464"></A>Table&nbsp;10.22 describes

a digital filter to compute a &quot;moving average&quot; over four successive

samples in time (i(0), i(1), i(2), and i(3), with <CODE>i(0)</CODE> being

the first sample).</P>



<P><TABLE BORDER="1" CELLSPACING="2" CELLPADDING="2">

<TR>

<TH COLSPAN="2" ALIGN="LEFT"><P ALIGN=LEFT><P CLASS="TableTitle"><A NAME="pgfId=464962"></A>TABLE&nbsp;10.22&nbsp;&nbsp;&nbsp;&nbsp;A

digital filter.</TH></TR>

<TR>

<TD ROWSPAN="2" VALIGN="TOP"><PRE><B>library</B> IEEE; 

<B>use</B> IEEE.STD_LOGIC_1164.<B>all</B>; -- STD_LOGIC type, rising_edge

<B>use</B> IEEE.NUMERIC_STD.<B>all</B>; -- UNSIGNED type, &quot;+&quot; and &quot;/&quot;

<B>entity</B> filter <B>is </B>

	<B>generic </B>TPD : TIME := 1 ns;

	<B>port</B> (T_in : <B>in</B> UNSIGNED(11 <B>downto</B> 0); 

	rst, clk : <B>in</B> STD_LOGIC; 

	T_out: <B>out</B> UNSIGNED(11 <B>downto</B> 0));

<B>end</B>;

<B>architecture</B> rtl <B>of</B> filter <B>is</B>

<B>type</B> arr <B>is</B> <B>array</B> (0 <B>to</B> 3) <B>of</B> UNSIGNED(11 <B>downto</B> 0); 

<B>signal</B> i : arr ;

<B>constant</B> T4 : UNSIGNED(2 <B>downto</B> 0) := &quot;100&quot;; 

<B>begin</B> 

	<B>process</B>(rst, clk) <B>begin</B>

		<B>if</B> (rst = '1') <B>then</B>

			<B>for</B> n <B>in</B> 0 <B>to</B> 3 <B>loop </B>i(n) &lt;= (<B>others</B> =&gt;'0') <B>after</B> TPD; 

<B>			end</B> <B>loop</B>; 

		<B>else</B> 

<B>			if</B>(rising_edge(clk)) <B>then</B>

			i(0) &lt;= T_in <B>after</B> TPD;i(1) &lt;= i(0) <B>after</B> TPD;

			i(2) &lt;= i(1) <B>after</B> TPD;i(3) &lt;= i(2) <B>after</B> TPD;

			<B>end</B> <B>if</B>;

		<B>end</B> <B>if</B>;

	<B>end</B> <B>process</B>;

	<B>process</B>(i) <B>begin</B>

		T_out &lt;= ( i(0) + i(1) + i(2) + i(3) )/T4 <B>after</B> TPD;

	<B>end</B> <B>process</B>;

<B>end</B> rtl;</PRE>

</TD>

<TD ROWSPAN="2"><P><P CLASS="TableLeft"><A NAME="pgfId=465002"></A>The filter computes a

moving average over four successive samples in time.</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503071"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503051"></A>Notice</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503052"></A>i(0) i(1) i(2) i(3)</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503069"></A>are each 12 bits wide.</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503072"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503070"></A>Then the sum</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503073"></A>i(0) + i(1) + i(2) +

i(3)</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503082"></A>is 14 bits wide, and

the</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503124"></A>average</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503083"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503084"></A>( i(0) + i(1) + i(2)

+ i(3) )/T4</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503089"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503090"></A>is 12 bits wide.</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503095"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503096"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503097"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=503098"></A>All delays are generic

<CODE>TPD</CODE> .</P>



<P>&nbsp;</TD></TR>

<TR></TR>

</TABLE>

<P CLASS="Body"><A NAME="pgfId=538672"></A>The filter uses the following

formula:</P>



<P><P CLASS="EqnNmbrdAlign"><A NAME="pgfId=538673"></A><CODE>T_out &lt;=

( i(0) + i(1) + i(2) + i(3) )/T4</CODE></P>



<P><P CLASS="Body"><A NAME="pgfId=538674"></A>Division by <CODE>T4 = &quot;100&quot;</CODE>

is free in hardware. If instead, we performed the divisions before the additions,

this would reduce the number of bits to be added for two of the additions

and saves us worrying about overflow. The drawback to this approach is round-off

errors. We can use the register shown in Table&nbsp;10.23 to register the

inputs.</P>



<P><TABLE BORDER="1" CELLSPACING="2" CELLPADDING="2">

<TR>

<TH COLSPAN="2" ALIGN="LEFT"><P ALIGN=LEFT><P CLASS="TableTitle"><A NAME="pgfId=538682"></A>TABLE&nbsp;10.23&nbsp;&nbsp;&nbsp;&nbsp;The

input register.</TH></TR>

<TR>

<TD ROWSPAN="2"><PRE><B>library</B> IEEE; 

<B>use</B> IEEE.STD_LOGIC_1164.<B>all</B>; -- type STD_LOGIC, rising_edge

<B>use</B> IEEE.NUMERIC_STD.<B>all</B> ; -- type UNSIGNED 

<B>entity</B> register_in <B>is</B> 

<B>generic</B> ( TPD : TIME := 1 ns); 

<B>port</B> (T_in : <B>in</B> UNSIGNED(11 downto 0);

clk, rst : <B>in</B> STD_LOGIC; T_out : <B>out</B> UNSIGNED(11 <B>downto</B> 0)); <B>end</B>;

<B>architecture</B> rtl <B>of</B> register_in <B>is</B>

<B>begin</B> 

<B>	process</B>(clk, rst) <B>begin</B> 

<B>		if</B> (rst = '1') <B>then </B>T_out &lt;= (<B>others</B> =&gt; '0') <B>after</B> TPD; 

		<B>else</B> 

		<B>if</B> (rising_edge(clk)) <B>then</B> T_out &lt;= T_in <B>after</B> TPD; <B>end</B> <B>if</B>;

<B>		end</B> <B>if</B>;

<B>	end</B> <B>process</B>;

<B>end</B> rtl ;</PRE>

</TD>

<TD ROWSPAN="2"><P><P CLASS="TableLeft"><A NAME="pgfId=538707"></A>12-bit-wide register

for the temperature input</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538708"></A>signals.</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538709"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538710"></A>If the input is asynchronous

(from an A/D</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538711"></A>converter with a separate

clock, for example), we would need to worry about metastability.</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538712"></A>&nbsp;</P>



<P><P CLASS="TableLeft"><A NAME="pgfId=538713"></A>All delays are generic

<CODE>TPD</CODE> .</TD></TR>

<TR></TR>

</TABLE>

<P CLASS="Body"><A NAME="pgfId=464940"></A>Table&nbsp;10.24 shows a first-in,

first-out stack (FIFO). This allows us to buffer the signals coming from

the sensor until the microprocessor has a chance to read them. The depth

of the FIFO will depend on the maximum amount of time that can pass without

the microcontroller being able to read from the bus. We have to determine

this with statistical simulations taking into account other traffic on the

bus.</P>



<P><TABLE BORDER="1" CELLSPACING="2" CELLPADDING="2">

<TR>

<TH COLSPAN="2" ALIGN="LEFT"><P ALIGN=LEFT><P CLASS="TableTitle"><A NAME="pgfId=464866"></A>TABLE&nbsp;10.24&nbsp;&nbsp;&nbsp;&nbsp;A

first-in, first-out stack (FIFO).</TH></TR>

<TR>

<TD ROWSPAN="2" VALIGN="TOP"><PRE><B>library</B> IEEE; <B>use</B> IEEE.NUMERIC_STD.<B>all</B> ; -- UNSIGNED type

<B>use</B> ieee.std_logic_1164.<B>all</B>; -- STD_LOGIC type, rising_edge

<B>entity</B> fifo <B>is</B> 

<B>	generic</B> (width : INTEGER := 12; depth : INTEGER := 16);

	<B>port</B> (clk, rst, push, pop : STD_LOGIC;

	Di : <B>in</B> UNSIGNED (width-1 <B>downto</B> 0);

	Do : <B>out</B> UNSIGNED (width-1 <B>downto</B> 0);

	empty, full : <B>out</B> STD_LOGIC);

<B>end</B> fifo;

<B>architecture</B> rtl <B>of</B> fifo <B>is</B>

<B>subtype</B> ptype <B>is</B> INTEGER <B>range</B> 0 <B>to</B> (depth-1);

<B>signal</B> diff, Ai, Ao : ptype; <B>signal</B>  f, e : STD_LOGIC;

<B>type</B> a <B>is</B> <B>array</B> (ptype) <B>of</B> UNSIGNED(width-1 <B>downto</B> 0);

<B>signal</B> mem : a ; 

<B>function</B> bump(<B>signal</B> ptr : INTEGER <B>range</B> 0 <B>to</B> (depth-1))

<B>return</B> INTEGER <B>is</B> <B>begin</B> 

	<B>if</B> (ptr = (depth-1)) <B>then</B> <B>return</B> 0; 

	<B>else</B> <B>return</B> (ptr + 1);

	<B>end</B> <B>if</B>;

<B>end</B>; 

<B>begin</B>

	<B>process</B>(f,e) <B>begin</B> full &lt;= f ; empty &lt;= e; <B>end</B> <B>process</B>;

	<B>process</B>(diff) <B>begin</B>

	<B>if</B> (diff = depth -1) <B>then</B> f &lt;= '1'; <B>else</B> f &lt;= '0'; <B>end</B> <B>if</B>;

	<B>if</B> (diff = 0) <B>then</B> e &lt;= '1'; <B>else</B> e &lt;= '0'; <B>end</B> <B>if</B>; 

	<B>end</B> <B>process</B>;

	<B>process</B>(clk, Ai, Ao, Di, mem, push, pop, e, f) <B>begin</B>

	<B>if</B>(rising_edge(clk)) <B>then</B> 

	<B>if</B>(push='0')<B>and</B>(pop='1')<B>and</B>(e = '0') <B>then</B> Do &lt;= mem(Ao); <B>end</B> <B>if</B>;

	<B>if</B>(push='1')<B>and</B>(pop='0')<B>and</B>(f = '0') <B>then</B> mem(Ai) &lt;= Di; <B>end</B> <B>if</B>;

	<B>end</B> <B>if</B> ; 

	<B>end</B> <B>process</B>;

	<B>process</B>(rst, clk)  <B>begin</B>

		<B>if</B>(rst = '1') <B>then</B> Ai &lt;= 0; Ao &lt;= 0; diff &lt;= 0;

		<B>else</B> <B>if</B>(rising_edge(clk)) <B>then</B> 

			<B>if</B> (push = '1') <B>and</B> (f = '0') <B>and</B> (pop = '0') <B>then</B>

				Ai &lt;= bump(Ai); diff &lt;= diff + 1; 

			<B>elsif</B> (pop = '1') <B>and</B> (e = '0') <B>and</B> (push = '0') <B>then</B>

				Ao &lt;= bump(Ao); diff &lt;= diff - 1;

			<B>end</B> <B>if</B>;

		<B>end</B> <B>if</B>;

		<B>end</B> <B>if</B>; 

	<B>end</B> <B>process</B>;

<B>end</B>;</PRE>

⌨️ 快捷键说明

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