Professional Documents
Culture Documents
, Calcutta University
acakcs@caluniv.ac.in
Introduction
VHDL is used to: document circuits simulate circuits synthesize design descriptions Synthesis is the reduction of a design description to a lowerlevel representation (such as a netlist or a set of equations). The lecture will at times draw upon the concepts of VHDL as a simulation language
The Entity
A BLACK BOX The ENTITY describes the periphery of the black box (i.e., the design I/O)
BLACK_BOX
rst
d[7:0] clk
q[7:0] co
q[7:0]
co
entity_name is an arbitrary name generics are used for defining parameterized components name is the signal/port identifier and may be a comma separated list for ports of identical modes and types mode describes the direction the data is flowing type indicates the set of values name may be assigned
Ports
The Entity (BLACK BOX) has PORTS
PORTS are the points of communication PORTS are usually the device pins PORTS have an associated name, mode, and type
Port Modes
A ports MODE indicates the direction that data is transferred:
Entity
IN OUT INOUT
Data goes into the entity only Data goes out of the entity only (and is not used internally) Data is bi-directional (goes into and out of the entity)
BUFFER Data that goes out of the entity and is also fed-back internally
IEEE Types
VHDL is a strongly typed language (you cannot assign a signal of one type to the signal of another type) bit - a signal of type bit that can only take values of '0' or '1' bit_vector - a grouping of bits (each can be '0' or '1')
SIGNAL SIGNAL a: BIT_VECTOR(0 TO 3); -- ascending range b: BIT_VECTOR(3 DOWNTO 0); -- descending range a <= "0111"; -- double quotes used for vectors b <= "0101"; This means that: a(0) = '0' b(0) = '1' a(1) = '1' b(1) = '0' a(2) = '1' b(2) = '1' a(3) = '1' b(3) = '0'
IEEE 1164
A package created to solve the limitations of the BIT type Nine values instead of just two ('0' and '1') Allows increased flexibility in VHDL coding, synthesis, and simulation STD_LOGIC and STD_LOGIC_VECTOR are used instead of BIT and BIT_VECTOR when a multi-valued logic system is required STD_LOGIC and STD_LOGIC _VECTOR must be used when tri-state logic (Z) is required To be able to use this new type, you need to add 2 lines to your code: LIBRARY ieee; USE ieee.std_logic_1164.ALL;
1164 Types
std_logic and std_logic_vector are the industry standard logic type for digital design Values for Simulation & Synthesis 0 -- Forcing 0 1 -- Forcing 1 Z -- High Impedance L -- Weak 0 H -- Weak 1 - -- Dont care Values for Simulation only (std_ulogic): U -- Uninitialized X -- Forcing Unknown W -- Weak Unknown
co
Port D is a 12-bit bus, input only Port OE and CLK are each input bits Port AD is a 12-bit, three-state bi-directional bus Port A is a 12-bit bus, output only Port INT is a three-state output Port AS is an output also used internally
my_design d[11:0] oe clk
ad[11:0]
a[11:0] int as
The Architecture
Architectures describe what is in the black box (i.e., the structure or behavior of entities) Descriptions can be either a combination of Structural descriptions Instantiations (placements of logic-much like in a schematic-and their connections) of building blocks referred to as components Behavioral/Dataflow descriptions Algorithmic (or high-level) descriptions:
IF a = b THEN state <= state5;
arch_name is an arbitrary name optional signal declarations are used for signals local to the architecture body (that is, not the entitys I/O). entity_name is the entity name statements describe the function or contents of the entity
a b
d f
c USE WORK.gatespkg.ALL; ARCHITECTURE archlogic OF logic IS SIGNAL d: std_logic; BEGIN Behavioral/Dataflow d <= a AND b; Structural g1: nor2 PORT MAP (c, d, f); END archlogic;
g1
A Simple Counter
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE WORK.std_arith.ALL; clk ENTITY count8 IS PORT ( clk: IN std_logic; count: BUFFER std_logic_vector(7 DOWNTO 0)); END count8 ; ARCHITECTURE arch_count8 OF count8 IS BEGIN upcount: PROCESS (clk) BEGIN IF clkEVENT and clk=1 THEN count <= count + 1; END IF; END PROCESS upcount; END arch_count8;
count
VHDL Statements
There are two types of statements, Concurrent and Sequential
Concurrent Statements (means in parallel) Concurrent statements are executed concurrently (at the same time)
The order of concurrent statements is not important Most of the examples we have seen so far have been concurrent statements: Boolean Equations WHEN-ELSE WITH-SELECT-WHEN
With Sequential statements, the ORDER of the statements is important (example later)
Therefore, we use a process to mark the beginning and end of a block of sequential statements
Each completed process is considered to be one big concurrent statement (there can be many processes inside one architecture)
Combinational Logic
Can be described with concurrent statements boolean equations when-else with-select-when component instantiatons Can be described with sequential statements if-then-else case-when
x <= (a AND NOT(s(1)) AND NOT(s(0))) OR (b AND NOT(s(1)) AND s(0)) OR (c AND s(1) AND NOT(s(0))) OR (d AND s(1) AND s(0)) ;
a b c d
mux
WITH selection_signal SELECT signal_name <= value_1 WHEN value_1 of selection_signal, value_2 WHEN value_2 of selection_signal, ... value_n WHEN value_n of selection_signal, value_x WHEN OTHERS;
a b c d
mux
More on with-select-when
You can use a range of values with int_value select x <= a when 0 to 3, b when 4 | 6 | 8 , c when 10 , d when others ;
a b c d
mux
if-then-else
4-1 mux shown below mux4_1: process (a, b, c, d, s) begin if s = 00 then x <= a ; elsif s = 01 then x <= b ; elsif s = 10 then x <= c ; else x <= d ; end if; end process mux4_1 ;
s
2
a b c d
mux
s
2
a b c d
mux
clock
clock
Therefore, on the previous slide, two registers will be synthesized (c <= b will be the old b)
In some cases, the use of a concurrent statement outside the process will fix the problem, but this is not always possible So how else can we fix this problem ?
Variables
When a concurrent signal assignment outside the process cannot be used, the previous problem can be avoided using a variable Variables are like signals, BUT they can only be used inside a PROCESS. They cannot be used to communicate information between processes Variables can be of any valid VHDL data type The value assigned to a variable is available immediately Assignment of variables is done using a colon (:), like this:
c := a AND b;
Native Operators
Logical - defined for type bit, bit_vector, boolean* AND, NAND OR, NOR XOR, XNOR NOT Relational - defined for types bit, bit_vector, integer* = (equal to) /= (not equal to) < (less than) <= (less than or equal to) > (greater than) >= (greater than or equal to) * overloaded for std_logic, std_logic_vector
Overloaded Operators
In VHDL, the scope of all of the previous operators can be extended (or overloaded) to accept any type supported by the language, e.g.,
-----
assume a declaration of a 16-bit vector as SIGNAL pc IS std_logic_vector(15 DOWNTO 0); then a valid signal assignment is pc <= pc + 3; assuming the '+' operator has been overloaded to accept std_logic_vector and integer operands
The std_logic_1164 package defines overloaded logical operators (AND, OR, NOT, etc.,) for the std_logic and std_logic_vector types In this training, you will learn to use overloaded operators, but not to define them
Write an architecture that causes aeqb to be asserted when a is equal to b Multiple solutions exist
aeqb
Produces the equation x = c To assign dont cares in VHDL: mysig <= '-'; 'X' means "unknown" and is not useful for synthesis
Comparing Vectors to Strings -more on don't cares Comparing "1101" to "11-1" will return FALSE Use std_match(a,"string") Must include std_arith package Example:
Signals can be pulled from larger vectors Good for grouping outputs as an alias Sizes on both sides of assignment must match
rw <= ctrl(0); ce <= ctrl(1); oe <= ctrl(2); highcount <= count(7 DOWNTO 4);
Synchronous Logic
PLDs work well in synchronous applications Two methods of creating synchronous logic Structurally instantiating components with registers Behaviorally Using a processes with a clock signal in the sensitivity list
This process is only sensitive to changes in clk, i.e., it will become active only when the clock transitions
upcount: PROCESS (clk, reset) BEGIN IF reset = '1' THEN count <= x"0"; ELSIF rising_edge(clk) THEN count <= count + 1; END IF;
This process is sensitive to changes in both clk and rst, i.e., it will become active during clock or reset transitions.
ARCHITECTURE archregistered OF registered IS BEGIN flipflop: Mff generic map (lpm_width=>4,lpm_fftype=>lpm_dff) PORT MAP (data=>d,clock=>clk,enable=>one,q=>q); END archregistered;
q_out
Implicit memory
Signals in VHDL have a current value and may be scheduled for a future value If the future value of a signal cannot be determined, a latch will be synthesized to preserve its current value Advantages: Simplifies the creation of memory in logic design Disadvantages: Can generate unwanted latches, e.g., when all of the options in a conditional sequential statement are not specified
a c
IF a = '1'
THEN c <= b; END IF; END PROCESS im_mem; END archincomplete;
Note: the incomplete specification of the IF...THEN... statement causes a latch to be synthesized to store the previous state of c
a b
The conditional statement is fully specified, and this causes the process to synthesize to a single gate
Exercise #4
Making use of the previous examples, write an entity/architecture pair for the following design:
ENC
COUNTER
DATA LD CLOCK
COUNT
4
COMPARATOR
P P=Q Q
RESET (sync)
REGISTER
State machines
Moore Machines A finite state machine in which the outputs change due to a change of state Mealy Machines A finite state machine in which the outputs can change asynchronously i.e., an input can cause an output to change immediately
Moore machines
Outputs may change only with a change of state Multiple implementations include: Arbitrary state assignment outputs must be decoded from the state bits combinatorial decode registered decode Specific state assignment outputs may be encoded within the state bits one-hot encoding
Inputs
Next State
State Registers
Output Logic
Outputs
Tco + tpd
IN IN std_logic;
Example: Solution 1
Combinatorial outputs decoded from the state registers
ARCHITECTURE arch_1 OF state_machine IS TYPE traffic_states IS (red, yellow, green); -- enumerated type SIGNAL sm: traffic_states; BEGIN
fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine only IF reset = '1' THEN sm <= red; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; ELSE sm <= red; END IF;
WHEN green => IF timer2=1' THEN sm <= yellow; ELSE sm <= green; END IF;
Present State
Inputs
Outputs
tco
Example: Solution 2
Registered outputs decoded from the state registers
ARCHITECTURE arch_2 OF state_machine IS TYPE traffic_states IS (red, yellow, green); SIGNAL sm: traffic_states; BEGIN
fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine AND the outputs IF reset = '1' THEN sm <= red; r<=1; g<=0; y<=0; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; r<=0; g<=1; y=0; ELSE sm <= red; r<=1; g<=0; y=0; END IF;
WHEN yellow => IF timer3=1' THEN sm <= red; r<=1; g<=0; y<=0; ELSE sm <= yellow; r<=0; g<=0; y<=1; END IF; WHEN others => sm <= red; END CASE; END IF; END PROCESS fsm; END arch_2;
Inputs
Logic
State Registers
Outputs
Tco
Example: Solution 3
Outputs encoded inside the state registers
ARCHITECTURE arch_3 OF state_machine IS SIGNAL CONSTANT CONSTANT CONSTANT sm: red: green: yellow: std_logic_vector(2 std_logic_vector(2 std_logic_vector(2 std_logic_vector(2 DOWNTO DOWNTO DOWNTO DOWNTO 0) 0) 0) 0) ; := 100" ; := "010" ; := "001" ;
BEGIN
fsm: PROCESS (clock, reset) -- the process describes the BEGIN -- state machine only IF reset = '1' THEN sm <= red; ELSIF rising_edge(clock) THEN CASE sm IS WHEN red => IF timer1=1 THEN sm <= green; ELSE sm <= red; END IF;
WHEN yellow => IF timer3=1 THEN sm <= red; ELSE sm <= yellow; END IF; WHEN others => sm <= red; END CASE; END IF; END PROCESS fsm;
r <= sm(2); g <= sm(1); y <= sm(0); END arch_3; -- the outputs are just taken from -- the state machine registers -- (no decode logic required)
Mealy Machines
Outputs may change with a change of state OR with a change of inputs Mealy outputs are non-registered because they are functions of the present inputs
State Registers
Inputs
Logic
Outputs
IDLE
RETRY
END IF; WHEN retry => IF pwait = '1' THEN wait_gen <= idle; ELSE wait_gen <= retry; END IF; WHEN OTHERS => wait_gen <= idle; END CASE; END IF; END PROCESS fsm; retry_out <= '1' WHEN (wait_gen = retry AND enable='0') ELSE '0'; END archmealy1;
Exercise #5
Design a state machine to implement the function shown below:
hold
POS
sample
extend
clear='0'
track='1'
track='1'
In the past, this was the major advantage of schematic capture tools
But, VHDL also supports hierarchical designs !!
i
b sel
mux2to1
a c b sel symbol component
schematic entity/architecture
library package
Hierarchy Management
Libraries are used to store re-usable components, type definitions,
overloaded operators etc. You add the LIBRARY and USE clauses to your code to get access to them
Your Design (VHDL)
LIBRARY ieee; USE ieee.std_logic_1164.. USE work.std_arith.all
Others (VHDL)
std_logic type definitions
Others (VHDL)
overloaded operators
work
std_arith
LIBRARY ieee; USE ieee.std_logic_1164.ALL; PACKAGE mymuxpkg IS COMPONENT mux2to1 PORT ( a, b, sel: IN std_logic; c: OUT std_logic); END COMPONENT; END mymuxpkg; LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY mux2to1 IS PORT ( a, b, sel: IN std_logic; c: OUT std_logic); END mux2to1;
ARCHITECTURE archmux2to1 OF mux2to1 IS BEGIN c <= (a AND NOT sel) OR (b AND sel); END archmux2to1;
Schematic of example
mux2to1
i(2) a
t(0) i(1)
mux2to1
a
t(1) i(0)
mux2to1
a
t(2)
m0 c
r(0) b sel r(1) b
m1 c
sel r(2) b
m2 c
sel
Exercise #6
Making use of exercise #4, we will use a separate entity/architecture for each block and use VHDL hierarchy
ENC
COUNTER
DATA LD CLOCK
COUNT
4
COMPARATOR
P P=Q Q
RESET (sync)
REGISTER
PACKAGE ex6_pkg IS
COMPONENT comp4 PORT ( p, q : IN std_logic_vector (3 DOWNTO 0); peqq : OUT std_logic); END COMPONENT; COMPONENT reg4 PORT ( clk, enr : IN std_logic; din : IN std_logic_vector(3 DOWNTO 0); q : OUT std_logic_vector(3 DOWNTO 0)); END COMPONENT;
COMPONENT count4 PORT( clk, enc, ld, rst : IN std_logic; din : IN std_logic_vector(3 downto 0); q : BUFFER std_logic_vector(3 downto 0)); END COMPONENT; END ex6_pkg;
: : : :
IN IN IN BUFFER
SIGNAL regout : std_logic_vector(3 downto 0); SIGNAL peqq : std_logic; SIGNAL not_peqq : std_logic;
Exercise 6: Summary
We created entity/architectures for each component. We stored those
components in a package so that we could RE-USE them We included ALL components in the ex6_pkg package which was compiled into the work library
Your Design (VHDL)
LIBRARY ieee; USE ieee.std_logic_1164.. USE work.ex6_pkg.all
Others (VHDL)
std_logic type definitions
q(1)
q(0)
LIBRARY ieee ; USE ieee.std_logic_1164.ALL; USE WORK.std_arith.all ; ENTITY ldcnt IS PORT ( clk, ld, oe: IN std_logic; count: INOUT std_logic_vector(7 DOWNTO 0)); END ldcnt; ARCHITECTURE archldcnt OF ldcnt IS SIGNAL int_count: std_logic_vector(7 DOWNTO 0); BEGIN cnt: PROCESS (clk) BEGIN IF RISING_EDGE(clock) THEN IF ld = '1' THEN int_count <= count; -- count as "IN" ELSE int_count <= int_count + 1; END IF; END IF; END PROCESS cnt ; outen: PROCESS (oe, int_count) BEGIN IF oe = '1 THEN count <= int_count ; -- count as "OUT" ELSE count <= (OTHERS => 'Z') ;-- count as "OUT" END IF ; -- equivalent to count <= "ZZZZZZZZ" END PROCESS outen; END archldcnt;
Exercise #7
Design a Moore Machine to implement the Output Enable Controller shown below:
68040
DRAM BANK A DRAM BANK B
DRAM BANK C
DRAM BANK D
Output Enable
DRAM Controller
Controller
RESET IDLE
OE=1111
/RAM
CHOOSE
OE=1111 /EOC /A3 AND /A2 /A3 AND A2 A3 AND /A2 A3 AND A2
BANK A
OE=1110
EOC
BANK B
OE=1101
EOC
BANK C
OE=1011
EOC
BANK D
OE=0111
EOC
BEGIN