📄 ch02.18.htm
字号:
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="Adobe PageMill 2.0 Mac">
<TITLE> 2.6.6 Other Datapath Operators</TITLE>
</HEAD><!--#include file="top.html"--><!--#include file="header.html"-->
<P><A NAME="pgfId=195929"></A><HR ALIGN=LEFT></P>
<P><A HREF="CH02.12.htm">Chapter start</A> <A
HREF="CH02.17.htm">Previous page</A> <A HREF="CH02.19.htm">Next page</A></P>
<H2>2.6.6 Other Datapath Operators</H2>
<P><P CLASS="BodyAfterHead"><A NAME="pgfId=195915"></A>Figure 2.32
shows symbols for some other datapath elements. The combinational datapath
cells, NAND, NOR, and so on, and sequential datapath cells (flip-flops and
latches) have standard-cell equivalents and function identically. I use
a bold outline (1<SPAN CLASS="White"> </SPAN>point)
for datapath cells instead of the regular (0.5<SPAN CLASS="White"> </SPAN>point)
line I use for scalar symbols. We call a set of identical cells a <B>vector</B>
of datapath elements in the same way that a bold symbol, <B>A</B> , represents
a vector and A represents a scalar.</P>
<P><TABLE BORDER="0" CELLSPACING="2" CELLPADDING="0">
<TR>
<TD><P><P CLASS="TableFigure"><A NAME="pgfId=195922"></A> </P>
<P><IMG SRC="CH02-112.gif" WIDTH="452" HEIGHT="166" NATURALSIZEFLAG="3"
ALIGN="BOTTOM"></TD></TR>
<TR>
<TD><P CLASS="TableFigureTitle"><A NAME="pgfId=195926"></A>FIGURE 2.32 Symbols
for datapath elements. (a) An array or vector of flip-flops (a register).
(b) A two-input NAND cell with databus inputs. (c) A two-input
NAND cell with a control input. (d) A buswide MUX. (e) An incrementer/decrementer.
(f) An all-zeros detector. (g) An all-ones detector. (h) An
adder/subtracter.</TD></TR>
</TABLE>
<P CLASS="Body"><A NAME="pgfId=99793"></A>A <B>subtracter</B> is similar
to an adder, except in a <B>full subtracter </B>we have a borrow-in signal,
BIN; a borrow-out signal, BOUT; and a difference signal, DIFF:</P>
<P><P CLASS="EqnNmbrdAlign"><A NAME="pgfId=99886"></A> DIFF<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>A<SPAN CLASS="White"> </SPAN><SPAN CLASS="Symbol">
</SPAN> <SPAN CLASS="White"> </SPAN>NOT(B)<SPAN CLASS="Symbol">
<SPAN CLASS="White"> </SPAN><SPAN CLASS="White"> </SPAN>NOT(</SPAN>
BIN)<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>SUM(A,
NOT(B), NOT(BIN))(2.65)</P>
<P><P CLASS="EquationAlign"><A NAME="pgfId=99887"></A> NOT(BOUT)<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>A<SPAN CLASS="White"> </SPAN>·<SPAN CLASS="White"> </SPAN>NOT(B)<SPAN CLASS="White"> </SPAN>+<SPAN CLASS="White"> </SPAN>A<SPAN CLASS="White"> </SPAN>·<SPAN CLASS="White"> </SPAN>NOT(BIN)<SPAN CLASS="White"> </SPAN>+<SPAN CLASS="White"> </SPAN>NOT(B)<SPAN CLASS="White"> </SPAN>·<SPAN CLASS="White"> </SPAN>NOT(BIN)</P>
<P><P CLASS="EqnNmbrdAlign"><A NAME="pgfId=99898"></A> <SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>MAJ(NOT(A),
B, NOT(BIN))(2.66)</P>
<P><P CLASS="Body"><A NAME="pgfId=100048"></A>These equations are the same
as those for the FA (Eqs. 2.38 and 2.39) except that the B input is
inverted and the sense of the carry chain is inverted. To build a subtracter
that calculates (A<SPAN CLASS="White"> </SPAN><SPAN CLASS="White"> </SPAN>B)
we invert the entire B input bus and connect the BIN[0] input to VDD (not
to VSS as we did for CIN[0] in an adder). As an example, to subtract B<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0011'
from A<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'1001'
we calculate '1001'<SPAN CLASS="White"> </SPAN>+<SPAN CLASS="White"> </SPAN>'1100'<SPAN CLASS="White"> </SPAN>+<SPAN CLASS="White"> </SPAN>'1'<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN><SPAN CLASS="White"> </SPAN>'0110'.
As with an adder, the true overflow is XOR(BOUT[MSB], BOUT[MSB<SPAN CLASS="White"> </SPAN><SPAN CLASS="White"> </SPAN>1]).</P>
<P><P CLASS="Body"><A NAME="pgfId=99979"></A>We can build a ripple-borrow
subtracter (a type of borrow-propagate subtracter), a borrow-save subtracter,
and a borrow-select subtracter in the same way we built these adder architectures.
An <B>adder/subtracter</B> has a control signal that gates the A input with
an exclusive-OR cell (forming a programmable inversion) to switch between
an adder or subtracter. Some adder/subtracters gate both inputs to allow
us to compute (A<SPAN CLASS="White"> </SPAN><SPAN CLASS="White"> </SPAN>B).
We must be careful to connect the input to the LSB of the carry chain (CIN[0]
or BIN[0]) when changing between addition (connect to VSS) and subtraction
(connect to VDD).</P>
<P><P CLASS="Body"><A NAME="pgfId=89197"></A>A <B>barrel shifter</B> rotates
or shifts an input bus by a specified amount. For example if we have an
eight-input barrel shifter with input '1111 0000' and we specify a
shift of '0001 0000' (3, coded by bit position) the right-shifted 8-bit
output is '0001 1110'. A barrel shifter may rotate left or right (or
switch between the two under a separate control). A barrel shifter may also
have an output width that is smaller than the input. To use a simple example,
we may have an 8-bit input and a 4-bit output. This situation is equivalent
to having a barrel shifter with two 4-bit inputs and a 4-bit output. Barrel
shifters are used extensively in floating-point arithmetic to align (we
call this <B>normalize</B> and <B>denormalize</B> ) floating-point numbers
(with sign, exponent, and mantissa).</P>
<P><P CLASS="Body"><A NAME="pgfId=99485"></A>A <B>leading-one detector</B>
is used with a normalizing (left-shift) barrel shifter to align mantissas
in floating-point numbers. The input is an <SPAN CLASS="EquationVariables">
n</SPAN> -bit bus A, the output is an <SPAN CLASS="EquationVariables"> n</SPAN>
-bit bus, S, with a single '1' in the bit position corresponding to the
most significant '1' in the input. Thus, for example, if the input is A<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0000 0101'
the leading-one detector output is S<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0000 0100',
indicating the leading one in A is in bit position 2 (bit 7 is the MSB,
bit zero is the LSB). If we feed the output, S, of the leading-one detector
to the shift select input of a normalizing (left-shift) barrel shifter,
the shifter will normalize the input A. In our example, with an input of
A<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0000 0101',
and a left-shift of S<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0000 0100',
the barrel shifter will shift A left by five bits and the output of the
shifter is Z<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'1010 0000'.
Now that Z is aligned (with the MSB equal to '1') we can multiply Z with
another normalized number.</P>
<P><P CLASS="Body"><A NAME="pgfId=99707"></A>The output of a <B>priority
encoder</B> is the binary-encoded position of the leading one in an input.
For example, with an input A<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0000 0101'
the leading 1 is in bit position 3 (MSB is bit position 7) so the output
of a 4-bit priority encoder would be Z<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0011'
(3). In some cell libraries the encoding is reversed so that the MSB has
an output code of zero, in this case Z<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>'0101'
(5). This second, reversed, encoding scheme is useful in floating-point
arithmetic. If A is a mantissa and we normalize A to '1010 0000' we
have to subtract 5 from the exponent, this <B>exponent correction</B> is
equal to the output of the priority encoder.</P>
<P><P CLASS="Body"><A NAME="pgfId=129141"></A>An <B>accumulator</B> is an
adder/subtracter and a register. Sometimes these are combined with a multiplier
to form a <B>multiplieraccumulator</B> (<B> MAC</B> ). An <B>incrementer</B>
adds 1 to the input bus, Z<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>
A<SPAN CLASS="White"> </SPAN>+<SPAN CLASS="White"> </SPAN>1,
so we can use this function, together with a register, to negate a two's
complement number for example. The implementation is Z[<SPAN CLASS="EquationVariables">
i</SPAN> ]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>XOR(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]), and COUT[<SPAN CLASS="EquationVariables">
i</SPAN> ]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>AND(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]). The carry-in
control input, CIN[0], thus acts as an enable: If it is set to '0' the output
is the same as the input.</P>
<P><P CLASS="Body"><A NAME="pgfId=100166"></A>The implementation of arithmetic
cells is often a little more complicated than we have explained. CMOS logic
is naturally inverting, so that it is faster to implement an incrementer
as</P>
<P><P CLASS="Equation"><A NAME="pgfId=100156"></A>Z[<SPAN CLASS="EquationVariables">
i</SPAN> (even)]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>XOR(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]) and COUT[<SPAN CLASS="EquationVariables">
i</SPAN> (even)]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>NAND(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]).</P>
<P><P CLASS="Body"><A NAME="pgfId=100165"></A>This inverts COUT, so that
in the following stage we must invert it again. If we push an inverting
bubble to the input CIN we find that:</P>
<P><P CLASS="Equation"><A NAME="pgfId=100169"></A>Z[<SPAN CLASS="EquationVariables">
i</SPAN> (odd)]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>XNOR(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]) and COUT[<SPAN CLASS="EquationVariables">
i</SPAN> (even)]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>NOR(NOT(A[<SPAN CLASS="EquationVariables">
i</SPAN> ]), CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]).</P>
<P><P CLASS="Body"><A NAME="pgfId=100151"></A>In many datapath implementations
all odd-bit cells operate on inverted carry signals, and thus the odd-bit
and even-bit datapath elements are different. In fact, all the adder and
subtracter datapath elements we have described may use this technique. Normally
this is completely hidden from the designer in the datapath assembly and
any output control signals are inverted, if necessary, by inserting buffers.</P>
<P><P CLASS="Body"><A NAME="pgfId=100182"></A>A <B>decrementer</B> subtracts
1 from the input bus, the logical implementation is Z[<SPAN CLASS="EquationVariables">
i</SPAN> ]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>XOR(A[<SPAN CLASS="EquationVariables">
i</SPAN> ], CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]) and COUT[<SPAN CLASS="EquationVariables">
i</SPAN> ]<SPAN CLASS="White"> </SPAN>=<SPAN CLASS="White"> </SPAN>AND(NOT(A[<SPAN CLASS="EquationVariables">
i</SPAN> ]), CIN[<SPAN CLASS="EquationVariables"> i</SPAN> ]). The implementation
may invert the odd carry signals, with CIN[0] again acting as an enable.</P>
<P><P CLASS="Body"><A NAME="pgfId=100198"></A>An <B>incrementer/decrementer</B>
has a second control input that gates the input, inverting the input to
the carry chain. This has the effect of selecting either the increment or
decrement function.</P>
<P><P CLASS="Body"><A NAME="pgfId=89779"></A>Using the <B>all-zeros detectors</B>
and <B>all-ones detectors</B> , remember that, for a 4-bit number, for example,
zero in ones' complement arithmetic is '1111' or '0000', and that zero in
signed magnitude arithmetic is '1000' or '0000'.</P>
<P><P CLASS="Body"><A NAME="pgfId=86986"></A>A <B>register file</B> (or
scratchpad memory) is a bank of flip-flops arranged across the bus; sometimes
these have the option of multiple ports (multiport register files) for read
and write. Normally these register files are the densest logic and hardest
to fit in a datapath. For large register files it may be more appropriate
to use a multiport memory. We can add control logic to a register file to
create a <B>first-in first-out register</B> (<B> FIFO</B> ), or <B>last-in
first-out register</B> (<B> LIFO</B> ).</P>
<P><P CLASS="Body"><A NAME="pgfId=142494"></A>In Section 2.5 we saw
that the standard-cell version and gate-array macro version of the sequential
cells (latches and flip-flops) each contain their own clock buffers. The
reason for this is that (without intelligent placement software) we do not
know where a standard cell or a gate-array macro will be placed on a chip.
We also have no idea of the condition of the clock signal coming into a
sequential cell. The ability to place the clock buffers outside the sequential
cells in a datapath gives us more flexibility and saves space. For example,
we can place the clock buffers for all the clocked elements at the top of
the datapath (together with the buffers for the control signals) and <B>river
route</B> (in river routing the interconnect lines all flow in the same
direction on the same layer) the connections to the clock lines. This saves
space and allows us to guarantee the clock skew and timing. It may mean,
however, that there is a fixed overhead associated with a datapath. For
example, it might make no sense to build a 4-bit datapath if the clock and
control buffers take up twice the space of the datapath logic. Some tools
allow us to design logic using a <B>portable netlist</B> . After we complete
the design we can decide whether to implement the portable netlist in a
datapath, standard cells, or even a gate array, based on area, speed, or
power considerations.</P>
<P><HR ALIGN=LEFT></P>
<P><A HREF="CH02.12.htm">Chapter start</A> <A
HREF="CH02.17.htm">Previous page</A> <A HREF="CH02.19.htm">Next page</A>
</BODY>
<!--#include file="Copyright.html"--><!--#include file="footer.html"-->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -