0% found this document useful (0 votes)
45 views33 pages

VHDL For Synthesis: Summary Notes From: Appendix A: Synthesis The Designer's Guide To VHDL, 2 Ed

This document discusses writing VHDL code for synthesis into hardware. It explains that only a subset of VHDL commands are synthesizable and describes synthesizable data types like integers, arrays, and enumerated types. It provides examples of combinational logic like multiplexers and sequential logic like edge-triggered processes. Key points are that all inputs must be in the sensitivity list, all outputs must be assigned, and variables must be assigned before being read to avoid latches.

Uploaded by

sridharmir
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views33 pages

VHDL For Synthesis: Summary Notes From: Appendix A: Synthesis The Designer's Guide To VHDL, 2 Ed

This document discusses writing VHDL code for synthesis into hardware. It explains that only a subset of VHDL commands are synthesizable and describes synthesizable data types like integers, arrays, and enumerated types. It provides examples of combinational logic like multiplexers and sequential logic like edge-triggered processes. Key points are that all inputs must be in the sensitivity list, all outputs must be assigned, and variables must be assigned before being read to avoid latches.

Uploaded by

sridharmir
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 33

VHDL for Synthesis

Summary notes from:


Appendix A: Synthesis
The Designer’s Guide to VHDL, 2nd 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

NB: No fixed-point numbers and no floating point!

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:

type sample is range –64 to 63;


will make sample a 7-bit, two’s complement integer.

type table_index is natural range 0 to 1023;


will implement table_index as a 10-bit unsigned number.
8
Defining Arrays that Can be
Synthesized in Hardware
We require STATIC (fixed) integer bounds and a type that is
implemented in bits!

Valid Array Definitions:


type coeffs is array (3 downto 0) of integer; -- 4 n-bits elements

type channel_states is array (0 to 7) of state; -- 8 m-bits elements


-- assuming that state is an enumeration type

subtype word is bit_vector (31 downto 0); -- 32 single bits


type reg_file is array (0 to 15) of word; -- 16 32-bit elements
9
The following cannot be
synthesized!
type color is array (red, green, blue);
type plane_status is array (color) of boolean;
-- color is NOT an integer! (should have worked though!)

type matrix is array (1 to 3, 1 to 3) of real;


-- CANNOT synthesize 2-D arrays (would have been nice!)
-- CANNOT synthesize floating-point numbers (not yet!)

type reg_file_set is array (0 to 3) of reg_file;


-- the elements are vectors of non-bits! (see previous slide)
10
For Signed and Unsigned
Integers USE …
Signed integers:
• Use signed definition from numeric_bit
and numeric_std IEEE libraries.

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.

Use the std_match function from the numeric_std IEEE library


for comparing instead of using ‘=‘!

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”;

Do not use “else” statement unless you want to


implement a priority encoder!
14
Combinational Circuits: Rules
for Processes
We can use a process statement with:
• process must be sensitive to all its inputs
• all outputs must be assigned in all
possible executions
• variable(s) must be assigned before read
– if this condition is violated, then the variable is
implemented using storage (not combinational)

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 …

clock_signal_name’event and clock_signal_name=‘1’


clock_signal_name=‘1’ and clock_signal_name’event

-- in what follows, note that not has precedence over and


-- also, note that ‘stable is an attribute for signals
not clock_signal_name’stable and clock_signal_name=‘1’
clock_signal_name=‘1’ and not clock_signal_name’stable

21
Proper Definitions of a Falling
Edge
falling_edge (clock_signal_name) -- best one! from IEEE library …

clock_signal_name’event and clock_signal_name=‘0’


clock_signal_name=‘0’ and clock_signal_name’event

-- in what follows, note that not has precedence over and


-- also, note that ‘stable is an attribute for signals
not clock_signal_name’stable and clock_signal_name=‘0’
clock_signal_name=‘0’ and not clock_signal_name’stable

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)

Provide storage if:


• There is an execution path that does not assign all
signals/variables
• When a signal/variable is read before being
assigned (when there is no Clock signal)
25
First Latch Example
latch : process (enable, d) – Need: enable and read (see below)
-- sensitivity list includes all variables/signals read.
begin
-- Place everything within an if-statement of
-- the enabling signal. Place sequential statements afterwards
if enable = ‘1’ then -- enable is read here
q <= d; -- d is read here
end if;
end process latch;
-- Note that if enable is zero, there is no value stored for q. Thus, we
-- need a storage element for implementing q (NOT combinational)
26
When is a signal/variable “read”?
A signal is read if:
• it appears on the right-hand-side of any
assignment
• it appears in any conditional expression

Basically, if a signal/variable appears in the


body of a process (or procedure, …), and it is
not just assigned values, then it is “read”.
27
A Second Latch Example
latch_with_reset : process (enable, reset, d)
variable stored_value : bit;
begin
if reset=‘1’ then
stored_value := ‘0’;
elsif enable=‘1’ then -- stored_value is not assigned
stored_value := d; -- when reset=enable=0.
end if; -- Thus, we create storage for it!
q <= stored_value;
end process latch_with_reset;
28
Modeling Finite State Machines (I of III)
architecture rtl of state_machine is
type state is (ready, ack, err);
signal current_code, next_state : state;
begin
-- Define two processes inside the architecture:
-- 1. A combinational process (call next_state_and_output), and
-- 2. A register process for storing the current state (state_reg).

next_state_and_output : process (current_state, in1, in2)


-- everything depends on: current state and all the inputs.
begin
case current_state is -- case statement for parallel implementation.
when ready =>
-- Here, current_state=ready, provide the logic for computing
29
-- the next_state
Modeling Finite State Machines (II of III)
out1 <= ‘0’; -- Note that ALL outputs and current_state
if in1 = ‘0’ then -- are assigned on EVERY execution path.
out2 <= ‘1’; -- Else, synthesis may not be combinational.
next_state <= ack;
else
out2 <= ‘0’;
next_state <= ready;
end if;
when ack => -- Similarly. Make sure to do this for ALL states.

when err =>

end case;
end process next_state_and_output;

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

You might also like