12.6
VHDL and Logic Synthesis
Most logic synthesizers insist we follow a set of rules when we use a logic system to ensure that what we synthesize matches the behavioral description. Here is a typical set of rules for use with the IEEE VHDL nine-value system:
-
You can use logic values corresponding to states
'1'
,
'H'
,
'0'
, and
'L'
in any manner.
-
Some synthesis tools do not accept the uninitialized logic state
'U'
.
-
You can use logic states
'Z'
,
'X'
,
'W'
, and
'-'
in signal and variable assignments in any manner.
'Z'
is synthesized to three-state logic.
-
The states
'X'
,
'W'
, and
'-'
are treated as unknown or don’t care values.
The values
'Z'
,
'X'
,
'W'
, and
'-'
may be used in conditional clauses such as the comparison in an
if
or
case
statement. However, some synthesis tools will ignore them and only match surrounding
'1'
and
'0'
bits. Consequently, a synthesized design may behave differently from the simulation if a stimulus uses
'Z'
,
'X'
,
'W'
or
'-'
. The IEEE synthesis packages provide the
STD_MATCH
function for comparisons.
12.6.1
Initialization and Reset
You can use a VHDL
process
with a
sensitivity list to synthesize clocked logic with a reset, as in the following code:
process
(signal_1, signal_2)
begin
if
(signal_2'EVENT
and
signal_2 = '0')
then
-- Insert initialization and reset statements.
elsif
(signal_1'EVENT
and
signal_1 = '1')
then
-- Insert clocking statements.
end
if
;
end process
;
Using a specific pattern the synthesizer can infer that you are implying a positive-edge clock (
signal_1
) and a negative-edge reset (
signal_2
). In order to be able to recognize sequential logic in this way, most synthesizers restrict you to using a maximum of two edges in a sensitivity list.
12.6.2 Combinational Logic Synthesis in VHDL
In VHDL a
level-sensitive process
is a
process
statement that has a sensitivity list with signals that are not tested for event attributes (
'EVENT
or
'STABLE
, for example) within the
process
. To synthesize combinational logic we use a VHDL level-sensitive
process
or a concurrent assignment statement. Some synthesizers do not allow reference to a signal inside a level-sensitive
process
unless that signal is in the sensitivity list. In this example, signal
b
is missing from the sensitivity list:
entity
And_Bad
is port
(a, b:
in
BIT; c:
out
BIT);
end
And_Bad;
architecture
Synthesis_Bad
of
And_Bad
is
begin process
(a) -- this should be process (a, b)
begin
c <= a
and
b;
end
process
;
end
Synthesis_Bad;
This situation is similar but not exactly the same as omitting a variable from an event control in a Verilog
always
statement. Some logic synthesizers accept the VHDL version of
And_Bad
but not the Verilog version or vice versa. To ensure that the VHDL simulation will match the behavior of the synthesized logic, the logic synthesizer usually checks the sensitivity list of a level-sensitive
process
and issues a warning if signals seem to be missing.
12.6.3 Multiplexers in VHDL
Multiplexers can be synthesized using a
case
statement (avoiding the VHDL reserved word
'select'
), as the following example illustrates:
entity
Mux4
is port
(i: BIT_VECTOR(3
downto
0); sel: BIT_VECTOR(1
downto
0); s:
out
BIT);
end
Mux4;
architecture
Synthesis_1
of
Mux4
is
begin
process
(sel, i)
begin
case
sel
is
when
"00" => s <= i(0);
when
"01" => s <= i(1);
when
"10" => s <= i(2);
when
"11" => s <= i(3);
end
case
;
end
process
;
end
Synthesis_1;
The following code, using a concurrent signal assignment is equivalent:
architecture
Synthesis_2
of
Mux4
is
begin with
sel
select
s <=
i(0)
when
"00", i(1)
when
"01", i(2)
when
"10", i(3)
when
"11";
end
Synthesis_2;
In VHDL the
case
statement must be exhaustive in either form, so there is no question of any priority in the choices as there may be in Verilog.
For larger MUXes we can use an array, as in the following example:
library
IEEE;
use
ieee.std_logic_1164.
all
;
entity
Mux8
is port
(InBus :
in
STD_LOGIC_VECTOR(7
downto
0);
Sel :
in
INTEGER
range
0 to 7;
OutBit :
out
STD_LOGIC);
end
Mux8;
architecture
Synthesis_1
of
Mux8
is
begin
process
(InBus, Sel)
begin
OutBit <= InBus(Sel);
end
process
;
end
Synthesis_1;
Most synthesis tools can infer that, in this case,
Sel
requires three bits. If not, you have to declare the signal as a
STD_LOGIC_VECTOR
,
Sel :
in
STD_LOGIC_VECTOR(2
downto
0);
and use a conversion routine from the
STD_NUMERIC
package like this:
OutBit <= InBus(TO_INTEGER ( UNSIGNED (Sel) ) ) ;
At some point you have to convert from an
INTEGER
to
BIT
logic anyway, since you cannot connect an
INTEGER
to the input of a chip! The VHDL
case
,
if
, and
select
statements produce similar results. Assigning
don’t care bits (
'x'
) in these statements will make it easier for the synthesizer to optimize the logic.
12.6.4 Decoders in VHDL
The following code implies a
decoder:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
Decoder
is port
(enable :
in
BIT;
Din: STD_LOGIC_VECTOR (2
downto
0);
Dout:
out
STD_LOGIC_VECTOR (7
downto
0));
end
Decoder;
architecture
Synthesis_1
of
Decoder
is
begin
with
enable
select
Dout <=
STD_LOGIC_VECTOR
(UNSIGNED'
(shift_left
("00000001", TO_INTEGER (UNSIGNED(Din))
)
)
)
when
'1',
"11111111"
when
'0', "00000000"
when
others
;
end
Synthesis_1;
There are reasons for this seemingly complex code:
-
Line
1
declares the
IEEE library. The synthesizer does not parse the VHDL code inside the library packages, but the synthesis company should be able to guarantee that the logic will behave exactly the same way as a simulation that uses the IEEE libraries and does parse the code.
-
Line
2
declares the
STD_LOGIC_1164
package, for
STD_LOGIC
types, and the
NUMERIC_STD
package for conversion and shift functions. The shift
operators
(
sll
and so on–the infix operators) were introduced in VHDL-93, they are not defined for
STD_LOGIC
types in the 1164 standard. The shift
functions
defined in
NUMERIC_STD
are not operators and are called
shift_left
and so on. Some synthesis tools support
NUMERIC_STD
, but not VHDL-93.
-
Line
10
performs a type conversion to
STD_LOGIC_VECTOR
from
UNSIGNED
.
-
Line
11
is a type qualification to tell the software that the argument to the type conversion function is type
UNSIGNED
.
-
Line
12
is the shift function,
shift_left
, from the
NUMERIC_STD
package.
-
Line
13
converts the
STD_LOGIC_VECTOR
,
Din
, to
UNSIGNED
before converting to
INTEGER
. We cannot convert directly from
STD_LOGIC_VECTOR
to
INTEGER
.
-
The others clause in line
18
is required by the logic synthesizer even though type
BIT
may only be
'0'
or
'1'
.
If we model a decoder using a process, we can use a
case
statement inside the process. A MUX model may be used as a decoder if the input bits are set at
'1'
(active-high decoder) or at
'0'
(active-low decoder), as in the following example:
library
IEEE;
use
IEEE.NUMERIC_STD.
all
;
use
IEEE.STD_LOGIC_1164.
all
;
entity
Concurrent_Decoder
is port
(
enable :
in
BIT;
Din :
in
STD_LOGIC_VECTOR (2
downto
0);
Dout :
out
STD_LOGIC_VECTOR (7
downto
0));
end
Concurrent_Decoder;
architecture
Synthesis_1
of
Concurrent_Decoder
is
begin process
(Din, enable)
variable
T : STD_LOGIC_VECTOR(7
downto
0);
begin
if
(enable = '1')
then
T := "00000000"; T( TO_INTEGER (UNSIGNED(Din))) := '1';
Dout <= T ;
else
Dout <= (
others
=> 'Z');
end
if
;
end
process
;
end
Synthesis_1;
Notice that
T
must be a variable for proper timing of the update to the output. The
else
clause in the
if
statement is necessary to avoid inferring latches.
12.6.5 Adders in VHDL
To add two
n
-bit numbers and keep the overflow bit, we need to assign to a signal with more bits, as follows:
library
IEEE;
use
IEEE.NUMERIC_STD.
all
;
use
IEEE.STD_LOGIC_1164.
all
;
entity
Adder_1
is
port
(A, B:
in
UNSIGNED(3
downto
0); C:
out
UNSIGNED(4
downto
0));
end
Adder_1;
architecture
Synthesis_1
of
Adder_1
is
begin
C <= ('0' & A) + ('0' & B);
end
Synthesis_1;
Notice that both
A
and
B
have to be
SIGNED
or
UNSIGNED
as we cannot add
STD_LOGIC_VECTOR
types directly using the IEEE packages. You will get an error if a result is a different length from the target of an assignment, as in the following example (in which the arguments are not resized):
adder_1: begin C <= A + B;
Error
: Width mis-match: right expression is 4 bits wide, c is 5 bits wide
The following code may generate three adders stacked three deep:
z <= a + b + c + d;
Depending on how the expression is parsed, the first adder may perform
x = a + b
, a second adder
y = x + c
, and a third adder
z = y + d
. The following code should generate faster logic with three adders stacked only two deep:
z <= (a + b) + (c + d);
12.6.6 Sequential Logic in VHDL
Sensitivity to an edge implies sequential logic in VHDL. A synthesis tool can locate edges in VHDL by finding a
process
statement that has either:
-
no sensitivity list with a
wait until
statement
-
a sensitivity list and test for
'EVENT
plus a specific level
Any signal assigned in an edge-sensitive
process
statement should also be reset—but be careful to distinguish between asynchronous and synchronous resets. The following example illustrates these points:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
entity
DFF_With_Reset
is
port
(D, Clk, Reset :
in
STD_LOGIC; Q :
out
STD_LOGIC);
end
DFF_With_Reset;
architecture
Synthesis_1
of
DFF_With_Reset
is
begin
process
(Clk, Reset)
begin
if
(Reset = '0')
then
Q <= '0'; -- asynchronous reset
elsif
rising_edge(Clk)
then
Q <= D;
end
if
;
end
process
;
end
Synthesis_1;
architecture
Synthesis_2
of
DFF_With_Reset
is
begin
process
begin
wait
until
rising_edge(Clk);
-- This reset is gated with the clock and is synchronous:
if
(Reset = '0')
then
Q <= '0';
else
Q <= D;
end
if
;
end
process
;
end
Synthesis_2;
Sequential logic results when we have to “remember” something between successive executions of a
process
statement. This occurs when a
process
statement contains one or more of the following situations:
-
A signal is read but is not in the sensitivity list of a
process
statement.
-
A signal or variable is read before it is updated.
-
A signal is not always updated.
-
There are multiple
wait
statements.
Not all of the models that we could write using the above constructs will be synthesizable. Any models that do use one or more of these constructs and that are synthesizable will result in sequential logic.
12.6.7 Instantiation in VHDL
The easiest way to find out how to
hand instantiate a component is to generate a structural netlist from a simple HDL input—for example, the following Verilog behavioral description (VHDL could have been used, but the Verilog is shorter):
`timescale 1ns/1ns
module
halfgate (myInput, myOutput);
input
myInput;
output
myOutput;
wire
myOutput;
assign
myOutput = ~myInput;
endmodule
We synthesize this module and generate the following VHDL structural netlist:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
library
COMPASS_LIB;
use
COMPASS_LIB.COMPASS.
all
;
--compass compile_off -- synopsys etc.
use
COMPASS_LIB.COMPASS_ETC.
all
;
--compass compile_on -- synopsys etc.
entity
halfgate_u
is
--compass compile_off -- synopsys etc.
generic
(
myOutput_cap : Real := 0.01;
INSTANCE_NAME : string := "halfgate_u" );
--compass compile_on -- synopsys etc.
port
( myInput :
in
Std_Logic := 'U';
myOutput :
out
Std_Logic := 'U' );
end
halfgate_u;
architecture
halfgate_u
of
halfgate_u
is
component
in01d0
port
( I :
in
Std_Logic; ZN :
out
Std_Logic );
end
component
;
begin
u2: in01d0
port
map
( I => myInput, ZN => myOutput );
end
halfgate_u;
--compass compile_off -- synopsys etc.
library
cb60hd230d;
configuration
halfgate_u_CON
of
halfgate_u
is
for
halfgate_u
for
u2 : in01d0
use
configuration
cb60hd230d.in01d0_CON
generic
map
(
ZN_cap => 0.0100 + myOutput_cap,
INSTANCE_NAME => INSTANCE_NAME&"/u2" )
port
map
( I => I, ZN => ZN);
end
for
;
end
for
;
end
halfgate_u_CON;
--compass compile_on -- synopsys etc.
This gives a template to follow when hand instantiating logic cells. Instantiating a standard component requires the name of the component and its parameters:
component
ASDFF
generic
(WIDTH : POSITIVE := 1;
RESET_VALUE : STD_LOGIC_VECTOR := "0" );
port
(Q :
out
STD_LOGIC_VECTOR (WIDTH-1 downto 0);
D :
in
STD_LOGIC_VECTOR (WIDTH-1 downto 0);
CLK :
in
STD_LOGIC;
RST :
in
STD_LOGIC );
end
component
;
Now you have enough information to be able to instantiate both logic cells from a cell library and standard components. The following model illustrates instantiation:
library
IEEE, COMPASS_LIB;
use
IEEE.STD_LOGIC_1164.
all
;
use
COMPASS_LIB.STDCOMP.
all
;
entity
Ripple_4
is
port
(Trig, Reset: STD_LOGIC; QN0_5x:
out
STD_LOGIC;
Q :
inout
STD_LOGIC_VECTOR(0
to
3));
end
Ripple_4;
architecture
structure
of
Ripple_4
is
signal
QN : STD_LOGIC_VECTOR(0
to
3);
component
in01d1
port
( I : in Std_Logic; ZN : out Std_Logic );
end
component
;
component
in01d5
port
( I : in Std_Logic; ZN : out Std_Logic );
end
component
;
begin
--compass dontTouch inv5x -- synopsys dont_touch etc.
-- Named association for hand-instantiated library cells:
inv5x: IN01D5
port
map
( I=>Q(0), ZN=>QN0_5x );
inv0 : IN01D1
port
map
( I=>Q(0), ZN=>QN(0) );
inv1 : IN01D1
port
map
( I=>Q(1), ZN=>QN(1) );
inv2 : IN01D1
port
map
( I=>Q(2), ZN=>QN(2) );
inv3 : IN01D1
port
map
( I=>Q(3), ZN=>QN(3) );
-- Positional association for standard components:
-- Q D Clk Rst
d0: asDFF
port
map
(Q (0
to
0), QN(0
to
0), Trig, Reset);
d1: asDFF
port
map
(Q (1
to
1), QN(1
to
1), Q(0), Reset);
d2: asDFF
port
map
(Q (2
to
2), QN(2
to
2), Q(1), Reset);
d3: asDFF
port
map
(Q (3
to
3), QN(3
to
3), Q(2), Reset);
end
structure;
-
Lines
5
and
8
. Type
STD_LOGIC_VECTOR
must be used for standard component ports, because the standard components are defined using this type.
-
Line
5
. Mode
inout
has to be used for
Q
since it has to be read/write and this is a structural model. You cannot use mode
buffer
since the formal outputs of the standard components are declared to be of mode
out
.
-
Line
14
. This synthesis directive prevents the synthesis tool from removing the 5X drive strength inverter
inv5x
. This statement ties the code to a particular synthesis tool.
-
Lines
16
–
20
. Named association for the hand-instantiated library cells. The names (
IN01D5
and
IN01D1
) and port names (
I
and
ZN
) come from the cell library data book or from a template (such as the one created for the
IN01D1
logic cell). These statements tie the code to a particular cell library.
-
Lines
23
–
26
. Positional port mapping of the standard components. The port locations are from the synthesis standard component library documentation. These
asDFF
standard components will be mapped to D flip-flop library cells. These statements tie the code to a particular synthesis tool.
You would receive the following warning from the logic synthesizer when it synthesizes this input code (entity
Ripple_4
):
Warning
: Net has more than one driver: d3_Q[0]; connected to: ripple_4_p.q[3], inv3.I, d3.Q
There is potentially more than one
driver on a net because
Q
was declared as
inout
. There are a total of four warnings of this type for each of the flip-flop outputs. You can check the output netlist to make sure that you have the logic you expected as follows (the Verilog netlist is shorter and easier to read):
`timescale 1ns / 10ps
module
ripple_4_u (trig, reset, qn0_5x, q);
input
trig;
input
reset;
output
qn0_5x;
inout
[3:0] q;
wire
[3:0] qn;
supply1
VDD;
supply0
VSS;
in01d5 inv5x (.I(q[0]),.ZN(qn0_5x));
in01d1 inv0 (.I(q[0]),.ZN(qn[0]));
in01d1 inv1 (.I(q[1]),.ZN(qn[1]));
in01d1 inv2 (.I(q[2]),.ZN(qn[2]));
in01d1 inv3 (.I(q[3]),.ZN(qn[3]));
dfctnb d0(.D(qn[0]),.CP(trig),.CDN(reset),.Q(q[0]),.QN(\d0.QN ));
dfctnb d1(.D(qn[1]),.CP(q[0]),.CDN(reset),.Q(q[1]),.QN(\d1.QN ));
dfctnb d2(.D(qn[2]),.CP(q[1]),.CDN(reset),.Q(q[2]),.QN(\d2.QN ));
dfctnb d3(.D(qn[3]),.CP(q[2]),.CDN(reset),.Q(q[3]),.QN(\d3.QN ));
endmodule
12.6.8 Shift Registers and Clocking in VHDL
The following code implies a
serial-in/parallel-out (SIPO) shift register:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
SIPO_1
is port
(
Clk :
in
STD_LOGIC;
SI :
in
STD_LOGIC; -- serial in
PO :
buffer
STD_LOGIC_VECTOR(3
downto
0)); -- parallel out
end
SIPO_1;
architecture
Synthesis_1
of
SIPO_1
is
begin process
(Clk)
begin
if
(Clk
= '1'
)
then
PO <= SI & PO(3
downto
1);
end
if
;
end
process
;
end
Synthesis_1;
Here is the Verilog structural netlist that results (
dfntnb
is a positive-edge–triggered D flip-flop without clear or reset):
module
sipo_1_u (clk, si, po);
input
clk;
input
si;
output
[3:0] po;
supply1
VDD;
supply0
VSS;
dfntnb po_ff_b0 (.D(po[1]),.CP(clk),.Q(po[0]),.QN(\po_ff_b0.QN));
dfntnb po_ff_b1 (.D(po[2]),.CP(clk),.Q(po[1]),.QN(\po_ff_b1.QN));
dfntnb po_ff_b2 (.D(po[3]),.CP(clk),.Q(po[2]),.QN(\po_ff_b2.QN));
dfntnb po_ff_b3 (.D(si),.CP(clk),.Q(po[3]),.QN(\po_ff_b3.QN ));
endmodule
The synthesized design consists of four flip-flops. Notice that (line 6 in the VHDL input) signal
PO
is of mode
buffer
because we cannot read a signal of mode
out
inside a process. This is acceptable for synthesis but not usually a good idea for simulation models. We can modify the code to eliminate the
buffer
port and at the same time we shall include a reset signal, as follows:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
SIPO_R
is port
(
clk :
in
STD_LOGIC ; res :
in
STD_LOGIC ;
SI :
in
STD_LOGIC ; PO :
out
STD_LOGIC_VECTOR(3
downto
0));
end
;
architecture
Synthesis_1
of
SIPO_R
is
signal
PO_t : STD_LOGIC_VECTOR(3
downto
0);
begin
process
(PO_t)
begin
PO <= PO_t;
end
process
;
process
(clk, res)
begin
if
(res = '0')
then
PO_t <= (
others
=> '0');
elsif
(rising_edge(clk))
then
PO_t <= SI & PO_t(3
downto
1);
end
if
;
end
process
;
end
Synthesis_1;
Notice the following:
-
Line
10
uses a temporary signal,
PO_t
, to avoid using a port of mode
buffer
for the output signal
PO
. We could have used a variable instead of a signal and the variable would consume less overhead during simulation. However, we must complete an assignment to a variable inside the clocked process (not in a separate process as we can for the signal). Assignment between a variable and a signal inside a single process creates its own set of problems.
-
Line
11
is sensitive to the clock,
clk
, and the reset,
res
. It is not sensitive to
PO_t
or
SI
and this is what indicates the sequential logic.
-
Line
13
uses the
rising_edge
function from the
STD_LOGIC_1164
package.
The software synthesizes four positive-edge–triggered D flip-flops for design entity
SIPO_R(Synthesis_1)
as it did for design entity
SIPO_1(Synthesis_1)
. The difference is that the synthesized flip-flops in
SIPO_R
have active-low resets. However, the simulation behavior of these two design entities will be different. In
SIPO_R
, the function
rising_edge
only evaluates to
TRUE
for a transition from
'0'
or
'L'
to
'1'
or
'H'
. In
SIPO_1
we only tested for
Clk = '1'
. Since nearly all synthesis tools now accept
rising_edge
and
falling_edge
, it is probably wiser to use these functions consistently.
12.6.9 Adders and Arithmetic Functions
If you wish to perform
BIT_VECTOR
or
STD_LOGIC_VECTOR
arithmetic you have three choices:
-
Use a vendor-supplied package (there are no standard vendor packages—even if a company puts its own package in the IEEE library).
-
Convert to
SIGNED
(or
UNSIGNED
) and use the IEEE standard synthesis packages (IEEE Std 1076.3-1997).
-
Use overloaded functions in packages or functions that you define yourself.
Here is an example of addition using a ripple-carry architecture:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
Adder4
is port
(
in1, in2 :
in
BIT_VECTOR(3
downto
0) ;
mySum :
out
BIT_VECTOR(3
downto
0) ) ;
end
Adder4;
architecture
Behave_A
of
Adder4
is
function
DIY(L,R: BIT_VECTOR(3
downto
0))
return
BIT_VECTOR
is
variable
sum:BIT_VECTOR(3
downto
0);
variable
lt,rt,st,cry: BIT;
begin
cry := '0';
for
i
in
L'REVERSE_RANGE
loop
lt := L(i); rt := R(i); st := lt
xor
rt;
sum(i):= st
xor
cry; cry:= (lt
and
rt)
or
(st
and
cry);
end
loop
;
return
sum;
end
;
begin
mySum <= DIY (in1, in2); -- do it yourself (DIY) add
end
Behave_A;
This model results in random logic.
An alternative is to use
UNSIGNED
or
UNSIGNED
from the IEEE
NUMERIC_STD
or
NUMERIC_BIT
packages as in the following example:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
Adder4
is port
(
in1, in2 :
in
UNSIGNED(3
downto
0) ;
mySum :
out
UNSIGNED(3
downto
0) ) ;
end
Adder4;
architecture
Behave_B
of
Adder4
is
begin
mySum <= in1 + in2; -- This uses an overloaded '+'.
end
Behave_B;
In this case, the synthesized logic will depend on the logic synthesizer.
12.6.10
Adder/Subtracter and Don’t Cares
The following code models a 16-bit sequential
adder and subtracter. The input signal,
xin
, is added to output signal,
result
, when signal
addsub
is high; otherwise
result
is subtracted from
xin
. The internal signal
addout
temporarily stores the result until the next rising edge of the clock:
library
IEEE;
use
IEEE.STD_LOGIC_1164.
all
;
use
IEEE.NUMERIC_STD.
all
;
entity
Adder_Subtracter is
port
(
xin :
in
UNSIGNED(15
downto
0);
clk, addsub, clr:
in
STD_LOGIC;
result :
out
UNSIGNED(15
downto
0));
end
Adder_Subtracter;
architecture
Behave_A
of
Adder_Subtracter
is
signal
addout, result_t: UNSIGNED(15
downto
0);
begin
result <= result_t;
with
addsub
select
addout <= (xin + result_t)
when
'1',
(xin - result_t)
when
'0',
(
others
=> '-')
when
others
;
process
(clr, clk)
begin
if
(clr = '0')
then
result_t <= (
others
=> '0');
elsif
rising_edge(clk)
then
result_t <= addout;
end
if
;
end
process
;
end
Behave_A;
Notice the following:
-
Line
11
is a concurrent assignment to avoid using a port of mode
buffer
.
-
Lines
12
–
15
define an exhaustive list of choices for the selected signal assignment statement. The default choice sets the result to
'-'
(don’t care) to allow the synthesizer to optimize the logic.
Line
18
includes a reference to signal
addout
that could be eliminated by moving the selected signal assignment statement inside the clocked process as follows:
architecture
Behave_B
of
Adder_Subtracter
is
signal
result_t: UNSIGNED(15 downto 0);
begin
result <= result_t;
process
(clr, clk)
begin
if
(clr = '0')
then
result_t <= (
others
=> '0');
elsif
rising_edge(clk)
then
case
addsub
is
when
'1' => result_t <= (xin + result_t);
when
'0' => result_t <= (xin - result_t);
when
others
=> result_t <= (
others
=> '-');
end
case
;
end
if
;
end
process
;
end
Behave_B;
This code is simpler than architecture
Behave_A
, but the synthesized logic should be identical for both architectures. Since the logic that results is an adder/subtracter followed by a register (bank of flip-flops) the
Behave_A
model more clearly reflects the hardware.
[ Chapter start ] [ Previous page ] [ Next page ] |