VHDL For Synthesis: Summary Notes From: Appendix A: Synthesis The Designer's Guide To VHDL, 2 Ed
VHDL For Synthesis: Summary Notes From: Appendix A: Synthesis The Designer's Guide To VHDL, 2 Ed
1
Writing VHDL for Synthesis
• Motivation
• Synthesizable Data Types
• Combinational Circuits
• Latch Examples
• RTL for Finite State Machines
2
Why do we care?
• If the code is not synthesizable, then it can
be very inefficient (too slow, too much
power, may not be able to implement)
• What else do we gain?
– We can expect optimization tools to provide us
with different solutions, optimizing the design
for speed, area, and possibly power.
3
A Subset of VHDL Only
Majority of the synthesis tools accept:
• A subset of VHDL commands:
– What do we do with all the rest of VHDL?
We use it for testing:
• Writing test-benches
• Provide a simpler version of the architecture (for testing)
Mostly Avoid?
• Yes, except when it is extremely simple to not-ignore and
• Based on the IEEE libraries (hoping to get support later)
– IEEE Standard is for VHDL Register Transfer Level Synthesis
(RTL)
Thus, we must always CHECK AT THE RTL LEVEL.
4
IEEE Synthesis Standard in 1999
Supports VHDL-87 ONLY
VHDL-87 only supports:
• ASCII character set (not full)
• Following are not supported:
group, impure, inertial, literal, postponed,
pure, reject, rol, ror, shared,
sla, sll, sra, srl, unaffected, xnor, protected.
• See: Appendix F of Designer’s Guide to VHDL,
2nd ed.
5
Synthesizable Data Types
• Enumeration types, including: boolean, bit, character
• integer types, including integer
• One-dimensional arrays of scalars, including: bit_vector and
strings
• IEEE std_logic_1164 types:
std_ulogic, std_ulogic_vector, std_logic, std_logic_vector
• IEEE numeric_bit package types: unsigned and signed
• IEEE numeric_std package types: unsigned and signed
6
Synthesizable Scalar Types
• The following will be implemented as bits:
– boolean, bit, std_ulogic, std_logic
• Other enumerated types are implemented as the synthesis tool decides to
do!
• We can force the encoding using strings:
attribute enum_encoding : string;
• We can force the state assignment using:
type state is (idle, preamble, data, crc, ok, error);
attribute enum_encoding of state: type is
“000 001 010 011 100 111”;
Use the same number of bits!
List them in ascending order if using “<“ or “>”.
7
Working with Integers
Supports up to 32-bit integers:
– range: -231 to 231-1.
Examples:
Unsigned integers:
• Use unsigned definition from numeric_bit
and numeric_std IEEE libraries.
11
How Assignments Affect
Synthesis
The synthesis tool will mostly ignore ‘U’, ‘Z’, ‘X’ and all the other values.
After synthesis, every bit level is mapped to 0 or 1.
If we assign a ‘Z’ to a variable, it will be implemented as a tri-state buffer.
Eg:
request <= ‘Z’;
-- will implement a tri-state buffer to drive request.
This guarantees that we will get the same results in simulation and
synthesis. Eg:
std_match (‘0’, ‘0’) -- returns true
std_match (‘0’, ‘1’) -- returns false
12
Remembering Buffers …
13
Combinational Circuits: Muxes
For multiplexer logic, use “select”:
with addr(1 downto 0) select
request <= request_a when “00”,
request_b when “01”,
request_c when “10”,
request_d when “11”;
15
Combinational: first process
example
read_sample : process (read_enable, sample, limit_exceeded, ready)
begin
if std_match(read_enable, ‘1’) then
data <= sample;
parity <= calc_parity(sample);
status <= ready and not limit_exceeded;
else
data <= sample;
parity <= calc_parity(sample);
status <= ready and not limit_exceeded;
end if;
end process read_sample;
16
Combinational: first process
example comments
• every variable/signal appearing in the right-hand-side of an
assignment or in the if-statement, also appeared in the
sensitivity list EXCEPT for local variables/signals. Note
that local variables cannot appear in a sensitivity list.
– satisfies first requirement
• every execution thread involved assigning all the variables
– satisfies second requirement
• there are no variables in this process!
– satisfies third requirement
17
Combinational: second process
example
adder : process (sel, a, b, c) -- all relevant inputs
variable operand : integer; -- LOCAL variable. Not in sensitivity list.
begin -- all execution threads must assign operand.
if sel=‘1’ then
operand := a; -- operand assigned and NOT READ
else
operand := b; -- operand assigned and NOT READ
end if;
sum <= operand + c; -- operand has already been assigned. READ IS OK
end process adder; -- no need for storage for operand!
18
Sequential Circuits: General
Comments
• No support for synthesizing asynchronous
circuits. Asynchronous means that we do
not have a Clock or an Enable signal.
• Only support for synthesizing synchronous
circuits (clock or enable must be present)
• Clock signal must be defined to be of type:
bit, std_ulogic or its subtype(s) (eg: std_logic)
19
Simplest Example of Edge
triggered process
process_label : process (clock_signal_name)
begin
-- see next slides for proper definitions
-- of valid clock_edge statements.
if clock_edge then
-- NO wait statements allowed!
-- NO references to an edge allowed!
sequential_statements;
end if;
end process_label;
20
Proper Definitions of a Rising
Edge
rising_edge (clock_signal_name) -- best one! from IEEE library …
21
Proper Definitions of a Falling
Edge
falling_edge (clock_signal_name) -- best one! from IEEE library …
22
Synchronous Counter with
Asynchronous Controls
count_byte: process (clk, rst_n, load, load_data) – sens. list: clk + async controls
variable count : unsigned(7 downto 0);
begin
if std_match(rst_n, ‘0’) then -- async negated reset
count := “00000000”;
q <= count; -- q is a signal defined elsewhere.
elsif std_match(load, ‘1’) then -- async load
count := load_data;
q <= count;
elsif rising_edge(clk) then -- only one check for the edge!
count := count + 1; -- count IS a STATIC variable implying storage.
q <= count; -- NOTE that we need storage for this to work.
end if;
end process count_byte;
23
A second template for
synchronous controls
shift_reg : process
variable stored_value : bit_vector(7 downto 0);
begin
-- wait statement must be first statement (no more allowed)
wait until clk=‘1’ -- rising edge. It will be ‘0’ here for falling edge
if load=‘1’ then -- synchronous load
stored_value := load_data_in; -- load_data_in externally defined
q <= stored_value;
else
-- NOTE that stored_value MUST be STORED for this to work.
stored_value := stored_value(6 downto 0) & serial_data_in;
q <= stored_value;
end if;
end process shift_reg;
24
Level-sensitive Logic
• No Clock signal present
• Usually, an enable signal is used (eg: latches)
30
Modeling Finite State Machines (III of III)
-- the second process is here to define the logic for the register that stores
-- the current state. It has an asynchronous reset input.
state_reg : process (clk, reset)
begin
if reset=‘1’ then
current_state <= ready;
elsif clk’event and clk=‘1’ then
current_state <= next_state; -- note the assignment for next_state
end if; -- causing next_state to be read.
end
end rtl;
31
Metacomments
The synthesis tool will ignore all the code
Between (not case sensitive):
-- rtl_synthesis off
…
-- rtl_synthesis on
However, the simulator will interpret them as
regular code.
32
Xilinx Tutorial Using ISE
http://direct.xilinx.com/direct/ise8_tutorials/ise8tut.pdf
33