AVHDL
AVHDL
Variables
Variables are used for information storage and pass within process, function and procedure. Variable is given its value immediately, not at the delta end like signal. Assignments may be made from signals to variables and vice-versa, provided the types match. process variable name : type [:= initial_value]; begin : : end process;
Presented by Abramov B. All right reserved 4
+ + +
res
11
Variables (cont)
process( clk, rst) is variable temp : std_logic_vector(7 downto 0); begin if (rst=active) then reg<=(others=>0); elsif rising_edge(clk) then case some_sig is when cond_A => temp:=.. when cond_B => temp:=.. -------when others => temp:= .. end case; reg<=temp + y; end if; end process;
Presented by Abramov B. All right reserved 14
temp dont have reset! Case should be with all possible branches
Variables Scope
16
Attributes
Attributes supply additional information an item: signal variable type component Certain attributes are predefined for types, array objects and signals. Syntax: objectattribute name; There are a number of attributes that are applicable to all scalar types and provide information about the range of values in the type.
17
Attributes (cont)
Scalar types attributes: Tleft first (leftmost) value in T; Tright - last (rightmost) value in T; Tlow least value in T; Thigh - greatest value in T; Tascending return boolean value, true if T is ascending range , false otherwise. Timage(x) - represent a scalar value of x into string form Tvalue(s) return the scalar value of object s are represented by string form
18
Attributes (cont)
There are attributes that applicable to just discrete and physical types. For any such type T, a value x of that type and an integer n, the attributes are: - position number of x in T Tpos(x) Tval(n) - value in T at position n Tsucc(x) - value in T at position one greater than that of x Tpred(x) - value in T at position one less than that of x Tleftof(x) - value in T at position one to the left of x Trightof(x) - value in T at position one to the right of x
19
Attributes (cont)
type my_type1 is ( unknown, low, medium, high); type my_type2 is range 15 downto 0; signal type1 : my_type1; signal type2 : my_type2; signal flag : boolean; signal position : integer; type1<= my_type1left ; -- unknown type2<= my_type2left; -- 15 type1<= my_type1right; -- high type2<=my_type2right; -- 0 type1<=my_type1low; -- unknown type2<=my_type2low; -- 0 type1<= my_type1high ;-- high type2<=my_type2high;-- 15
Presented by Abramov B. All right reserved
20
10
Attributes (cont)
flag<=my_type1ascending ; -- true; flag<= my_type2ascending; -- false my_type1image(low); -- low type2<= my_type2value(12); -- 12 position<= my_type1pos(low); -- 1 type2<= my_type2val(4); -- 11 type2<=my_type2succ(14); -- the position of number 14 is 1, then returned result is number from position 2 -> 13
Presented by Abramov B. All right reserved 21
Attributes (cont)
type1<=my_type1succ(unknown); -- low type2<=my_type1pred(14) ; -- 15 type1<=my_type1pred(medium); --low type1<=my_type1leftof(medium); -- low type1<=my_type1rightof(medium); --high type2<=my_type2leftof(10); -- 11 type2<=my_type2rightof(10); --9
22
11
Attributes (cont)
signal b : boolean; signal a : bit; signal i : integer; signal sl : std_logic; a<=bitval(booleanpos(b)); b<=booleanval(bitpos(a)); i<=booleanpos(b); i<=bitpos(a); sl<=std_logicval(booleanpos(b) + std_logicpos(0));
Presented by Abramov B. All right reserved 23
Attributes (cont)
The array attributes: Aleft - left bound of index range Aright - right bound of index range Alow - lower bound of index range Ahigh - upper bound of index range Arange - Index range Areverse_range - reverse of index range Alength - length of index range Aascending - true if index range is an ascending, false otherwise
Presented by Abramov B. All right reserved 24
12
Attributes (cont)
my_port : in std_logic_vector((N-1) downto 0); signal my_sig : std_logic_vector(my_portrange); -- 7 downto 0 signal temp : std_logic_vector( (my_portlength 1) downto 0); -- 7 downto 0 signal rev_sig : std_logic_vector (my_portreverse_range); -- 0 to 7 signal my_int : integer range 15 downto 0; signal flag : boolean; my_int<=my_sigleft; -- 7 my_int<=my_siglow; -- 0 my_int<=my_sigrigth; -- 0 my_int<=my_sighigh; --7 flag<= my_sigascending; --false flag<= rev_sigascending; -- true my_sig<= xaa; rev_sig<=my_sig; -- x55
Presented by Abramov B. All right reserved
25
Attributes (cont)
User defined attributes: signal my_sig : std_logic_vector(8 downto 0); attribute middle : integer; attribute middle of my_sig: signal is my_sig'length/2; -- 4 signal target : std_logic_vector(my_sigmiddle downto 0);
26
13
Attributes (cont)
Synthesis attributes Noopt: noopt <instance name> <true or false> Specifies that an instance should not be optimized or changed. However, in contrast to dont_touch, lower level hierarchy and leaf instances are not protected from optimization or change. For example: attribute noopt : boolean; attribute noopt of <component_name> : component is TRUE;
27
Attributes (cont)
Pin_number: pin_number <pin number> <port name> Assigns a device pin number to a certain port. Note: Pin location corresponds to pin_number attribute. Syntax: attribute pin_number : string; attribute pin_number of din : signal is P10;
28
14
Attributes (cont)
entity attribute_example is port ( CLK_30M : in std_logic; PRESET : in std_logic; CLK_DIS : in std_logic; ID : in std_logic_vector (2 downto 0); Y_LED : out std_logic); attribute altera_chip_pin_lc : string; attribute altera_chip_pin_lc of ID : signal is "N3, L4, R1"; attribute altera_chip_pin_lc of CLK_30M : signal is "G1"; attribute altera_chip_pin_lc of CLK_DIS : signal is "M4"; attribute altera_chip_pin_lc of PRESET : signal is "E5"; attribute altera_chip_pin_lc of Y_LED : signal is "P2"; end entity attribute_example ;
Presented by Abramov B. All right reserved
29
Attributes (cont)
Pullup/pulldown: Assign pullup or pulldown resistors (if possible) to your ports. Syntax: attribute pull:string; attribute pull of inbus_a : signal is "pullup"; attribute pull of inbus_b : signal is "pulldn";
30
15
Attributes (cont)
Open drain: Before using OPEN_DRAIN, declare it with the following syntax: attribute OPEN_DRAIN: string; After OPEN_DRAIN has been declared, specify the VHDL constraint as follows: attribute OPEN_DRAIN of signal_name : signal is TRUE;
31
Attributes (cont)
Preserve_signal When you apply preserve_signal, synthesis tool preserves the specified signal and the driver in the design.
32
16
Attributes (cont)
Clock_cycle clock_cycle <clock period> <signal name> Specifies the length (nanoseconds, real numbers) of the clock. This is a clock control command. Note: clock_cycle is one of two basic clock commands. The other : pulse_width. Syntax: attribute clock_cycle : real; -- or time type attribute clock_cycle of in_clock:signal is 30.0;
Presented by Abramov B. All right reserved
33
Attributes (cont)
Pulse_width pulse_width <clock width> Specifies the width (nanoseconds) of the clock pulse. This is a clock control command for duty_cycle description. Syntax: attribute pulse_width : time; -- or real type attribute pulse_width of clock:signal is 10 ns;
34
17
Attributes (cont)
Problem
35
Attributes (cont)
36
18
Attributes (cont)
Step 1 : Create intermediate signals
37
Attributes (cont)
attribute keep : boolean; attribute keep of signal_name : signal is true;
38
19
Attributes (cont)
Attributes of signal: Given a signal S, and a value T of type time, VHDL defines the following attributes: - created the new signal of type S, delayed from S by T. Sdelayed(T) Sstable(T) - return Boolean value, true if there has been no event on s in the time interval T up to the current time, false otherwise. Squiet(T) - return Boolean value, true if there has been no transaction on s in the time interval T up to the current time, false otherwise. Stransaction - return value of type bit, that changed value from 0 to 1 or vice-versa each time there is a transaction on S. Sevent - true if there is a event on S in the current cycle, false otherwise. Sactive - true if there is a transaction on S in the current cycle, false otherwise. - the time interval since the last event on S. Slast_event Slast_active - the time interval since the last transaction on S. Slast_value - the value of S just before the last event on S.
Presented by Abramov B. All right reserved 39
Attributes (cont)
Generate a new signal delayed from the source signal.
Adelayed(10 ns)
40
20
Attributes (cont)
The clock Rising edge detecting. clkevent and clk=1; not clkstable and clk=1; clkevent and clklast_value=0; not clkstable and clklast_value=0; The clock falling edge detecting. clkevent and clk=0; not clkstable and clk=0; clkevent and clklast_value=1; not clkstable and clklast_value=1;
Presented by Abramov B. All right reserved 41
Attributes (cont)
For Example (Set Up Violation Check):
Clk
A
8 ns
WAIT UNTIL rising_edge(Clk); ASSERT (A'Last_event>=8 ns) REPORT " SetUp Violation on Signal A ";
Presented by Abramov B. All right reserved 42
21
Attributes (cont)
Setup time violation checker: constant setup_time : time:= 2 ns; if clkevent and clk=1 then if not dstable( setup_time) then report Setup time violation on signal d; end if; end if;
43
Attributes (cont)
Hold time violation checker: constant hold_time : time:= 2 ns; if devent then if not clkstable( hold_time) and clklast_value= 0 then report Hold time violation on signal d; end if; end if; if clkdelayed(hold_time)event and clk=1 then if not dstable (hold_time) then report Hold time violation on signal d; end if; end if;
Presented by Abramov B. All right reserved 44
22
Attributes (cont)
Pulse width measurement with attributes
wait until falling_edge(pulse_100ns); if (pulse_100nsdelayedlast_event<100 ns) then report pulse_100ns length is less than expected time; end if;
Presented by Abramov B. All right reserved 45
-- synthesis off process is variable temp : std_logic_vector(cntrange); variable ones_counter : integer:=0; begin wait until rising_edge(clock); wait on cnt; temp:=cnt xor cntdelayedlast_value; for i in temprange loop ones_counter:= ones_counter + conv_integer(temp(i)); end loop; assert (ones_counter=1 or now=0 or reset=reset_active) report Counter error detected & timeimage(now) severity Warning; end process; -- synthesis on
Presented by Abramov B. All right reserved 46
XOR between current and previous values of Gray code counter should be one-hot value
23
Loops
VHDL has a basic loop statement, which can be augmented to form the usual while and for loops seen in other programming languages. The loop statement contains a sequence of statements, which are supposed to be repeated many times. The statement also lists the conditions for repeating the sequence or specifies the number of iterations. A loop statement can have several different forms depending on the iteration scheme preceding the reserved word loop.
Presented by Abramov B. All right reserved 47
Loops (cont)
In its simplest form, no iteration scheme is specified and the loop is repeated indefinitely. Example : signal clock : std_logic := '0'; clk_gen: process is begin L1: loop wait for 5 ns; clock <= 0; wait for 5 ns; clock<=1; end loop L1; end process clk_gen;
Presented by Abramov B. All right reserved 48
24
Loops (cont)
In order to exit from an infinite loop, an exit statement has to be used. The exit statement is used to finish or exit the execution of an enclosing loop statement. If the exit statement includes a condition, then the exit from the loop is conditional. Syntax: exit; exit loop_label; exit loop_label when condition;
49
Loops (cont)
The exit statement terminates entirely the execution of the loop in which it is located. The execution of the exit statement depends on a condition placed at the end of the statement, right after the when reserved word. When the condition is TRUE (or if there is no condition at all) the exit statement is executed and the control is passed to the first statement after the end loop.
50
25
Loops (cont)
The loop label in the exit statement is not obligatory and can be used only in case of labeled loops. If no label is present then it is assumed that the exit statement relates to the innermost loop containing it. If an exit from a loop on a higher level of hierarchy is needed then the loop has to be assigned a label, which will be used explicitly in the exit statement.
51
Loops (cont)
signal a : integer:=0; L2: loop a<= a+1; wait until rising_edge(clk); exit L2 when (a > 10); end loop L2; The infinite loop becomes in practice a finite, as the iterations will terminate as soon as the variable A becomes greater than 10.
Presented by Abramov B. All right reserved
52
26
Loops (cont)
Instead of specifying an infinite loop with a conditional exit statement, a while loop can be used. In such a case the reserved word while with a condition precede the keyword loop. The sequence of statements inside the loop will be executed if the condition of the iteration scheme is true. The condition is evaluated before each execution of the sequence of statements. When the condition is false, the loop is not entered and the control is passed to the next statement after the end loop clause
53
Loops (cont)
shifter: process is variable i : positive := 1; begin L3: while i < 8 loop serial_out <= reg(i) ; i := i + 1; wait until rising_edge(clk); end loop L3; end process shifter;
Presented by Abramov B. All right reserved 54
27
Loops (cont)
Another iteration scheme is useful when a discrete range can define the number of iterations. In this case the keyword for with a loop parameter precede the keyword loop. The header of the loop also specifies the discrete range for the loop parameter. In each iteration the parameter takes one value from the specified range, starting from the leftmost value within the range.
55
Loops (cont)
shifter: process is begin L4: for index in 0 to 7 loop serial_out <= din(index); wait until rising_edge(clk); end loop L4; end process shifter; In the above example the loop statement parameter index will cause the loop to execute 8 times, with the value of index changing from 0 to 7.
Presented by Abramov B. All right reserved 56
28
Loops (cont)
The next statement is used to complete execution of one of the iterations of an enclosing loop statement. The completion is conditional if the statement includes a condition. Syntax: next; next loop_label; next loop_label when condition;
57
Loops (cont)
The next statement allows to skip a part of an iteration loop. If the condition specified after the when reserved word is TRUE, or if there is no condition at all, then the statement is executed. This results in skipping all statements below it until the end of the loop and passing the control to the first statement in the next iteration. Loop_Z: for index in 0 to 15 loop next when((index rem 2) = 1); bus_b(index/2) <= bus_a(index); end loop Loop_Z;
Presented by Abramov B. All right reserved
58
29
Loops (cont)
Important notes: The next statement is often confused with the exit statement. The difference between the two is that the exit statement "exits" the loop entirely, while the next statement skips to the "next" loop iteration (in other words, it "exits" the current iteration of the loop). The parameter for a 'for' loop does not need to be specified the loop declaration implicitly declares it. The loop parameter is a constant within a loop, which means that it may not be assigned any values inside the loop.
Presented by Abramov B. All right reserved 59
Loops (cont)
The difference between next and exit for I in 0 to max_no loop if (done(I)=true) then next; else Done(I):=true; end if; x(I) <= y(I) and z(I); end loop; for I in 0 to max_no loop if (done(I)=true) then exit; else Done(I):=true; end if; x(I) <= y(I) and z(I); end loop;
60
30
Loops (cont)
shifter: process(clk,rst) is begin Shift left or shift right ? if (rst='0') then What a difference within/out of reg<=(others=>'0'); commented line? elsif rising_edge(clk) then if (ld='1') then reg<=din; elsif (en='1') then for i in reg'low to (reg'high-1) loop reg(i+1)<=reg(i); -- reg(i) <=0; end loop; end if; end if; end process shifter;
Presented by Abramov B. All right reserved
61
Loops (cont)
signal din : std_logic_vector(7 downto 0); parity_check: process(din) is variable p_even : std_logic; begin for i in dinrange loop if (i=dinleft) then p_even:=din(dinleft); else p_even:=p_even xor din(i); end if; end loop; parity<=p_even; end process parity_check;
Presented by Abramov B. All right reserved 62
31
Loops (cont)
63
Loops (cont)
Loop is a very powerful instrument for description of similar operations or repeated structures. Example: priority encoder implementation with If-else statement. process (din) is begin if (din(15)='1') then dout<="1111"; elsif (din(14)='1') then dout<="1110"; elsif (din(13)='1') then dout<="1101; .. else dout<="0000"; end if; end process; Current code style is very simple but should be used only for small encoders.
Presented by Abramov B. All right reserved
64
32
Loops (cont)
Priority encoder implementation with for loop and exit statements. process (din) is begin dout<=(others=>'0'); for i in din'range loop dout<=conv_std_logic_vector(i,dout'length); exit when (din(i)='1'); end loop; end process; The given description is very short but nondeterministic for hardware compilers. The next description is better for synthesis.
Presented by Abramov B. All right reserved 65
Loops (cont)
Priority encoder implementation with for loop statement. process (din) is variable first_one : boolean; Flag that indicates occurrence of the first bit begin which equals 1 first_one:= false; dout<=(others=>'0'); for i in din'range loop if ((not first_one) and (din(i)='1')) then first_one:=true; dout<=conv_std_logic_vector(i,dout'length); end if; end loop; end process; The given description is completely generic.
Presented by Abramov B. All right reserved 66
33
Loops (cont)
twos_complement: process (a) is variable temp : std_logic_vector(arange); variable carry : std_logic; begin carry:=1; for i in areverse_range loop temp(i):= (not a(i)) xor carry; carry:= (not a(i)) and carry; end loop; b<=temp; end process twos_complement;
Presented by Abramov B. All right reserved 67
b(n)
b(0)
68
34
35
signal products_p : registers((din_width - 1) downto 0); signal stage_0 signal stage_1 signal stage_2 begin : registers((din_width/2 - 1) downto 0); : registers((din_width/4 - 1) downto 0); : registers((din_width/8 - 1) downto 0);
71
72
36
73
74
37
75
76
38
Assert statements
A statement that checks that a specified condition is true and reports an error if it is not. Syntax: assert condition report string severity severity_level;
77
39
79
80
40
81
82
41
83
84
42
File I/O
VHDL defines the file object and includes some basic file IO procedures implicitly after a file type is defined. A file type must be defined for each VHDL type that is to be input from or output to a file. Example: TYPE bit_file IS FILE of bit; In VHDL87, there are no routines to open or close a file, so both the mode of the file and its name must be specified in the file declaration. The mode defaults to read if none is specified. Examples: FILE in_file :bit_file IS my_file.dat -- opens a file for reading FILE out_file:bit_file IS OUT my_other_file.dat; -- opens a file for writing
85
43
87
88
44
Status values : OPEN_OK - File Opened successfully. STATUS_ERROR - File Object already has an external file associated with it. NAME_ERROR - External file does not exist. MODE_ERROR - External file can not open with requested File_Open_Kind.
Presented by Abramov B. All right reserved 90
45
92
46
47
95
96
48
49
99
100
50
process is file stim_file : text; variable fopen_stat : FILE_OPEN_STATUS; variable l : line; variable t : real; variable good : boolean; variable cl,d1,d2,d3 : bit; begin file_open(fopen_stat,stim_file, test_vector.txt, read_mode); assert (fopen_stat=OPEN_OK) report file open error severity FAILURE; while not endfile(stim_file) loop readline(stim_file,l); read(l,t,good); next when not good; read(l,cl); read(l,d1); read(l,d2); read(l,d3); wait for ((t*1 ns) now); clk <= to_stdlogic(cl); data1 <= to_stdlogic(d1); data2 <= to_stdlogic(d2); data3 <= to_stdlogic(d3); end loop; file_close(stim_file); wait; end process; Presented by Abramov B.
All right reserved
C l k _ I 0 1 0 1 0 1 0 1 0 1 0
101
102
51
103
104
52
105
53
107
108
54
109
55
111
The next step toward automation of the output verification is the use of golden vectors.
112
56
113
Arrays
Records
114
57
Arrays
Array contains multiple elements of the same type. Syntax: type type_name is array ( range ) of element_type; When an array object is declared, an existing array type must be used. type nibble is array ( 3 downto 0) of std_logic; signal my_bus : nibble;
115
Arrays (cont)
An array type definition can be unconstrained, i.e. of undefined length. String, bit_vector, an std_logic_vector are defined in this way. type std_logic_vector is array ( natural range <>) of std_logic; An object ( signal, variable or constant) of an unconstrained array type must have its index range defined when it is declared. signal byte : std_logic_vector(7 downto 0);
116
58
Arrays (cont)
1-D arrays: type dword is array (31 downto 0) of integer; constant depth : integer :=10; type ram_model is array ((2**depth 1) downto 0) of dword; -- defined 1Kdwords 2-D arrays: type arr_2d is array ((3 downto 0), (3 downto 0)) of dword; Note: logic synthesis tools accept one-dimensional arrays of others supported types.
117
Initializing Arrays
type point3d is array(1 to 3) of real; signal P : point3d := (12.5, 2.4, 1.9); signal P : point3d := (1=>12.5, 2=>2.4, 3=>1.9); subtype addr is integer range 0 to 127; type memory is array(addr) of std_logic_vector(7 downto 0); signal mem : memory := (0=>XFF, 3=>XAB, others=>X00); signal mem : memory := (0 to 10=>XAB, others=>X00); signal mem : memory := (others=>( others =>0));
subtype shortint is integer range 0 to 25; type asciihex is array(a to z) of shortint; constant convtable : asciihex := (a=>0, b=>1, ... z=25);
118
59
119
Unconstrained Arrays
array type range < > of element type
type std_logic_vector is array (natural range<>) of std_logic; -- constraining by declaration signal word :std_logic_vector(31 downto 0); -- constraining by subtype definition subtype word is std_logic_vector(31 downto 0); -- constraining by initialization signal word :std_logic_vector := (1=>1, 2=>Z, 3=>1); signal word :std_logic_vector := (1,Z,1,0,Z);
Presented by Abramov B. All right reserved 120
60
Records
The second type of composite types is record type. Record type have named fields of different types: type t_packet is record byte_id : std_logic; parity : std_logic; address : integer range 3 downto 0; data : std_logic_vector( 3 downto 0); valid : boolean; end record;
121
Records (cont)
Records A way of abstraction
VHDL records support the abstraction of data into high level representation. Records are collection of elements that might be of different types (elements filed). Records are ideal for representing packets of frames,standard and non-standard buses and interfaces.
122
61
Records (cont)
Whole record values can be assigned using assignment statements, for example: signal first_packet,last_packet : t_packet; last_packet<=first_packet; first_packet<=(1,1,2,xa,true); last_packet.valid<=false; first_packet.data<=last_packet.data;
123
CDT Example
entity fifo is generic ( data_width : natural:=16 ; depth : natural :=256); port ( clk : in std_logic ; rst : in std_logic ; din : in std_logic_vector((data_width - 1) downto 0); we : in std_logic ; re : in std_logic ; dout : in std_logic_vector((data_width - 1) downto 0); valid : out std_logic ; full : buffer boolean ; empty : buffer boolean ); end entity fifo;
Presented by Abramov B. All right reserved 124
62
125
63
64
Aliases
An alias is an alternative name for existing object. It does not define a new object. VHDL provides the alias construct to enhance readability in VHDL descriptions. Aliases are available in two varieties: 1. Object aliases rename objects a. constant b. signal c. variable d. file 2. Non-object aliases rename items that are not objects aliases a. function names b. literals c. type names d. attribute names
Presented by Abramov B. All right reserved
129
Aliases (cont)
Syntax: alias alias_name : alias_type is object_name; Example: signal my_bus : std_logic_vector(31 downto 0); alias upper_half_word : std_logic_vector(15 downto 0) is my_bus(31 downto 16); alias lower_half_word : std_logic_vector(15 downto 0) is my_bus(15 downto 0); alias reversed_bus : std_logic_vector(0 to 31) is my_bus; In VHDL-93 standard all object may be aliased, all non-object can also be aliased. Example: alias main_logic is ieee.std_logic_1164.std_logic;
Presented by Abramov B. All right reserved
130
65
Aliases (cont)
architecture arc_keyboard_receiver of keyboard_receiver is signal serial2parallel : std_logic_vector(10 downto 0); alias start_bit : std_logic is serial2parallel(0); alias stop_bit : std_logic is serial2parallel(10); alias odd_parity_bit : std_logic is serial2parallel(9); alias scan_code : std_logic_vector(7 downto 0) is serial2parallel(8 downto 1); begin . . valid<=1 when (start_bit=0 and stop_bit=1 and parity=odd_parity_bit) else 0;
131
Packages
A package is a cluster of declarations and definitions of objects, functions, procedures,components, attributes etc. that can be used in a VHDL description. You cannot define an entity or architecture in a package, so a package by itself does not represent a circuit. A package consists of two parts: The package header, with declarations The package body, with definitions. An example of a package is std_logic_1164, the IEEE 1164 logic types package. It defines types and operations on types for 9-valued logic. To include functionality from a package into a VHDL description, the use clause is used.
Presented by Abramov B. All right reserved 132
66
Packages (cont)
To include functionality from a package into a VHDL description, the use clause is used.
Package Declaration
USE
Design1
Package Body
USE
Design2
USE
Design3
133
Packages (cont)
A Package is a common storage area used to hold data to be shared among a number of entities. Kind Of Packages: Standard Packages (IEEE,TextIO) Synthesizer Packages (exemplar_1164) VITAL Packages (Gate Level Primitives) User Defined Project Packages
134
67
Packages (cont)
Declaration part syntax : package package_name is declarations end package package_name; Declarations may typically be any of the following: type, subtype, constant, file, alias,component, attribute,function,procedure. package demo_pack is constant full : std_logic_vector; type state is (idle, wait_cs, ack); function parity ( data : std_logic_vector) return std_logic; end package demo_pack;
Presented by Abramov B. All right reserved 135
Packages (cont)
When a procedure or function is declared in a package , Its body ( the algorithm part) must be placed in the package body. Definition part syntax: package body package_name is declarations deferred constant declaration subprogram bodies end package body package_name;
Presented by Abramov B. All right reserved 136
68
Packages (cont)
A constant declared in a package may be deferred. This means its value is deferred in the package body. package body demo_pack is constant full : std_logic_vector :=xff; function parity ( data : std_logic_vector) return std_logic is begin -- function code end function parity; end package body demo_pack ;
Presented by Abramov B. All right reserved 137
Function
Function the powerful tool to implement functionality that is repeatedly used. Functions take a number of arguments that are all inputs to the function, and return a single value. All statements in functions and procedures are executed sequentially. May contain any sequential statement except signal assignment and wait. Variables that are local to the function can be declared . Local signals are not allowed. A type conversion function may be called in a port map. Array-type parameters may be unconstrained. Can be called from the dataflow environment and from any sequential environment (processes or other sub-programs) Presents only combinatorial logic !!!
Presented by Abramov B. All right reserved 138
69
Function (cont)
Syntax : function function_name ( parameter_list) return type is local declarations begin sequential statements end function function_name ;
139
Function (cont)
Function implementation example: function parity ( data : std_logic_vector ) return std_logic is variable temp : std_logic; begin for i in datarange loop if (i=dataleft) then temp:=data(dataleft); else temp:=temp xor data(i); end if; end loop; return temp; end function parity;
Presented by Abramov B. All right reserved 140
70
Function (cont)
Another implementation with variable initialization: function parity ( data : std_logic_vector ) return std_logic is variable temp : std_logic =0; begin for i in datarange loop temp:=temp xor data(i); end loop; return temp; end function parity;
141
Function (cont)
Hardware implementation of parity function with 8 bit data width:
142
71
Aliases in functions
Aliases are often useful in unbound function calls. For instance, if you want to make a function that takes the AND operation of the two left most bits of an arbitrary array parameter. If you want to make the function general enough to handle arbitrary sized arrays, this function could look like this: function left_and (arr: std_logic_vector) return std_logic is begin return arr(arrleft) and arr(arrleft-1) ; end function left_and ;
143
Aliases in functions(cont)
Instead, you could make an alias of arr, with a known index range, and operate on the alias: function left_and (arr : std_logic_vector) return std_logic is alias aliased_arr : std_logic_vector (0 to arrlength-1) is arr ; begin return aliased_arr(0) and aliased_arr(1) ; end function left_and ;
Function works for both ascending and descending index ranges of arr!!!
144
72
145
Function (cont)
function recurse_xor (data: std_logic_vector) return std_logic is alias t : std_logic_vector(0 to (datalength-1)) is data;; variable left_tree , right_tree : std_logic; begin if (t'length = 1) then return t(0); else left_tree := recurse_xor (t(0 to (t'length /2 -1) )); right_tree := recurse_xor (t(t'length /2 to t'right)); return (left_tree xor right_tree); end if; end function recurse_xor;
146
73
Function (cont)
147
Function (cont)
function recursive_parity ( vec : std_logic_vector) return std_logic is variable temp : std_logic_vector((vec'length/2 -1) downto 0); begin if (vec'length = 2) then return (vec(vec'high) xor vec(vec'low)); else for i in temprange loop temp(i):=vec(i*2 +1) xor vec(i*2); end loop; return recursive_parity(temp); end if; end function recursive_parity;
Presented by Abramov B. All right reserved 148
74
Function (cont)
Hardware implementation of recursive parity function with 8 bit data width: first call second call third (last) call
149
Function (cont)
type vec_arr is array (natural range <>) of std_logic_vector(15 downto 0); function add (data : vec_arr)return std_logic_vector is alias t : vec_arr(0 to (data'length-1)) is data; variable res : std_logic_vector(t(0)'range); begin if (t'length=1) then res:=t(0); else res:=add(t(0 to ((t'length/2)-1))) + add(t((t'length/2) to t'high)); end if; return res; end function add;
150
75
Function (cont)
Functions that receive and return a constant values constant MAX_VALUE integer := some integer value; function log2 (constant arg: integer) return integer is begin NOTICE! for i in 0 to 31 loop This function has no hardware representation but if (2**i>=arg) then only the calculation during compilation return i; end if; return 1; end function log2; signal cnt: std_logic_vector ( (log2(MAX_VALUE )-1) downto 0);
151
Function (cont)
type int_arr is array (natural range <>) of integer; constant C_POLINOM : int_arr:=(7,5,4,3); ---------------------------------------------------------------------------------------------------------function rand_gen (buff : std_logic_vector; polinom : int_arr) return std_logic_vector is variable or_gate, xor_gate, sin : std_logic :=0; begin for i in buffrange loop or_gate:=or_gate or buff(i); -- usage example elsif rising_edge(clk) then rand_sig<=rand_gen(rand_sig,C_POLINOM);
end loop; for j in polinomrange loop xor_gate:=xor_gate xor buff(polinom(j)); end loop; sin:=xor_gate or (not or_gate); return (buff((buffhigh-1) downto bufflow) & sin); end function rand_gen;
Presented by Abramov B. All right reserved 152
76
153
Resolution function
In many digital systems, buses are used to connect a number of output drivers to a common signal. For example, if open-collector or open-drain output drivers are used with a pull-up load on a signal, the signal can be pulled low by any driver, and is only pulled high by the load when all drivers are off. This is called a wired-or or wired-and connection. We can describe the following circuit with resolved type and resolution function
154
77
78
157
Procedure
The other kind of subprograms is procedure. Procedures take a number of arguments that can be inputs, outputs or inouts, depending on the direction of the flow of information through the argument. All statements in procedures are executed sequentially May have in,out or inout parameters. Parameter may be signal, variable or constant. May be called concurrently or sequentially. A concurrent procedure call executes whenever any of its in or inout parameters change. May declare local variables. A procedure can contain wait statements , unless it is called from a process with a sensitivity list, or from within a function. May contain a return statement.
Presented by Abramov B. All right reserved 158
79
Procedure (cont)
Procedures syntax : procedure procedure_name (parameter_list) is declaration begin sequential statements end procedure procedure_name;
159
Procedure (cont)
Procedure without parameters_list: procedure initialize is begin address<=(others=>-); data<=(others=>-); wait until rstevent and rst=1; wait for 10 ns; cs<=0; address<=x00; data<=xff; end procedure initialize;
Presented by Abramov B. All right reserved 160
80
Procedure (cont)
Procedure with parameters_list ( in by default) procedure do_op (opcode : std_logic_vector) is variable result : integer; begin case opcode is when add => result:=op1 + op2; when sub => result:= op1 op2; end case; dest<= result after alu_tpd; end procedure do_op ;
Presented by Abramov B. All right reserved 161
Procedure (cont)
Procedure with parameters_list: procedure adder ( a,b : in std_logic_vector ; res: out std_logic_vector; overflow : out boolean) is variable sum : std_logic_vector(arange); variable carry : std_logic:=0; begin for i in resreverse_range loop sum(i):= a(i) xor b(i) xor carry; carry:=(a(i) and b(i)) or (a(i) and carry) or (b(i) and carry); end loop; res:= sum; overflow:= (carry=1); end procedure adder ;
Presented by Abramov B. All right reserved 162
81
Procedure (cont)
Procedure with default value for a formal parameter of mode in : procedure increment ( signal a : inout std_logic_vector; step : in integer:=1) is begin a<= a + step; end procedure increment ; We can call the procedure to increment by 1, as follows: increment(count); or increment(count,open); If we want to increment a signal count by other value ,we can call the procedure, as follows: increment(count,5); or increment(count,new_step);
Presented by Abramov B. All right reserved 163
Procedure (cont)
The procedures completed execution of the statements in their bodies before returning. Sometimes it is useful to be able to return from the middle of a procedure. We can do this using a return statement. procedure read is begin addr<= addr_reg; ram_read<=1; wait until ram_ready=1 or rst=0; if (rst=0) then return; end if; wait until ram_ready=0; end procedure read;
Presented by Abramov B. All right reserved 164
82
Procedure (cont)
The procedures shift register as procedure with default parameters: procedure shift_right_arst_ld_en( signal clk : in std_logic; arst : in std_logic; ld : in std_logic:='0'; din :in std_logic_vector:=conv_std_logic_vector(0,din'length); sin : in std_logic_vector(15 downto 0):=x"0000"; en : in std_logic; signal buf : inout std_logic_vector ) is begin if (arst=RESET_INIT) then buf<=conv_std_logic_vector(0,buf'length); elsif rising_edge(clk) then if (ld='1') then buf(din'range)<=din; elsif (en='1') then buf<=sin & buf(buf'high downto sin'length); end if; end if; end procedure shift_right_arst_ld_en;
Presented by Abramov B. All right reserved 165
Procedure (cont)
Shift register shift right that provides shift right with serial in and shift enable by procedure shift_right_arst_ld_en : shift_right_arst_ld_en ( clk => sys_clk, arst => sys_rst, sin => per_data, en => ing_inbuf_en, buf => ing_search_inbuf ); Not used inputs : ld -> parallel load and din -> parallel data input
166
83
Procedure (cont)
Shift register that provides shift right with parallel load and shift enable by procedure shift_right_arst_ld_en : shift_right_arst_ld_en ( clk => sys_clk, arst => sys_rst, ld => cpu_table_rd_valid, din => cpu_table_data_rd, en => ing_search_outbuf_re, buf => ing_search_outbuf ); Not used inputs : sin -> serial data input (by default x0000)
Presented by Abramov B. All right reserved 167
Overloading
When we are writing subprograms, it is a good idea to chose names for out subprograms that indicate what operation they perform. How to name two subprograms that perform the same kind of operation but on parameters of different types? VHDL allows us to define subprograms in this way, using technique called overloading of subprogram names. procedure increment(a : inout integer ; by : in integer:=1) is procedure increment(a : inout std_logic_vector ; by : in integer:=1) is procedure increment(a : inout std_logic_vector ; by : std_logic_vector :=b1) is ---------------------------------------------------------------------------------------increment(count_1,2); increment(count_v, 101)
Presented by Abramov B. All right reserved 168
84
Overloading (cont)
VHDL provides a way for us to define new subprograms using the operator symbols as names. function + (left,right : std_logic) return std_logic is begin return ( left or right); end function +; function * (left,right : std_logic) return std_logic is begin return ( left and right); end function *; Now we can write your logical equation like a Boolean equation: carry<=a*b + a*c + b*c;
Presented by Abramov B. All right reserved 169
Overloading (cont)
package my_pack is function "not"(R: integer) return integer; end package my_pack; package body my_pack is function "not"(R: integer) return integer is variable vector : signed(31 downto 0); begin vector := conv_signed(R,32); for i in vectorrange loop vector(i) :=not vector(i); end loop; return conv_integer(vector); end function not; end package body my_pack; Int <= not(126); Int <= not(integer(22.17))
Presented by Abramov B. All right reserved 170
85
Overloading (cont)
Simple design problem: signal ASel, BSel, CSel, DSel : std_logic ; signal Y, A, B, C, D : std_logic_vector(7 downto 0) ; Y <= A when (ASel = '1') else B when (BSel = '1') else C when (CSel = '1') else a D when (DSel = '1') else b (others => '0') ; Mux c 2x1 Mux d 2x1 Mux 2x1 zero bsel csel dsel This code defines priority select logic, which is inefficient from a hardware area and timing perspective.
Presented by Abramov B. All right reserved 171
Mux 2x1
asel
Overloading (cont)
When the select signals (ASel, ) are mutually exclusive, overloading can be perfect solution for this problem. function and "(l : std_logic_vector ;R: std_logic) return std_logic_vector is variable res : std_logic_vector(lrange); begin for i in lrange loop res(i) :=l(i) and R; end loop; return res; end function and; Now we can write : Y <= (A and ASel) or (B and BSel) or (C and CSel) or (D and DSel) ;
Presented by Abramov B. All right reserved 172
86
Overloading (cont)
Here there is the hardware implication of A and Asel:
173
174
87
175
176
88
ADT (cont)
package complex_type is constant re : integer:=0; constant im : integer:=1; library ieee; use ieee.std_logic_1164.all; subtype dword is std_logic_vector(31 downto 0); type complex is array (re to im) of dword; function + (a,b: complex) return complex; function - (a,b: complex) return complex; function * (a,b: complex) return complex; function / (a,b: complex) return complex; function conjugate (a,b: complex) return complex; end package complex_type; This is a package declaration for a package that implements a complex number data type. Note that the data type is given as well as some standard operators on that type.
Presented by Abramov B. All right reserved
178
89
ADT (cont)
package body complex_type is library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; function + (a,b: complex) return complex is variable t : complex; begin t(re):=a(re) + b(re); t(im):=a(im) + b(im); return t; end function +; function - (a,b: complex) return complex is variable t : complex; begin t(re):=a(re) - b(re); t(im):=a(im) - b(im); return t; end function -;
Presented by Abramov B. All right reserved 179
ADT (cont)
function * (a,b: complex) return complex is variable t : complex; begin t(re):=a(re) *b(re) a(im)*b(im); t(im):=a(re) *b(im) + a(im)*b(re); return t; end function *; function / (a,b: complex) return complex is variable t : complex; variable i : integer:=b(re)**2 + b(im)**2; begin t(re):= a(re) *b(re) + a(im)*b(im); t(im):=a(im) *b(re) - a(re)*b(im); t(re):=t(re)/i; t(im):=t(im)/i; return t; end function /;
Presented by Abramov B. All right reserved 180
90
ADT (cont)
function conjugate (a) return complex is variable t : complex:=(0,0); begin t(re):=a(re) - b(im); return t; end function conjugate; end package body complex_type;
181
ADT Benefits
Reduced design communication overhead No functional boundaries to negotiate Easier to manage feature changes later Changes made with less consequence Early problem detection Minimal component structure - fewer files to edit Enhanced readability Type names add extra "descriptiveness" Readable by non-VHDL literate people Increased maintainability Type implementations easy to document Intellectual property development facilitated
Presented by Abramov B. All right reserved 182
91
Video frame (640x480 pixel) rendering simulation: With ADT ~ 15 min Without ADT (std_logic type) ~ 2.0 hours
183
Min 6 5
Max -
Unit ns ns
184
92
186
93
188
94
189
190
95
TB2
TB3
191
192
96
Generate
Generate statements are provided as a convenient way to create multiple instances of concurrent statements (including processes), most typically component instantiation statements. All generate statements must start with label. There are two basic varieties of generate statements: For generate All objects created are similar The generate parameter must be discrete and is undefined outside the generate statement Loop cannot be terminated early If generate Allows for conditional creation of logic Cannot use ELSE or ELSIF clauses with the IF generate
Presented by Abramov B. All right reserved 194
97
Generate (cont)
The following example shows how you might use a for-generate statement to create four instances of a lower-level component (in this case a RAM block): architecture generate_example of my_entity is component RAM16X1 is port(A0, A1, A2, A3, WE, D: in std_logic; O: out std_logic); end component RAM16X1; begin ... RAMGEN: for i in 0 to 3 generate RAM: RAM16X1 port map ( . . . ); end generate RAMGEN; end architecture generate_example;
Presented by Abramov B. All right reserved 195
Generate (cont)
The if-generate statement is most useful when you need to conditionally generate a concurrent statement. A typical example of this occurs when you are generating a series of repetitive statements or components and need to supply different parameters, or generate different components, at the beginning or end of the series. The following example shows how a combination of a for-generate statement and two if-generate statements can be used to describe a n-bit parity shift register constructed of cascaded DFFs:
dff(0)
d_in
D CLK CLK Q
dff(1)
t(1)
D CLK Q
dff(2)
t(2)
D CLK Q
dff(n)
t(n)
D CLK Q
d_out
98
Generate (cont)
g1: FOR i IN 0 TO (length-1) GENERATE g2: IF i=0 GENERATE dff : d_ff PORT MAP(d_in,clk,t(1)); END GENERATE g2; g3: IF i>0 AND i<(length-1) GENERATE dff: d_ff PORT MAP (t(i),clk,t(i+1)); END GENERATE g3; g4: IF i=(length-1) GENERATE dff : d_ff PORT MAP(t(i),clk,d_out); END GENERATE g4; END GENERATE g1; END ARCHITECTURE;
197
Generate (cont)
The 16 bit adder with carry look ahead mechanism and speculative algorithm of group carry.
entity adder is generic (width: natural:=16); port( a: in std_logic_vector((width-1) downto 0); b: in std_logic_vector((width-1) downto 0); s: out std_logic_vector(width downto 0) ); end entity adder;
Presented by Abramov B. All right reserved 198
99
Generate (cont)
a Carry look ahead Carry look ahead b High byte 0 Low byte
High byte 1
carry
Result[16]
Result [15:8]
Result [7:0]
Presented by Abramov B. All right reserved 199
Generate (cont)
architecture arc_adder of adder is attribute middle : integer; attribute middle of a :signal is a'length/2; function fa_sum( a_bit,b_bit,c_in: std_logic) return std_logic is variable sum :std_logic; begin sum:= a_bit xor b_bit xor c_in; return sum; end function fa_sum; function fa_carry( a_bit,b_bit,c_in: std_logic) return std_logic is variable carry : std_logic; begin carry:=(a_bit and b_bit) or (a_bit and c_in) or (b_bit and c_in); return carry; end function fa_carry; constant GND : std_logic:='0'; constant VCC : std_logic:='1';
Presented by Abramov B. All right reserved 200
100
g1:for i in a'reverse_range generate lower_bit:if (i = a'low) generate temp(i)<=fa_sum(a(i),b(i),GND); g_l(i)<=a(i) and b(i); end generate lower_bit; others_bit: if (i > a'low) generate first_byte: if (i < a'middle) generate temp(i)<=fa_sum(a(i),b(i),g_l(i-1)); g_l(i)<=fa_carry(a(i),b(i),g_l(i-1)); end generate first_byte; second_byte: if (i >= a'middle) generate second_byte_lower_bit: if (i = a'middle) generate temp_0(i - a'middle)<=fa_sum(a(i),b(i),GND); g_m_0(i - a'middle) <=fa_carry(a(i),b(i),GND); temp_1(i - a'middle)<=fa_sum(a(i),b(i),VCC); g_m_1(i - a'middle) <=fa_carry(a(i),b(i),VCC); end generate second_byte_lower_bit; second_byte_others_bit : if (i > a'middle) generate temp_0(i - a'middle)<=fa_sum(a(i),b(i),g_m_0(i- a'middle -1)); g_m_0(i - a'middle) <=fa_carry(a(i),b(i),g_m_0(i- a'middle -1)); temp_1(i - a'middle)<=fa_sum(a(i),b(i),g_m_1(i - a'middle -1)); g_m_1(i - a'middle)<=fa_carry(a(i),b(i),g_m_1(i - a'middle -1)); end generate second_byte_others_bit; end generate second_byte; end generate others_bit; Presented by Abramov B. end generate g1; All right reserved
201
Generate (cont)
s(s'high)<= g_m_1(temp_1'high) when (g_l(g_l'high)='1') else g_m_0(temp_0'high); s((s'high -1) downto a'middle)<=temp_1 when (g_l(g_l'high)='1') else temp_0; s(temp'range)<=temp; end architecture arc_adder;
202
101
203
204
102
205
206
103
Delay Mechanism
Delay is a mechanism allowing introducing timing parameters of specified systems. Syntax: delay_mechanism ::= transport | [ reject time_expression ] inertial The delay mechanism allows introducing propagation times of described systems. Delays are specified in signal assignment statements. It is not allowed to specify delays in variable assignments.
207
208
104
209
210
105
211
212
106
213
214
107
u 0 1 0 a
sig_out
200
400
1100
215
Blocks
A block statement (which is concurrent) contains a set of concurrent statements. The order of the concurrent statements does not matter, because all statements are always executing. The syntax of a block statement is label: block [ (expression) ] { block_declarative_item } begin { concurrent_statement } end block [ label ]; label => The label, which is required, names the block. expression => The guard condition for the block.
Presented by Abramov B. All right reserved
216
108
Blocks (cont)
Objects declared in a block are visible to that block and to all blocks nested within it. When a child block (nested inside a parent block) declares an object with the same name as an object in the parent block, the child blocks declaration overrides that of the parent.
217
Blocks (cont)
B1: block signal S: bit; -- Declaration of S in block B1 begin S <= A and B; -- S from B1 B2: block signal S: bit; -- Declaration of S, block B2 begin S <= C and D; -- S from B2 B3: block begin Z <= S; -- S from B2 end block B3; end block B2; Y <= S; -- S from B1 end block B1;
Presented by Abramov B. All right reserved 218
109
Blocks (cont)
A block can also have a GUARD expression. In that case, an assignment inside the block that contains the keyword GUARDED will only be executed when the GUARD expression is TRUE. architecture RTL of EG1 is begin guarded_block: block (a = 1) begin z <= 1 when guard else 0; end block guarded_block; end architecture RTL ;
Presented by Abramov B. All right reserved 219
Blocks (cont)
Flip-flops and registers can also be generated with dataflow statements (as opposed to from a process) using a GUARDED block. signal input_sig, output_sig, clk : bit ;
b1 : block (clkevent and clk=1) begin output_sig <= guarded input_sig ; end block b1;
Presented by Abramov B. All right reserved 220
110
Blocks (cont)
Problem
221
Blocks (cont)
222
111
Blocks (cont)
223
Blocks (cont)
224
112
225
226
113
227
114
Key point to remember for register guarded signals : When all drivers are disconnected, the resolution function is NOT called, and therefore retains its previous value.
Presented by Abramov B. All right reserved 229
230
115
232
116
234
117
Simulation Levels
Stimulus
Non-portable
SIMULATOR STIMULUS COMMANDS
Design
DESIGN (SCHEMATIC OR OTHER)
235
Simulation Levels
Stimulus
Simple
BEHAVIORAL TESTBENCH RTL VHDL
Design
Complex
BEHAVIORAL TESTBENCH RTL VHDL
236
118
Test Methodology
Direct Test Designer knows the architecture of DUT (white box) and creates test stimulus adapted for DUT Advantage: Disadvantage: Usability: fast result, small set of test vectors. poorly coverage of all possible scenarios. single module test cases.
Random Test Test vectors generated in disregard to architecture requirements. Advantage: Disadvantage: Usability: large set of test vectors, easy to create erroneous scenarios. poorly productivity, only small subset of generated test vectors may be used system level simulation.
237
Test Methodology
Semi Random Test Designer knows the architecture of DUT, but creates test stimulus adapted for DUT using random mechanism for generation of erroneous scenarios.
Better productivity and reliability. complex to specify and implementation single module test cases, the next step after direct test.
238
119
Test Methodology
Number of detected bugs that with design coverage? If debugged?
Test Methodology
Useful tools for more testability and test productivity. Assert statements Interactive I/O to/from simulator shell Test vectors file and log files Vital library OVL library Bus Functional Models Third party models PLI interface with foreign languages models
Presented by Abramov B. All right reserved 240
120
241
242
121
243
122
123
247
124
249
125
procedure wait_n ( constant number_of_clock_cycles : natural; signal clock begin wait for ((number_of_clock_cycles * clock_period) 1 ns); wait until rising_edge (clock); end procedure wait_n; : in std_logic; constant clock_period : time :=C_CLOCK_P) is
252
126
Shared Variables
VHDL87 limited the scope of the variable to the process in which it was declared. Signals were the only means of communication between processes, but signal assignments require an advance in either delta time or simulation time. VHDL '93 introduced shared variables which are available to more than one process. Like ordinary VHDL variables, their assignments take effect immediately. However, caution must be exercised when using shared variables because multiple processes making assignments to the same shared variable can lead to unpredictable behavior if the assignments are made concurrently.
The VHDL 93 standard does not define the value of a shared variable it two or more processes make assignments in the same simulation cycle.
Presented by Abramov B. All right reserved 253
127
255
The following package uses shared variable to make the stack available to more that one procedure. The package declarative region is shown here declaring two procedures, push and pop. package int_stack_pack is procedure pop (what : in integer); procedure push(what : out integer); end package int_stack_pack;
Presented by Abramov B. All right reserved 256
128
257
129
Protected Type
We achieve mutual execution for a shared variable by declaring the Variable to be of a protected type. There are two parts to the definition of a protected type: protected type declaration protected type body Syntax: type t_name is protected declaration area end protected t_name; type t_name is protected body implementation area end protected body t_name;
Presented by Abramov B. All right reserved
259
130
131
263
264
132
266
133
Access Type
These are similar to pointer types found in many programming languages. In VHDL access type are used mainly in high-level behavioral models. We can declare an access type using a new form of type definition, given by the syntax rule:
For example : type int_ptr is access integer; This defines a new type, named int_prt ,representing values that points to data object of type integer. Once we have declared as access type, we can declare a variable of that type within process or subprogram: variable count : int_ptr;
Presented by Abramov B. All right reserved 267
268
134
269
135
136
274
137
Read list: ccell:=head; while (ccell/=null) loop s<=ccell.value; wait until rising_edge(clk); ccell:=ccell.next_cell; end loop;
Search for value: ccell:=head; while (ccell/=null ) loop ccell:=ccell.next_cell; exit when ccell.value=search_value; end loop; assert (ccell/=null) report search for value failed;
275
276
138
277
278
139
FSM Definition
Defined:
x = {x1 , x2 , , xn }
A = {a1 , a2 , , am } y = {y1 , y2 , , yk }
The transition function The output function The initial state -
- set of states
a1
279
280
140
281
282
141
283
a
00 -1
11
b
-0
10 01
DC
Presented by Abramov B. All right reserved
--
284
142
FSM forms
Many designs expressed at the register-transfer level consist of combinatorial data paths controlled by finite-state-machines -> FSM. There are basically two forms of state machines, Mealy machines and Moore machines. In a Mealy machine, the outputs depend directly on the present state and the inputs.
input signals Present clock reset state register Output logic output signals
Presented by Abramov B. All right reserved 285
input signals Present clock reset state register Output logic output signals Next state logic
286
143
input signals Present clock reset state register output signals Next state logic
287
FSM outputs
Moore FSM : The output vector (Y) is a function of state vector (S) only Y= f (S) (synchronous to state, unregistered outputs ) Medvedev FSM (Full Moore) : The output vector (Y) resembles the state vector (S) or the slice of state vector. Y = S ( synchronous to state, registered output) Good choice for latency dependent systems Mealy FSM : The output vector (Y) is a function of state vector (S) and the input vector (X) Y = f (S, X) (asynchronous to state, unregistered output) Full Mealy: The output vector (Y) resembles the next state vector (NS) or the slice of next state vector. Y = NS
Presented by Abramov B. All right reserved 288
144
289
Registered Output
For performance and reliability, register the outputs of a state machine which conforms to synchronous design methodology and simplifies the timing with all blocks that the outputs drive and improves the overall performance. Registering outputs makes the FSM a better candidate for reuse and ensures that the outputs will not be optimized. To reduce the latency of the outputs, implement one of the following two strategies : Decode the next state signal rather than the current state (Moore output decoding), this option is available if you implement a combinatorial next state decoding block. Implement a look ahead Mealy scheme of decoding the current state and inputs.
1. 2.
290
145
291
292
146
Case vs. IF
Case statements are the best implementation style, thats the reason we use them to define our state machines. If-then-else statements will generally infer priority encoded logic (cascaded logic adds delay), so we use case statement to achieve the most efficient use of our resources. We use case statements for next state decoding and output decoding.
293
Case vs. IF
Combinational Logic Inputs Case When If Then Else Next State CLKEVENT and CLK = 1 Flip Flops
Current State
294
147
Medvedev FSM
May be: state<= START when (rst=0) else next_st when rising_edge(clk);
148
FSM Performance
Factors affecting FSM performance are size, complexity, and state vector encoding. Size and complexity are determined by the design, and changes in performance cannot be affected without design changes. Encoding style attributes allows exploration of different coding styles and their effect on performance without having to change the FSM design or VHDL code.
298
149
299
FSM Performance
Many hardware compilers automatically encodes state vectors using Binary encoding when: the total number of states is 4 or less the total number of states is greater than 512 the target device has a CPLD architecture (SOP array) the Safe FSM option is enabled and automatically encodes state vectors using One-hot encoding when: the target device is not a CPLD (SOP array) the total number of states is 5 or greater the total number of states is 512 or less the Safe FSM option is disabled
Presented by Abramov B. All right reserved 300
150
FSM Encoding
TYPE_ENCODING_STYLE attribute can be applied to the label of the process to control the encoding of the implicit state machine. The TYPE_ENCODING_STYLE gives a hint to the compiler as to what kind of encoding style to choose. There are five different styles to choose from: BINARY,GRAY, ONEHOT, RANDOM, AUTO. Here is an example of how to use the TYPE_ENCODING_STYLE attribute on a (imaginary) state enumerated type: -- Declare the TYPE_ENCODING_STYLE attribute type encoding_style is (BINARY, ONEHOT, GRAY, RANDOM, AUTO) ; attribute TYPE_ENCODING_STYLE : encoding_style ; -- Declare the (state-machine) enumerated type : type my_state_type is (SEND, RECEIVE, IGNORE, HOLD, IDLE) ; -- Set the TYPE_ENCODING_STYLE of the state type : attribute TYPE_ENCODING_STYLE of my_state_type:type is ONEHOT ;
301
FSM Encoding
To fully control the state encoding, use the TYPE_ENCODING attribute. With the TYPE_ENCODING attribute you can define the state table used. Here is an example: The TYPE_ENCODING attribute takes an array of equal-length strings, where each string defines a row in the state table. Declare the TYPE_ENCODING attribute : type string_array is array (natural range <>, natural range <>) of character ; attribute TYPE_ENCODING : string_array ; -- Declare the (state-machine) enumerated type : type my_state_type is (SEND, RECEIVE, IGNORE, HOLD, IDLE) ; -- Set the type-encoding attribute : attribute TYPE_ENCODING of my_state_type: type is ("0001","0100","0000","1100","0010") ;
302
151
2 3 4 Data 5 6 Z
152
comb_logic: process(curr_state,wr,rd,ready) is begin cs <= '1'; rdn <= '1'; wrn <= '1'; ale <= '0'; next_state<=curr_st; case curr_state is when IDLE => if (wr='1') then next_state <=START_WRITE; elsif (rd='1') then next_state <=START_READ; end if; when START_READ => cs <='0'; rdn <='0'; next_state<=ALE_READ; when START_WRITE => cs <='0'; wrn <='0'; next_state<=ALE_WRITE; when ALE_READ => cs <='0'; rdn <='0'; ale <='1'; next_state<=WAIT_FOR_RREADY; when ALE_WRITE => cs <='0'; wrn<='0'; ale<='1'; next_state<=WAIT_FOR_WREADY; when WAIT_FOR_WREADY => cs<='0'; wrn<='0'; if (ready='1') then next_state<=IDLE; end if; when others => cs<='0'; rdn<='0'; if (ready='1') then next_state<=IDLE; end if; end case; end process comb_logic;
306
153
One-Hot FSM
constant IDLE : natural:=0; constant START_READ : natural:=1; constant START_WRITE : natural:=2; constant ALE_READ : natural:=3; constant ALE_WRITE : natural:=4; constant WAIT_FOR_WREADY : natural:=5; constant WAIT_FOR_RREADY : natural:=6; signal cstate : std_logic_vector(WAIT_FOR_RREADY downto IDLE); signal nstate : std_logic_vector(WAIT_FOR_RREADY downto IDLE); begin current_state_register: process (clk,rst) is begin if (rst='0') then cstate<= (IDLE=>'1',others=>'0'); elsif rising_edge(clk) then cstate<= nstate; end if; end process current_state_register;
Presented by Abramov B. All right reserved 308
154
One-Hot FSM
comb_logic: process (cstate,wr,rd,ready) is begin cs <= '1'; rdn <= '1'; wrn <= '1'; ale <= '0'; nstate <= (others=>'0'); if (cstate(IDLE)='1') then if (wr='1') then nstate(START_WRITE)<='1'; elsif (rd='1') then nstate(START_READ)<='1'; else nstate <= curr_state; end if; end if; if (cstate(START_READ)='1') then cs<='0';rdn<='0'; nstate(ALE_READ)<='1'; end if; if (cstate(START_WRITE)='1') then cs<='0';wrn<='0'; nstate(ALE_WRITE)<='1'; end if; Presented by Abramov B. All right reserved
309
155
One-Hot FSM
constant START_READ : natural:=0; constant START_WRITE : natural:=1; constant ALE_READ : natural:=2; constant ALE_WRITE : natural:=3; constant WAIT_FOR_WREADY : natural:=4; constant WAIT_FOR_RREADY : natural:=5; signal curr_state : std_logic_vector(WAIT_FOR_RREADY downto START_READ); signal next_state : std_logic_vector(WAIT_FOR_RREADY downto START_READ); begin current_state_register: process(clk,rst) is begin if (rst='0') then curr_state<= (others=>'0'); elsif rising_edge(clk) then curr_state<= next_state; end if; end process current_state_register;
Presented by Abramov B. All right reserved
311
One-Hot FSM
comb_logic: process (curr_state,wr,rd,ready) is begin cs <= '1';rdn <= '1'; wrn <= '1';ale <= '0'; next_state <= (others=>'0'); if (curr_state=0) then if (wr='1') then next_state(START_WRITE)<='1'; elsif (rd='1') then next_state(START_READ)<='1'; end if; end if; if (curr_state(START_READ)='1') then cs<='0';rdn<='0'; next_state(ALE_READ)<='1'; end if; . end process comb_logic;
Presented by Abramov B. All right reserved 312
156
FSM decomposition
In this section, we will learn a simple technique of FSM decomposition. As an example, we use Mealy FSM with 4 states
313
FSM decomposition
am a0 a1 C(am) 0001 0010 as a1 a3 a2 a0 a0 a0 a3 a0 a0 a0 C(as) X(am,as) 0010 0100 1000 0001 0001 0001 1000 0001 0001 0001 x1x2 x1 x1x2 x3x4 x1x2 x3 x1x2 x3x4 x3x4 x3x4 x3 Y(am,as) y1,y2 y1,y2 y3 y1,y2 y1,y2 y2,y3 y1,y2 y1,y2 D(am,as) D1 D2 D3 D0 D0 D0 D2 D0 D0 D0
a2 a3
0100 1000
314
157
FSM decomposition
Partition is the set of states: = {A1, A2,}; A1 = {a0, a1}; A2 = {a2, a3}; The number of component FSMs in the FSM network is equal to the number of blocks in partition . Thus, in our example, we have three component FSMs S1, S2. Let Bm is the set of states in the component FSM Sm. Bm contains the corresponding block of the partition plus one additional state bm. So, in our example: S1 has the set of states B1 = {a0, a1, b1}; S2 has the set of states B2 = { a2, a3, b2};
Presented by Abramov B. All right reserved 315
FSM decomposition
In Mealy FSM S4, there is a transition between ai and aj (left) and both these states are in the same component FSM Sm. In such a case, we have the same transition in this component FSM Sm.
Two states ai and aj are in different component FSMs . Let ai is in the component FSM Sm (ai B and aj is in the m) component FSM Sp (aj B In such a case, one transition of FSM S4 p). should be presented as two transitions one in the component FSM Sm and one in the component FSM Sp.
Presented by Abramov B. All right reserved 316
158
FSM decomposition
FSM Sm transits from ai into its additional state bm with the same input Xh. At its output, we have the same output variables from set Yt plus one additional output variable zj, where index j is the index of state aj in the component FSM Sp. FSM Sp is in its additional state bp. It transits from this state into state aj with input signal zj, that is an additional output variable in the component FSM Sm. The output at this transition is Y0 the signal with all output variables equal to zero.
317
FSM decomposition
x1x2x3/x1x2'x3/y1y2 a0 x1x2x3'x4/y1y2 x1'/y3z1 z1 x1/z3 x1x2/y2y3z2 z2 x3'x4/y2y3 x3'x4'/z3 b2 a1 a2 y2y3 a3
318
159
FSM decomposition
A1 = {a0 , a1 , b1};
am a0 a1 C(am) 001 010 as a1 a0 a0 a0 b1 C(as) 010 001 001 001 100 X(am,as) x1x2x3 x1x2x3x4 x1x2x3 x1 Y(am,as) y1,y2 y1,y2 y2,y3,z1 D(am,as) D2 D1 D1 D1 D3
b1
100
a0 b1
001 100
z3 z3
D1 D3
319
FSM decomposition
A2 = { a 2 , a 3 , b2 };
am a2 a3 C(am) 001 010 as a3 b2 b2 b2 C(as) 010 100 100 100 X(am,as) x1 x3x4 x3x4 Y(am,as) y2,y3 y2,y3 z3 D(am,as) D2 D3 D3 D3
b2
100
a2 b2
001 100
z1 z1z2
D1 D3
320
160
FSM reuse
FSM implementation as procedure. type ctrl_fsm is (write_word, check_num_of_wwords, write_to_ram, clear_buf, check_block_select, wait_on_rw, read_request, wait_on_mem_valid, send_word); subtype wrctrl_fsm is ctrl_fsm range write_word to wait_on_rw; subtype rdctrl_fsm is ctrl_fsm range check_block_select to send_word; signal wrctrl_curr_st : wrctrl_fsm; signal wrctrl_next_st : wrctrl_fsm; signal rdctrl_curr_st : rdctrl_fsm; signal rdctrl_next_st : rdctrl_fsm;
321
FSM reuse
procedure ext_mem_write ( signal curr_st signal write_req signal is_addr signal buff_full signal buff_we signal ext_mem_we signal buff_cnt_clr signal next_st : in wrctrl_fsm; : in std_ulogic; : in std_ulogic; : in std_ulogic; : out std_ulogic; : out std_ulogic; : out std_ulogic; : out wrctrl_fsm
) is
begin case curr_st is when .. when .. end case; end procedure ext_mem_write ;
Presented by Abramov B. All right reserved 322
161
FSM reuse
procedure ext_mem_read ( signal curr_st : in rdctrl_fsm; signal read_req : in std_ulogic; signal is_addr : in std_ulogic; signal buff_empty : in std_ulogic; signal read_valid : in std_ulogic; signal buff_re : out std_ulogic; signal ext_mem_re : out std_ulogic; signal next_st : out rdctrl_fsm
) is
323
FSM reuse
-- write control FSM from CPU to external RAM wctrl_fsm_register : process(sys_clk, sys_rst) is begin if (sys_rst = RESET_INIT) then wrctrl_curr_st <= wait_on_rw; elsif rising_edge(sys_clk) then wrctrl_curr_st <= ing_search_wrctrl_next_st; end if; end process wctrl_fsm_register; -- next state logic and output logic by ext_mem_write procedure
324
162
FSM rules
The possible states of the state machine are listed in an enumerated type. A signal of this type (present_state) defines in which state the state machine appears. In a case statement of one process, a second signal (next_state) is updated depending on present_state and the inputs. In the same case statement, the outputs are also updated. Another process updates present_state with next_state on a clock edge, and takes care of the state machine reset.
Here are a few general rules to follow: Only one state machine per module Keep extraneous logic at a minimum (try not to put other code in the same FSM) Instantiate state flip-flops separately from logic
325
FSM rules
when state_1 => if ((sig1=30) and (sig2<20)) then State 1 Sig1=30 and sig2<20 next_st<= state_2;
State 2
326
163
FSM rules
when state_1 => if (comp_out) then State 1 comp_out next_st<= state_2;
State 2
FSM rules
Build delay of N clock cycles from state 1 to state 2 State 1
clk 2
clk N-1
328
164
FSM rules
!cnt_done Build delay of N clock cycles from state 1 to state 2 State 1 Counter enable
cnt_done
State 2
Counter disable
329
FSM rules
cnt_done<= ( cnt = (N-1)); delay_counter : process (clk ,rst) is begin if (rst=0) then cnt<=(others=>0); elsif rising_edge (clk) then if (cnt_en) then cnt <= cnt + 1; else cnt <= (others =>0); end if; end if; end process delay_counter;
Presented by Abramov B. All right reserved 330
-- FSM logic when state_1 => cnt_en<=true; if (cnt_done) then next_st<= state_2; else next_st<= state_1; end if; . when state_2 => cnt_en<=false;
165
FSM rules
Try to minimize the number of control outputs signal of FSM:
FSM
331
FSM rules
-- FSM logic when state_1 => srst <= false; cnt_en<=true; if (cnt_done) then next_st<= state_2; else next_st<= state_1; end if; . when state_2 => cnt_en<=false; srst <= true; Synchronous reset is not always needs. Try to write according to previous example of counter
332
166
FSM rules
State signals utilization. Output1 <=1 when delay_cnt=0 Output2 <= 1 when delay_cnt=N (end of delay) state1
Delay_st
state2
333
FSM rules
First possible solutions: Three states, full synchronous. Split the delay state to three states delay_0 with signal 1=1 delay_2 with signal 2 =1 delay_1 that implements delay between delay_0 and delay_2
Delay_0
Delay_1
Delay_2
334
167
FSM rules
Second possible solutions: one state , asynchronous inputs. when delay_st => if (cnt_eq_zero) then output1<=1; else output_1<=0; end if; if (cnt_done) then output2<=1; else output_2<=0; end if; .. State_1 Delay_st state_2
335
FSM rules
Third solutions: One state , outside from FSM logic. Input condition to delay state
State_1
Delay_st
state_2
336
168
Safe FSM
Safe/Unsafe State Machines Safe State Machines: If the number of states N = 2n , where n is state register width, and you use a binary or gray-code encoding, the state machine is safe, because all of the possible states are reachable. Unsafe State Machines: n If the number of states N < 2 , or if you do not use binary or gray-code encoding, e.g. one-hot, the state machine is unsafe. A Safe State Machine has been defined as one that: Has a set of defined states Can jump to a defined state if an illegal state has been reached .
Presented by Abramov B. All right reserved 337
Safe FSM
Designers Beware!!! If using a CASE statement to implement the FSM, the others clause in your VHDL is ignored by the synthesis tools This logic will not get synthesized unless you explicitly attribute your FSM as Safe Synthesis tools offer a Safe option: type states is (IDLE, GET_DATA, SEND_DATA, BAD_DATA); signal current_state, next_state : states; attribute SAFE_FSM: Boolean; attribute SAFE_FSM of states: type is true;
Some versions of synthesis tools will not synthesize a Safe One-Hot FSM !!!
338
169
339
Safe FSM
Setting the FSM_COMPLETE attribute to true a synthesis tool to use transition specified by the VHDL default assignment to specify transition for unused states in the implementation. attribute FSM_COMPLETE : boolean; attribute FSM_COMPLETE of signal_name : signal is true;
340
170
Safe FSM
If a Binary encoded FSM flips into an illegal (unmapped) state, the safe option will return the FSM into a known state that is defined by the others or default clause If a Binary encoded FSM flips into a good state, this error will go undetected. If the FSM is controlling a critical output, this phenomena can be very detrimental! How safe is this?
341
Safe FSM
State(1) Flips upon SEU:
Using the Safe attribute will transition the user to a specified legal state upon an SEU
2 1 0
1 1
0 1
0 0
Good State
STATES (5): IDLE TURNON_A TURNOFF_A TURNON_B TURNOFF_B :000 :001 :010 :011 :100
Using the Safe attribute will not detect the SEU: This could cause detrimental behavior
2 1 0
342
171
Safe FSM
There used to be a consensus suggesting that Binary is safer than One-Hot Based on the idea that One-Hot requires more DFFs to implement a FSM thus has a higher probability of incurring an error This theory has been changed! The community now understands that although OneHot requires more registers, it has the built-in detection that is necessary for safe design Binary encoding can lead to a very un-safe design
343
Safe FSM
One-Hot Synthesis Safe directive will generally not work FSM becomes too large Each state in a One-Hot encoding has a hamming distance of two. Error Detection: During normal operation, only one bit is turned on, thus It inherently has SEU error detection SEU Error detection can be accomplished using combinational logic SEUs occurring near a clock edge will always be detected Binary Synthesis Safe directive generally will not meet requirements can flip into a good state undetected Binary Encoding has a hamming distance of One Error Detection: It needs extra DFFs in order to implement error detection Utilizing an extra DFF can cause a SEU to go undetected due to glitches and routing differences between combinational logic and DFFs.
Presented by Abramov B. All right reserved 344
172
Safe FSM
The state machine needs to be tolerant of single event upsets State machine should not hang State machine should always be in a defined state No asynchronous inputs to state machine Default state must be specified
345
inputs
Next state logic Current state register parity checker & parity generator
346
173
347
348
174
349
350
175
176
353
Advanced FSM
The primary architectures of FSMs usually have simple and regular structures at the top level. They are considered to be a composite of a combinational scheme and memory. The former calculates new states in state transitions and forms outputs, and the latter is used to store states. The top-level architecture can generally be reused for different applications. However, the combinational scheme is typically very irregular, and its implementation depends on the particular unique behavioral specification for a given FSM. Since such specifications vary from one implementation to another, we cannot construct a reusable FSM circuit. Another approach to the design of FSMs is based on the use of RAM blocks. It eliminates many of the restrictions that apply to traditional FSM architectures and current methods for FSM synthesis. Since very fast EMB (Embedded Memory Blocks) are available within widely used FPGAs, we can apply the proposed technique directly to the design of FPGA-based circuits. Such an implementation is very efficient.
354
177
355
178
358
179
180
361
181
182
183