A. Jawahar, Assistant Professor, ECE Dept. SSN College of Engineering Phone: 044 32909855 275 (Extn : 359) 91-9444067484 (cellphone) Email: jawahar_a@ssnce.ac.in Objective of this course Analysis a sequential network by signal tracing Given the problem statement for the design of a Mealy and Moore sequential network, find the corresponding state graph and table Reduce a state table to a minimum number of rows Guidelines in making state assignments and derive the flip flop input equations Design a sequential network using gates and flip flops Given a problem statement, design a iterative network Given a flow table, locate critical races, noncritical races and cycles Find the types of hazards and elimination of the same Fault diagnosis and testability using different algorithms Sequential network design with programmable logic devices Given a problem statement, design of digital system using VHDL REFERENCES: Donald G. Givone Digital principles and Design Tata McGraw Hill 2002. John M Yarbrough Digital Logic applications and Design Thomson Learning, 2001 Nripendra N Biswas Logic Design Theory Prentice Hall of India, 2001 Charles H. Roth Jr. Digital System Design using VHDL Thomson Learning, 1998. Charles H. Roth Jr. Fundamentals of Logic design Thomson Learning, 2004. Stephen Brown and Zvonk Vranesic Fundamentals of Digital Logic with VHDL Design Tata McGraw Hill, 2002. Navabi.Z. VHDL Analysis and Modeling of Digital Systems. McGraw International, 1998 Parag K Lala, Digital System design using PLD BS Publications, 2003 Peter J Ashendem, The Designers Guide to VHDL Harcourt India Pvt Ltd, 2002 Mark Zwolinski, Digital System Design with VHDL Pearson Education, 2004 Prerequisite What you should know: Minimum: Digital logic circuits, gates, flip-flops, registers, counters, simple logic functions, etc. Helpful: computer architecture, finite state machine logic minimization, truth tables, other hardware description languages, etc Helpful: Programming knowledge, Ada, Pascal, C, etc Expectations for Students What you should learn in this chapter: Logic design review Write VHDL models (five design units) Most of the seven concurrent statements Most of the thirteen sequential statements Arrays VHDL operators Modeling using VHDL Terminology Function - Input to output relationship Timing - Delays representing real digital circuits Structure (structural)- Description as an interconnection of lower level components (Often represented by a net-list) Behavior (behavioral) Definition 1 - Function plus timing Definition 2 - Description as logical or arithmetic operations versus structure Definition 3 - High-level operations versus lower-level RTL Design Automation Industry Terminology DA=Design Automation EDA = Electronic Design Automation CAD = Computer Aided Design (often implies layout/routing, one of the earliest design automation tools) LBD = Language Based Design (mostly VHDL and Verilog, but C and C++ getting lots of attention) Design Automation Industry Cadence Design Systems ($1.1 B/2003) San Jose, California - Early lead in CAD then merged with Verilog originator (Gateway) Synopsys ($1.18B/2003) Mountain View, California One of the first companies with VHDL Synthesis Mentor Graphics ($675 M) Wilsonville, Oregon (oldest of the big three) Pioneered schematic capture Forte ($20 M Est.) Summit (Unknown revenue) Transeda (Unknown revenue) Synplicity (Unknown revenue) Logic Introduction Logic circuits use two (i.e. binary) values: 0/1, low/high, or false/true Logic functions give outputs based on the values of the inputs (common operators are AND, OR, NOT, NAND, NOR, XOR, XNOR) Logic element: gate Hardware implementation of function - Output depends on the current values of the inputs Logic element: flip-flop or latch - Output depends on the sequence of inputs rather than only the current state. Simple Function Truth Tables A B AND OR XOR NAND NOR XNOR 0 0 0 0 0 1 1 1 0 1 0 1 1 1 0 0 1 0 0 1 1 1 0 0 1 1 1 1 0 0 0 1 A BUF NOT 0 0 1 1 1 0 Y <= A and B; Y A B Y <= A or B; A B Y Y <= A nor B; A B Y Y <= A nand B; Y A B Y <= A xor B; A B Y Y <= A xnor B; A B Y Y <= not A; A Y Schematic/VHDL Representations (combinational) Storage with Latch S R Y Y R Y Y S A latch (or flip-flops) stores one bit (binary digit) Latch with Enable En D Y Y En D Y Y Clocked Flip-Flop Clock Data There is a window of time around the clock active edge. The window begins at time Tsu before clock active edge and ends at time Th afterward. If D changes at any time during the setup- and hold-time window, the output of the FF is unpredictable (metastable). Clk Q D C D Q Latch vs. Flip-flop Q D E En D Q Latch Edge-sensitive Level sensitive Flip-flop En D Y Clk D Q Presentation Presentation Presentation Presentation Outline Outline Outline Outline VHDL Design Units Basic Language Elements What is VHDL? What is VHDL? What is VHDL? What is VHDL? What is VHDL? What is VHDL? What is VHDL? What is VHDL? VHDL is a hardware description language that can be used to model a digital system VHDL stands for VHSIC Hardware Description Language VHSIC stands for Very High Speed Integrated Circuit A hardware abstraction of the digital system is called an entity in this text Formalization of VHDL Formalization of VHDL Formalization of VHDL Formalization of VHDL Formalization of VHDL Formalization of VHDL Formalization of VHDL Formalization of VHDL The IEEE formally adopted the language as a standard ratifying it in 19S7, IEEE 1076. Like any IEEE standard there is a minimum five year period for modifications to the original This actually occurred in 1993 and VHDL-93 is now the official version of the language, however most tools provide support for older modules {VHDL-S7) and some are simply still catching up Features of VHDL Features of VHDL Non-propriety Language. Widely supported Hardware Description Language. Programming Language. Simulation Language. Documentation Language. Usable for logic synthesis. VHDL Design Units VHDL provides five different types of primary constructs called Design Units. Entity Declaration Architecture Body Configuration Declaration Package Declaration Package Body Entity Declaration - Describes the external view of the entity - Specifies the name of the entity being modeled and lists the set of interface ports. - Ports are signals through which the entity communicates with the other models in its external environment. - Specifies the declarations and statements that are part of the design. - May be shared by many design architectures. Entity Declaration entity enfify_nome is port ( [signuI] idenfifier {, idenfifier}: [mode] signoI_fype {, [signuI] idenfifier {, idenfifier}: [mode] signoI_fype}), end [enfify] [enfify_nome], entity HALF_ADDER is port (A,B: in B!T; SUN, CARRY: out B!T); end HALF_ADDER; Architecture Body & Declaration 8tyles Internal details of an entity are specified Structural Modeling As a set of interconnected components to represent structure. Data Flow Modeling As as set of concurrent assignments statements to represent data flow. Behavioral Modeling As a set of sequential assignment statements to represent behavior. Architecture Declaration urchitecture orchifecfure_nome of enfify_nome is fype_decIorofion | signoI_decIorofion | consfonf_decIorofion | componenf_decIorofion | oIios_decIorofion | offribufe_specificofion | subprogrom_body begin {process_sfofemenf | concurrenf_signoI_ossignmenf | componenf_insfonfiofion_sfofemenf | generofe_sfofemenf} end [orchifecfure] [orchifecfure_nome], 8tructural Modeling An entity is described as a set of interconnected components Architecture body composed of two parts Declarative part Specify the interface of the components Statement part Instantiate the declared components Example - Half Adder 8tructural style of Modeling architecture HA_STRUCTURE of HALF_ADDER is component XOR2 port (X,Y:in B!T;Z:out B!T); end component; component AND2 port (L,N:in B!T;N:out B!T); end component; begin X1:XOR2 port map (A,B,SUN); X2:AND2 port map (A,B,CARRY); end HA_STRUCTURE; Component Declaration Appears in declaration part of an architecture body. Declares the name and interface of a component in a structural description. Interface specifies the mode and the type of ports. component componenf nome [is] [port (Iisf of inferfoce porfs),] end component [componenf nome], component-name may or may not refer to the name of an entity already existing in a library if it does not exists, it must be explicitly bound to an entity. list-of-interface-ports specify the name, mode & type for each port (similar in entity declaration). Component nstantiation Represents an entity/architecture pair. Instantiations of components in architectures is a method to define hierarchy because architectures of components can have within them other components. Defines sub-component of the entity in which it appears. Associates the signals in the entity with the ports of that sub-component. Associates values with generics of that sub-component. Is equivalent to plugging a hardware component into a board and making the electrical connections between the pins of the component and the signals of the circuit board. component-label: name of the instance (legal identifier). component-name: must be the name of the a component declared earlier using a component declaration. association-list: associates signals in the entity, called actuals, with the ports of a component, called formals. actuals may be a signal, an expression for an input port, the keyword open to indicate a port that is not connected. formals two ways to perform association of formals with actuals: positional association and named association. componenf-IobeI: componenf-nome [port mup (ossociofion_Iisf)], Positional Association Association list of the form: actual 1 , actual 2 , actual 3 , , actual n Each actual in the component instantiation is mapped by position with each port in the component declaration. ---- signal declaration signal s1, s2, s3; ---- component declaration component nand2 port (a, b: in std_logic; z: out std_logic); end component; ---- component instantiation n1: nand2 port map (s1, s2, s3); Named Association Association list of the form: formal 1 =>actual 1 , , formal n => actual n Each actual in the component instantiation is mapped by position with each port in the component declaration. ---- signal declaration signal s1, s2, s3; ---- component declaration component nand2 port (a, b: in std_logic; z: out std_logic); end component; ---- component instantiation n1: nand2 port map (a => s1, b => s2, z => s3); The types of the formal and actual being associated must be the same. The modes of the ports must conform to the rule that if the formal is readable, so must the actual be, and if the formal is writable, so must the actual be. Since a locally declared signal is considered to be both readable and writable, such a signal may be associated with a formal of any mode. If an actual is a port of mode in, it may not be associated with a formal of mode out or inout. If an actual is a port of mode out, it may not be associated with a formal of mode in or inout. If an actual is a port of mode inout, it may be associated with a formal of mode in, out or inout. Association Rules Full Adder entity fulladd is port (a, b, c: in bit; sum, cout: out bit); end fulladd; architecture fulladd_str of fulladd is component XOR port (k, l: in bit; m: out bit); end component; component AND2 port (n, o : in bit; p: out bit); end component; component OR3 port (q, r : in bit; s: out bit); end component; signal s1, c1, c2, c3: bit; begin X1: XOR port map (a, B, s1); X2: XOR port map (s1, c, sum); A1: AND2 port map (a, b, c1); A2: AND2 port map (a, c, c2); A3: AND2 port map ( b, c, c3); O1: OR3 port map (c1, c2, c3, cout); end fulladd_str; Decoder 2-to-4 architecture decoder_str of decoder_2_to_+ is component NOT port (d: in bit; e: out bit); end component; component NAND3 port (p, q, r: in bit; s: out bit); end component; signal a_bar, b_bar: bit; begin !0: NOT port map (a, a_bar); !0: NOT port map (b, b_bar); N0: NAND3 port map (en, a_bar, b_bar, data(0)); N1: NAND3 port map (en, a_bar, b, data(1)); N2: NAND3 port map (en, a, b_bar, data(2)); N3: NAND3 port map (en, a, b, data(3)); end decoder_str; entity decoder_2_to_+ is port (a, b, en: in bit; data: out bit_vector (0 to 3); end decoder_2_to_+; open If a port in a component instantiation is not connected to any signal, the key word open can be used to signify that the port is not connected. ---- signal declaration signal s1, s2, s3; ---- component declaration component nand2 port (a, b: in std_logic; z: out std_logic); end component; ---- component instantiation n1: nand2 port map (s1, open, s3); 8tructural style of Modeling architecture archregister8 of register8 is begin process (rst, clk) begin if (rst = `1') then q <= (others => `0'); elsif (clk'event and clk = `1') then if (en = `1') then q <= data; else q <= q; end if; end if; end process; end archregister8; architecture deco_str of decoder is component inv port (k: in bit; l: out bit); end component; component nand3 port (m, n, o: in bit; p: out bit); end component; signal abar, bbar: bit; begin i0: inv port map (a, abar); i1: inv port map (b, bbar); n0: nand3 port map (en, abar, bbar, z(0)); n1: nand3 port map (en, abar, b, z(1)); n2: nand3 port map (en, a, bbar, z(2)); n3: nand3 port map (en, a, b, z(3)); end deco_str; entity decoder is port (a, b, en: in bit; z: out bit_vector( 0 to 3)); end decoder; Decoder Decoder Decoder Decoder Declarative Part Statement Part Data Flow Modeling Structure of the model is not explicitly specified, but implicitly deduced. Concurrent signal assignments are used. The ordering of the concurrent signal assignments are not important. Symbol (<=) implies an assignment of a value to a signal. Delay information is also included using after clauses. A Data Flow Model - Specifies the functionality of the entity without specifying its structure. - Shows the flow of information through the entity. - Uses the following statements Concurrent Signal Assignment Conditional Signal Assignment Selected Signal assignment Block Statement Concurrent Assertion Statement Concurrent 8ignal Assignment - A primary mechanism for modeling the data flow behavior of an entity. - Represents an equivalent process statement that assigns values to signals. - very useful to define data flow in behavioral modeling. - !n test benches, concurrent statements can serve to generate test design. A concurrent signal assignment is implicitly sensitive to all the signals used in waveforms. - All concurrent statements and process statement are order-independent Conditional 8ignal Assignment - Selects different values for the target signal based on the specified conditions. turget ~ opfions woveform(I) when condifionI eIse woveform(Z) when condifionI eIse --------- woveform(M-I) when condifion(M-I) eIse woveform(M) when condifion(M), architecture mux_df of mux2to1 is begin y <= a when sel = `0' else b; end mux_df; architecture HA_DF of HALF__ADDER is begin SUN <= A xor B after 8ns; CARRY <= A and B after +ns; end HA_DF; Dataflow style of Dataflow style of Dataflow style of Dataflow style of Modeling Modeling Modeling Modeling entity decoder is port (a, b, en: in bit; z: out bit_vector( 0 to 3)); end decoder; architecture deco_df of decoder is signal abar, bbar: bit; begin abar <= not a; bbar <= not b; z(0) <= not (en and abar and bbar); z(1) <= not (en and abar and b); z(2) <= not (en and a and bbar); z(3) <= not (en and a and b); end deco_df; Decoder Decoder Decoder Decoder entity mux8to1 is port (i: in bit_vector(7 downto 0); s: in bit_vector(2 downto 0); z: out bit); end mux8to1; architecture mux8to1_df of mux8to1 is begin z<= i[0| when s = 000" else i[1| when s = 001" else i[2| when s = 010" else i[3| when s = 011" else i[+| when s = 100" else i[5| when s = 101" else i[6| when s = 110" else i[7|;; end mux8to1_df: 8-to-1 Multiplexer 4-bit Comparator library ieee; use ieee.std_logic_116+.all; use ieee.std_logic_unsigned.all; entity comp is port (a, b: in std_logic_vector (3 downto 0); a_eq_b, a_gt_b, a_lt_b: out std_logic); end comp; architecture comp_df of comp is begin a_eq_b <= `1' when a = b else `0'; a_gt_b <= `1' when a > b else 0'; a_lt_b <= `1' when a < b else `0'; end comp_df; 8elected 8ignal Assignment with expression seIect forgef ~ opfions woveformI when choice_IisfI, woveformZ when choice_IisfZ, ----- woveformM-I when choice_IisfM-I, woveformM when choice_IisfM, - Selects different values for the target signal based on the specified conditions. architecture mux2to1_df of mux2to1 is begin with s select z <= a when 0, b when others; end mux2to1_df; entity priority is port (w: in bit_vector (3 downto 0); y: out bit_vector (1 downto 0); z: out bit); end priority; architecture priority_df of priority is begin with w select y <= 11" when `1000', 10" when 0100", 01" when 0010", 00" when others; with w select z <= `0' when `1000', `1' when others; end priority; Priority Encoder Concurrent Vs 8equential Concurrent - Appears outside the body of the process statement. - Event-triggered. architecture con of assign is signal a, b, z: bit; begin process a <= b; z <= a; end process; end con; Sequential - Appears within the body of the process statement. - Not event-triggered. architecture seq of assign is begin a <= b; z <= a; end con; Concurrent signal assignment is identical to the sequential signal assignment in terms of behavior. For every concurrent statement, there is an equivalent process statement with the same semantic meaning. Unaffected Value - An unaffected value can be assigned to a signal in a con- current signal assignment statement. - No change to the driver for the target signal. - An assignment of unaffected to a signal translates to a null statement in the equivalent process for the concur- rent signal assignment statement. mark <= access after 5 ns when strobe = `0' else unaffected; Block 8tatement - A concurrent statement, used for three purposes. To disable signal drivers by using guards. To limit scope of declarations including signal declarations. To represent portion of the hierarchy of a design - Has no execution semantics but provides additional semantics that appear within it. bIock-IobeI: bIock [(guord-expression)] [is] [bIock-heoder] [bIock-decIorofions] begin concurrenf sfofemenfs end bIock [bIock-IobeI], B1: block (strobe = `1') begin Z <= guarded not A; end block B1; - block-label: Necessary one and must be same at the end - guard-expression: An implicit signal called guard of type Boolean declared within the block. !t's values is always updated to reflect the value of the Boolean expression Signal assignment statements appearing within the block statement can use this guard signal to enable or disable the drivers. - block-header: Describes the interface of the block statement to its environment. - Any declarations within the block are visible only within the block. - Any number of concurrent statements can appear, possibly none. - very useful in modeling hardware elements that trigger on certain events (e.g. flip-flops, clocked logic). Block 8tatement - The only concurrent statement whose semantics are affected by the enclosing block statement are the guarded assignments. - Every guarded assignment has an equivalent process statement. B1: block (guard-expression) signal sign: bit; begin sign <= guarded waveform-elements; end block B1; B1: block (guard-expression) signal sign: bit; begin process begin if guard then sign <= waveform-elements; end if; wait on signals-in-waveform- elements, guard; end process; end block B1; impIicif -- signuI guord: 8ooIeon -- guord ~ guord-expression Block 8tatement - Blocks statements are non-synthesizable. - Block statement could be used to represent a portion of a design with optionally, a port association list. - However, vHDL already provides another more powerful mechanism to represent partitions of the design, the component instantiation statement. - The component instantiation statement is more powerful and practical than a block statement because Partition designs may be performed by different individuals. Partition designs may have multiple architectural representations. Unlike block, signals declared within an architecture of a component are not visible (limited in scope) by the architecture which instantiates a component. Block 8tatement Concurrent Assertion 8tatement An assertion statement present outside the process statement. - Used to report model errors, timing violations and signals with erroneous values. - Are also used as a debugging tool to alert the user of a particular situation and the time occurrence of this situation. - The following severity levels are recommended - Failure: Error in the model itself. - Error: Timing violations and invalid data not affecting the state of the model. - Warning: Timing violations and invalid data not affecting the state, but which could affect the simulation behavior of the model. - Note: message for debugging use. Concurrent Assertion 8tatement library ieee; use ieee.std_logic_1164.all; entity srff is port (s, r: in std_logic; q: out std_logic); end srff; architecture srff_assert of srff is begin assert not (s = 0 and r = 0) report no valid inputs severity error; end srff_assert; Behavioral Modeling Specifies the behavior of an entity as a set of statements that are executed sequentially in the specified order. Do not explicitly specify the structure of the entity but its functionality. The behavior of an entity is expressed using process statements. A process statement is itself a concurrent statement that can appear within an architecture body. Has sensitivity list and declarative part. consists of sequential signal assignment statements. architecture deco_behave of decoder is begin process (a, b, en) variable abar, bbar: bit; begin abar := not a; bbar := not b; if en = `1' then z(0) <= not (abar and bbar); z(1) <= not (abar and b); z(2) <= not (a and bbar); z(3) <= not (a and b); else z <= 1111"; end if; end process; end deco_behave; entity decoder is port (a, b, en: in bit; z: out bit_vector( 0 to 3)); end decoder; Decoder Decoder Decoder Decoder Process 8tatement A concurrent statement of an architecture. An architecture can have several processes to describe the concurrent operation of the various pieces of the architecture. A process statement contains sequential statements that describe the functionality of a portion of an entity in sequential terms. [process-label :] process [(sensitivity-list)] [is] [process-item-declarations] begin process_statement_part ::={sequential-statements} end process [process-label]; process_item_declarations ::= subprogram_declaration | subprogram_body | type_declaration | subtype_declaration | constant_declaration | variable_declaration | file_declaration | attribute_declaration | use_clause Process 8tatement SequenfioI-sfofemenfs ::~ voriobIe-ossignmenf-sfofemenf signoI-ossignmenf-sfofemenf | woif-sfofemenf | if-sfofemenf | cose-sfofemenf | Ioop-sfofemenf | nuII-sfofemenf | exif-sfofemenf | nexf-sfofemenf | osserfion-sfofemenf | reporf-sfofemenf Variable Assignment variables can be declared and used inside a process statement. A variable is assigned a value using the variable assignment VoriobIe-objecf :~ expression process (a) variable events_on_a: integer := -1; begin events_on_a := events_on_a + 1; end process; 8ignal Assignment Signals are assigned values using a signal assignment statement. The simplest from of a signal assignment statement is: signal-object<=expression[after delay-value|; A signal assignment statement can appear within a process or outside of a process. counter <= counter + 0010; par <= par xor din after 12ns; z <= (a0and a1) or (b0 and b1) or (c0 and c1); wait wait wait wait statement The wait statement is a sequential statement in a process or procedure and causes the suspension of a process statement or a procedure. When a process encounters a wait statement, whether it is an explicit or implicit wait, the process gets suspended until the condition to wake up the process occurs. The wait statement is the synchronization scheme for all concurrent statements. wait wait wait wait statement - syntax wuit [sensifivify_cIouse][condifion_cIouse] [fimeouf_cIouse], sensifivify_cIouse ::~ on sensifivify_Iisf -- sensifivify_Iisf ::~ signoI_nomes condifion_cIouse ::~ untiI condifion -- condifion ::~ 8ooIeon_expression fimeouf_cIouse ::~ for fime_expression wait on wait on wait on wait on The wait on sensitivity" suspends a process until the occurrence of another event on one of the signals in the sensitivity list. wait on s1, s2 -- the process will be suspended until an event occurs on either s1 or s2. wait until wait until wait until wait until The wait until condition" suspends a process until the condition following the until" is satisfied. !f there is no sensitivity list in the wait until clause, then there is an implicit sensitivity list on all the signals expressed in the condition clause. wait until clk = `1' -- process to have an implicit sensitivity list to clk -- above statement is equivalent to wait on clk until clk = `1' wait for wait for wait for wait for The wait for time_expression" suspends a process until the elapsed time in the time expression wait for 50 ns; -- the process will be suspended for 50 ns. -- process resumes unconditionally afterwards. wait for 0 ns; -- process will be suspended for 1 delta time. Delta time Delta time Delta time Delta time A delta time is an infinitesimal amount of time that represents a time greater than zero, but is zero when added to a discrete amount of time. To ensure that the simulation of the concurrent statements is order independence, the simulator should tag the signals for an update when all the processes have completed execution for the current time period. This time is called delta time. if if if if statement An if statement selects for execution one or more enclosed sequences of statements, based on the value of one or more corresponding conditions. The condition can be any expression that evaluates to a Boolean value. orchifecfure muxZ of mux is begin process (o, b, s) begin if s ~ '0' fhen ; ~ o, eIsif s ~ 'I' then ; ~ b, eIse ; ~ 'Z', end if, end process, end muxZ, [if_IobeI:] if condifion then sequence_of_sfofemenfs eIsif condifion then sequence_of_sfofemenfs [eIse sequence_of_sfofemenfs] end if [if_IobeI], condifion ::~ 8ooIeon_expression sequence_of_sfofemenf ::~ sequenfioI_sfofemenfs if if if if statement Avoid using more than 3 levels of if-else-end if statements. !f more than 3 levels are required, encapsulate the inner nested levels with procedure calls. !ndent and label each if statement. When defining the condition, use parenthesis to differentiate the levels of operations on condition. Group the operations in a logical and readable order. -- All rules enhance code readability. if statement - rules A case statement selects for execution one of a number of alternative sequences of statements. cose_sfofemenf ::~ [cose_IobeI:] cuse expression is cose_sfofemenf_oIfernofive_porf end cuse [cose_IobeI], cose_sfofemenf_oIfernofive_porf ::~ when choices ~ sequence_of_sfofemenfs, choices ::~ simpIe_expression | discrefe_ronge | eIemenf_simpIe_nome | ofhers case case case case statement case case case case statement type week_day is (mon, tue, wed, thu, fri, sat, sun); type dollars is range 0 to 10; variable day:week_day; variable pocket_money:dollars; case day is when tue => pocket_money := 5; when monfwed => pocket_money := 6; when fri to sun => pocket_money := 7; when others => pocket_money := 0; end case; Choices in a case statement - Nust be a locally static expression. - Should be separated by 1 blank line and should be indented. The sequence of statements should immediately follow the case alternative specification and indented by at least 2 spaces. case case case case statement - rules Nust be a discrete type. Keep the expression for the case statement simple. When the expression is complex, compute the expression using a variable and use that variable as the expression in the case statement. Every possible value of the case expression must be covered in one and only one when clause. Array case expression must have a static subtype. case case case case expression - rules null null null null statement A sequential statement that does not cause any action to take place Execution continues with the next statement. for j in 10 downto 5 loop if sum < total then sum = sum + 2; elsif sum = total then next; else null; end if; end loop; loop loop loop loop statement Used to execute a sequence of statements zero or more times. Three forms - simple loop, while loop and for loop. Ioop_sfofemenf ::~ [Ioop_IobeI:] [iferofion_scheme] Ioop sequence_of_sfofemenfs end Ioop [Ioop_IobeI], iferofion_scheme ::~ whiIe condifion | for Ioop_poromefer_specificofion poromefer_specificofion ::~ idenfifier in discrefe_ronge discrefe_ronge ::~ discrefe_subfype_indicofion | ronge 8imple loop The simple loop does not have an explicit iteration scheme. The implicit iteration scheme is while true", thus looping forever. To exit an infinite loop, use the exit statement. Do not use while true loop, use instead loop since while true statement is redundant and the simple loop is sufficient. 8imple loop statement pr1: process variable max : natural := 10; variable count : natural := 10; begin max := 6; simple_loop: loop count := count +1; if count := max then exit; --- loop iterates 6 times, exit current loop end if; end loop; end process pr1; while loop while loop !terates as long as the condition expressed in the while statement is true. Often used to execute a set of sequential statements while a signal or a variable meets a certain criteria. For a loop with a while iteration scheme, The condition evaluated before each execution of the sequence of statements. If the condition is true, then the sequence is executed Else the iteration scheme is said to be complete and execution of the loop statement is complete. pr1: process variable count : natural := 10; begin wait until clk = `1' new: while receive = `1' loop count := count +1; end loop; -- if the while loop fails the process gets suspended until next rising of the clk. end process pr1; while loop while loop for loop for loop The loop parameter type for the for iteration loop scheme is the base type of the discrete range and is not explicitly defined as a type but implicitly defined from the range. When defining loop parameter specification, either use a typefsubtype definition or use predefined attributes. Avoid using discrete range. This rule makes the code more flexible for maintenance. for Ioop_poromefer_specificofion poromefer_specificofion ::~ idenfifier in discrefe_ronge discrete_runge ::= discrete_subtype_indicution | runge for loop for loop pr1: process begin factorial := 1; new: for number in 2 to N loop count := factorial * number; end loop; -- the body of the for loop is executed (N-1) times, with loop identifier, number, being incremented by 1 at the end of the iteration. -- the object is implicitly declared within the for loop belonging to the integer whose values are in the range 2 to N. end process pr1; for for for for loop rules Loop parameter is not explicitly defined , but implicitly defined. Loop parameter's range is tested at the beginning of the loop, not at the end. Loop parameter is an object whose type is the base type of the discrete range. Loop parameter is a constant, it may be used but not altered. Loop parameter must not be given as an actual corresponding to a formal of mode out or inout in an association list. !f within the loop a procedure is called, the value of the loop parameter can be passed to that procedure as an input, but not as an output, since an output will attempt to modify the loop parameter. for for for for loop rules Loop parameter's discrete range may be dynamic. The discrete range of the loop is evaluated before the loop is first executed. !f the discrete range is null range, then the iteration scheme and the execution of the loop are is said to be complete. Otherwise the sequence is executed once for each value of the discrete range, after which the iteration is said to be complete. Prior to each iteration, the corresponding value of the discrete range is assigned to the loop parameter. for loop rules - next A next statement is used to complete the execution of one of the iterations of an enclosing loop statement. nexf_sfofemenf ::~ net [Ioop_IobeI][when condifion] new: for j in 10 downto 5 loop if sum < total then sum = sum + 2; elsif sum = total then next; else null; end if; end loop new; next next next next - rules A next statement with a loop is allowed within the labeled loop and applies only to that loop. A next statement without a loop label is only allowed within a loop, applies to the innermost enclosing loop (whether labeled or not). For the execution of the next statement, the condition, if present, is first evaluated. The current iteration loop is terminated if the value of the condition is true or if there is no condition. !f the condition for the when is simple, insert the condition in-line, otherwise compute the condition using a variable. - enhances code readability. for loop for loop for loop for loop rules - exit An exit statement is used to complete the execution of an enclosing loop statement. exif_sfofemenf ::~ eit [Ioop_IobeI][when condifion] sum := 1; J:=0; L3: loop J:= J+ 21; sum := sum * 10; if sum >100 then exit L3; end if; end loop L3; exit exit exit exit - rules The completion is conditional if the statement includes a condition. A exit statement with a loop is allowed within the labeled loop and applies only to that loop. A exit statement without a loop label is only allowed within a loop, applies to the innermost enclosing loop (whether labeled or not). For the execution of the exit statement, the condition, if present, is first evaluated. The current iteration loop is terminated if the value of the condition is true or if there is no condition. assertion 8tatement Used to report model errors, timing violations and signals with erroneous values. Are also used as a debugging tool to alert the user of a particular situation and the time occurrence of this situation. The following severity levels are recommended - Failure: Error in the model itself. - Error: Timing violations and invalid data not affecting the state of the model. - Warning: Timing violations and invalid data not affecting the state, but which could affect the simulation behavior of the model. - Note: message for debugging use. assertion 8tatement !f the value of the Boolean expression false, the report message is printed along with severity level. ussert 8ooIeon_expression [report sfring_expression] [severity expression], if d'event then assert new = 0 ns or report hold time too short" severity failure; end if; report statement report sfring_expression [severity expression], A report statement can be used to display a message. When a report statement is executed, it causes the specified string to be printed and the severity level to be reported to the simulator for appropriate action. Similar to assertion statement, but without the assertion check. if d'event then assert new = 0 ns or report hold time too short" severity failure; end if; and gate entity and21 is port (a1, b1: in bit; y1: out bit); end and21; architecture and_be of and21 is signal ab: bit; begin ab <= a1 & b1; process (ab) begin if (ab = 11) then y1 <= 1; else y1 <= 0; end if; end process; end and_be; half adder entity halfadd is port (a, b: in bit; sum, cout: out bit); end halfadd; architecture halfadd_be of halfadd is begin process (a, b) if (a xor b) then sum <= 1; elsif (a and b) then cout <= 1; else sum <= sum; cout <= cout; end if; end process; end halfadd_be; Mixed 8tyle of Modeling All three modeling styles are also mixed in a single architecture body. An architecture body consists of Component instantiation statements. Concurrent signal assignment statements. Process statements entity full_adder is port (a, b, cin: in bit; sum, cout: out bit); end full_adder; architecture full_adder_mix of full_adder is --- structural model component xor2 port (p, q: in bit; r: out bit); end component; signal s1: bit; begin x1: xor2 port map (a, b, s1); --- data flow model sum <= s1 xor cin; Full Adder Full Adder Full Adder Full Adder --- behavioral model process (a, b, cin) variable c1, c2, c3: bit; begin c1 := a and b; c2 := b and cin; c3 := a and cin; cout <= c1 or c2 or c3; end process; end full_adder_mix; Configuration Declaration A configuration declaration is used to select one of the possibly many architectures bodies that an entity has to bind components, which are used to represent structure in that architecture body, to entities represented by an entity- architecture pair or by a configuration, which reside in a design library. Configuration Declaration library cmos_lib, my_lib; configuration half_bind of half_add is for half_str for x1: xor2 use entity cmos_lib.xor_gate; end for; for a1: and2 use configuration my_lib.and_con; end for; end for; end half_bind; Package Declaration Used to store frequently used declarations such as components, types, procedures and subprograms (procedures and functions). Declarations can then be imported into other design units using a use clause. pockoge_decIorofion :~ puckuge idenfifier is pockoge_decIorofive_porf end [puckuge] [idenfifier], Package Declaration All items in the package declarative part are visible to any package body that uses the package declaration. Possible to selectively import declarations from a package declaration into other design units. Items declared in a package are immediately visible to all subsequent declarations in the same package. The items in a package declaration and package body are visible to any other design unit which has been given explicit access through a use clause. Package Body Stores the definitions of functions and procedures that were declared in the corresponding package declarations and also the complete constant declarations. A package body canot exist without package declaration. A package declaration can have atmost one package body associated with it. Package body is not necessary if the corresponding package declarations has no function or procedure declarations and no deferred constant declarations. The identifier is the same as the identifier in the package declaration. package_body ::= package body identifier is package_body_declarative_part; end [package body] [identifier]; 8-to-1 Multiplexer sZ s0 sI o(0) o(Z) o(3) o(4) o(b) o(o) o(7) o(I) ouf 2-to-1 Multiplexer library ieee; use ieee.std_logic_1164.all; entity mux2to1 is port (a, b, s: in std_logic; z: out std_logic); end mux2to1; architecture mux of mux2to1 is begin with s select z <= a when 0, b when others; end mux; Package Declaration & Package Body library ieee; use ieee.std_logic_116+.all; package mux_pack is component mux2to1 port (a, b, s: in std_logic; z: out std_logic); endcomponent; end mux_pack; library ieee; use ieee.std_logic_116+.all; library work; use work.mux_pack.all; architecture mux of mux8to1 is signal m1, m2, m3, m+, m5,m6: std_logic; begin m1: mux2to1 port map (a(0), a(1), s(0), m1); m2: mux2to1 port map (a(2), a(3), s(0), m2); m3: mux2to1 port map (a(+), a(5), s(0), m3); m+: mux2to1 port map (a(6), a(7), s(0), m+); m1: mux2to1 port map (m1, m2, s(1), m5); m1: mux2to1 port map (m3, m+, s(1), m6); m1: mux2to1 port map (m5, m6, s(2), z); end mux; entity mux8to1 is port (a: in std_logic_vector(0 to 7); s: in std_logic_vector(0 to 2); z: out std_logic); end mux8to1; 8 88 8- -- -to to to to- -- -1 Multiplexer 1 Multiplexer 1 Multiplexer 1 Multiplexer Basic Language Elements - Fundamental structures of the language -Identifiers, Delimiters, Literals -Data Objects (Constants, Variables, Signals, Files) -Data Types and Its subtypes -Operators 8yntax - The pattern or structure of the word order in a phrase. - Refers to rules for statements spelled out in the LRM (Language Reference Manual) and verified by a VHDL analyzer or compiler. - Latitude in the rules allows a programmer the choice of syntax for particular program statements that reflects his style. - This can cause significant variations in style and can affect the overall readability of a program. dentifiers - The names that identify various objects, procedures, functions, processes, etc. - Two kinds of identifiers - Basic Identifiers - Extended Identifiers. bosic_idenfifier::~Leffer {[underIine]Ieffer_or_digif} Ieffer ::~ upper_cose_Ieffer | Iower_cose_Ieffer e.g. legal: intr_5, zero_to_3 illegal: !ntr-, 0_to_3, _to_, abc@def. Basic dentifiers - Composed of a sequence of one or more characters. - Can only contain letters, numbers and underscores. - Can be of any length as long as the entire identifier appears within a line. - No distinction between upper & lower case letters. - Cannot have the same name as a keyword. - Must begin with a letter. - Cannot have underscore at the beginning, end or side by side. Underscores are significant. - No special characters allowed. - No space is allowed since it is a separator. Extended identifiers - A sequence of characters written between two backslashes. - Used to integrate VHDL code with other tools which use extended identifiers. - Case sensitive and special characters like ., !, @, `, and $ can also be used. e.g. legal identifiers: /TEST/, /Q@BCD/ illegal identifiers: /TeSt/, Abc@Def. - Avoid the use of extended identifiers because - They reduce the readability - They cause errors since they are case sensitive. Port dentifiers Port names should not exceed 16 characters including size of array - Tool specific requirement. Port names should be same as name of the connecting signal in next level architectures and must be same as port names in other connecting entities. For large designs, port names should identify the origin of the design partition. Port names should identify polarity of signals. Port names may identify a registered or delayed version of an original, non delayed signal. Capitalization Lower case should be used for all VHDL reserved words and VHDL attribute definitions. Mixed case should be used for all other identifiers, with consistent casing in all code. User defined key words should not depend on capitalization to be readable or meaningful. When user identifiers are in mixed or uppercase, they stand out. Delimiters - Delimiters are the symbols that have special meaning within VHDL. - These symbols are used as operators and statement terminators. - There are single delimiters (only one symbol) and double delimiters (two symbols). - No spacing is allowed before or after the following delimiters - The sharp # -- 16#E45F# - The period . -- data.enable - The single quote ` -- clk`event (bus`transaction) - Bit literals must be bracketed with double quotes with no spaces inside the quotes Delimiters - Avoid using spacing before the following delimiters: - Semicolon ; - Colon : --- after a label only, use spacing elsewhere - Parenthesis ( ) --- may be started on a continuation line - For all other delimiters, use one or more spacing before and after using the delimiter. - These rules enhance code readability. - The semicolon is a terminator and needs no separator. - The colon after a label can be thought of as part of the label. - Long lines are more readable when elements embraced in parenthesis are started on a new continuation line. Literals - A value, directly specified in the description of a design. - Types - decimal literals - based literals - character literals - string literals - bit string literals. - Use underscores for numerical literals to enhance readability Decimal & Based Literals decimoI_IiferoI ::~ infeger[.infeger][exponenf] 12, 0, 123_+56 -- integer literals 12.0, 0.23+, 3.1+1_78 -- real literals 1.31E-12, 1.0E+9 -- real literals with exponent base#based_integer[.based_integer|[exponent| 2#11_11#, 16#FF# -- integer literals 6#F.FFE+2 -- real literals with exponent Character Literals A letter of character type. Formed by enclosing one of the graphics characters between two apostrophe () characters. Eg. A, * 8tring Literals A sequence of graphics characters or possibly none, enclosed between quotation marks (). Its type is determined from the context This is a string A string must fit on one line Longer sequences can be obtained by concatenation of string literals. First part of a sequence of characters that continues on next line --- one string literal Bit 8tring Literals Formed by a sequence of extended digits enclosed between two quotations and preceded by a base specifier. Its type is determined from the context. Its length is the length of its string literal value. An underscore character inserted between adjacent character digits of a bit does not affect the value of this literal bif_sfring_IiferoI ::~ bose_specifier "[bif_voIue]" bose_specifier: 8 - binory (I,0), O - OcfoI (0,,,7) X - HexodecimoI (0, ,, 9,A, ,, 8) Data Ob]ects A data object holds a value of a specified type. Created by means of an object declaration variable COUNT:INTEGER; Every data object belongs to one of the following four classes. Constant Signal variable File Constants An object whose value may not change, i.e. constants are used to hold a static value. Value is assigned to the constant before simulation starts and the value cannot be changed during the course of the simulation. For a constant declared within a subprogram, the value is assigned to the constant every time the subprogram is called. Play very important role in VHDL because they create more readable and maintainable code. Use constants to define data parameters and table lookups. Constants consfonf_decIorofion ::~ constunt idenfifier_Iisf: subfype_indicofion [:expression], my_process: process (rst, clk) constant amount: std_logic_vector (3 downto 0) = 0000; begin wait until clk = 1; if (rst = 1) then q <= amount; elsif (en = 1) then q <= data; else q <= q; endif; end my_process; Constants constant rise_time: time := 10ns; -- declares the constant object rise_time of type time and assigns a value of 10ns at the start of simulation. constant bus_width: integer := 10; -- declares the constant object bus_width of type integer and assigns a value of 10 at the start of simulation. constant no_of_inputs : integer; -- the value of the constant is not specified -- called as deferred constant. -- can appear only inside a package declaration. -- the complete constant declaration with the associated value must appear in the corresponding package body. 8ignals Most commonly used data objects in synthesis designs All basic designs and many large designs can be fully described using signals as the only kind of data object. Signals have projected output waveforms. Signal assignment are scheduled, not immediate. They update projected waveforms. architecture full_adder of full_add is signal c1, c2, c3: std_logic; begin x1: xor3 port map (a, b, c_in, sum); a1: and2 port map (a, b, c1); a2: and2 port map (b, c_in, c2); x1: and2 port map (a, c_in, c3); x1: or3 port map c1,c2,c3, c_out); end full_adder; 8ignals A signal is defined in The declarative part of a package. The declarative part of an architecture. The declarative part of a block. The formal parameters of a subprogram. A signal has three properties attached to it, including: Type and type attributes Type insures consistency in operations on objects Attribute defines characteristics of objects. Value - Includes current, future and past value. Time - Represents a time associated with each value. Future values can be assigned to a signal using a signal assignment statement. 8ignals signal clock: bit; -- declares the signal object clock of type bit and gives it an initial value of `0'. signal gate_delay: time := 10 ns; -- declares the signal object gate_delay of type time and gives it an initial value of 10ns. signal new: std_logic_vector (3 down to 0) := ( 0 => `1',others => `U'); -- declares a +-element signal array new of type std_logic_vector and gives the value to 0th element and the value `U' to all other elements. Variables A variable is defined in The declarative part of a process. The declarative part of a subprogram. A variable is also defined as a shared variable in The declarative part of a package. The declarative part of an architecture. A signal has two properties attached to it, including: Type and type attributes Like signal properties but no attributes associated with time. Value - No time history. Different values can be assigned to the variable at different times using variable assignment statement. Variables variable new: bit_vector (+ down to 0); -- declares the variable object new of type bit_vector as an array of 5 elements. variable sum: integer range 0 to 100 :=10; -- declares the variable object sum of type integer and gives it an initial value of 10. !f no initial value is specified, a default value is given. 8ignals & Variables Use signals as channels of communication between concurrent statements (e.g. components, processes). To describe storage elements , use variables instead. Signals occupy storage two time as variables do during simulation. Files An object belonging to a file class, contains a sequence of values. Values can be read or written to the file using read procedures and write procedures, respectively. Used to represent objects in files in the host environment. fiIe fiIe-nomes: fiIe-fype-nome [ [open mode] is sfring-expression] string-expression:= Interpreted by the host environment as the physical name of the file. mode:= Specifies whether the file is to be used as read-only or write- only or in the append mode. Files -- fiIe fype decIorofions type sfd_Iogic_fiIe is fiIe of sfd_Iogic_vecfor, type bif_fiIe is fiIe of bif_vecfor, -- fiIe decIorofions fiIe sfimuIus:fexf open reod_mode is "/user/vvn.sfi", -- decIores o fiIe sfimuIus of fype fexf. -- The fiIe moy be opened in o reod-onIy mode ond fhe pofh nome wiII be "/user/vvn.sfi" fiIe oob, obb: sfd_Iogic_fiIe, -- decIores fwo fiIes oob, obb of fype sfd_Iogic_fiIe. -- no Iink is specified ond moy nof be opened during eIoborofion -- fiIe shouId be expIicifIy opened using o fiIe open procedure. Data Types VHDL types and subtypes represent the set of values and a set of operations. VHDL has a set of predefined types in the std_package. e.g. type bit is (0, 1); type Boolean is (true, false); type integer is range defined The language also provides the facility to define new types by using type declarations define a set of operations on these types by writing functions that return values of this new type. Data Types Four categories. Scalar types Values belonging to these types appear in a sequential order. Composite types These are composed of elements of single type (an array type) or elements of different type (a record type). Access types These provide access to objects of given types (via parameters). File types These provide access to objects that contain a sequence of values of a given type. 8calar types Values belonging to these objects are ordered, i.e. relational operators can be used on these values. Four kinds Enumeration Integer Floating point. Physical 8calar types Enumeration Types Defines a type that has a set of user-defined values consisting of identifiers and character literals type new is (U, 0, 1, Z); -- new is enumeration type that has a set of ordered values U, 0, 1 and Z Integer Types Defines a type whose set of values fall within a specified integer range type new is range 0 to 15; -- new is integer type that includes integer values from 0 to 15 8calar types Floating Point Types Have a set of values in a given range of real numbers variable new is real_data range -1.0 to 14; -- new is a variable of object type real_data whose values will be real values from -1.0 to 14 Physical Types Contain the values to represent the measurement of some physical quantity (time, length, voltage or current). These type values are expressed as integer multiples of a base unit. type current is range 0 to 1E9; units nA; -- base unit. uA = 1000nA; mA = 1000uA; Amps = 1000mA; end units; Composite types Represent a collection of values Tow types: Array types Record types Array types Represent a collection values all belonging to a single type type address_bus is array (0 to 63) of bit; -- address_bus is a one-dimensional array object that consists of 64 elements of type bit. Composite types Record types Represent a collection values that may belong to different types Analogous to the record data type in PASCAL and the struct declaration in C. type bus is range 0 to 10; type module is record size : integer range 20 to 100; crit_delay : time; !nputs_no : bus; outputs_no : bus; end record; Access types Values belonging to access types are pointers to dynamically allocated some other type. Analogous to the pointers in PASCAL and C. type new is access module; -- new is an access type whose values are addresses that point to objects of type module. File types Represent files in the host environment. Provide mechanism by which a VHDL design communicates with the host environment. type file-type-name is file of type-name; type-name:= Type of values contained in the file. type vectors is file of bit-vector; -- a file of type of vectors has a sequence of values of type bit_vector 8ubtypes Subtype is a type with a constraint, which specifies the subset of values for the subtype. The type is called base type of the subtype. The set of operations belonging to a subtype is the same as that associated with its base type. An object is said to belong to to a subtype if it is of the base type and if satisfies constraints. Subtype declarations are used to declare subtypes. Subtypes are useful for range checking and for imposing additional constraints on types. Operators Logical operators Relational operators Shift operators Adding operators Multiplying operators Miscellaneous Operators Logical Operators - Operators: not , and , or , nand , nor , xor , xnor - Used frequently to generate Boolean equations. - Predefined types bit and Boolean. - Are also defined for one dimensional arrays of bit and Boolean. - During evaluation, bit values `0' and `1' are treated as false" and true" values of the Boolean type respectively. - The result of a logical operation has the same type as its operands. - The not operator is a unary operator and has same precedence as that of miscellaneous operators. Logical Operators nand and nor operators are not associative The syntax of an expression with a sequence of nand and nor operators is illegal. signal a, b, c, d: std_logic; . . . . d <= a nand b nand c; ----illegal Parenthesis can be used to avoid this problem d <= (a nand b) nand c; ----legal Relational Operators - Operators: = , /= , < , <= , > , >= - Used frequently for comparisons. - = (equality) and /= (inequality) operators are predefined for any type except file type. - The remaining four operators are predefined on scalar type or discrete array type. When operands are discrete array type, comparison is performed one element at a time from left to right. bit_vector (0, 1, 1) < bit_vector (1, 1, 1) 8hift Operators - Operators: sll , srl , sla , sra , rol , ror - Used occasionally. - Each of the operator takes an array of bit or Boolean as the left operand and an integer value as the right operand and performs the specified operation. - If the integer value is negative number, the opposite action is performed. (i.e. left shift or rotate => right shift or rotate) Adding Operators Operators: + , - , & Used frequently to describe increments, decrements, adders and subtractors. + (addition) and - (subtraction) operators The operands must be of same numeric type and the result is also same numeric type. Also used as unary operators, where the operand and result is also same type. & (concatenation) operator The operands can be either a one dimensional array type or an element type. The result is always an array type. 0 & 1 - results in an array of characters 01 Multiplying Operators Operofors: * , / , mod , rem The * (multiplication) and / (division) operators They are predefined for both operands being of same integer or floating point type. The result is of the same type. * operator is also defined for the case when one of the operands is physical type and second operand is of integer or real type. For / operator, The division of a value of physical type by either an integer or real value is allowed and the result type is physical type. The division of a value of physical type by another object of the same physical type is also defined and the result type is integer type. variable a, b: integer range 0 to 255; . . . . a <= b * 2; Multiplying Operators The rem (remainder) and mod (modulus) operators operate on operands of integer types and the result is also of the same type. The result of rem operation has the sign of its first operand. a rem b = a - (afb) * b; 7 mod + ---- has value 3 (-7) rem + ---- has value -3. 8ign Operators - Operators: + , - - Rarely used for synthesis. - Predefined for any numeric type (floating-point or integer) variable a, b: integer range 0 to 255; . . . . a <= - (b + 2); Miscellaneous Operators - Operators: ** , abs - The abs (absolute) operator, defined for numeric type. - the ** (exponentiation) operator is defined for the left operand to be of integer or floating point type and for the right operand (i.e. the exponent) to be of integer type only. - The not logical operator has the same precedence as above two operators. Coding 8tyle Coding 8tyle Requirements Requirements Code must abide by the VHDL language rules. Code should have a common look and feel. Code should be easily readable and maintainable. Code must yield expected results Simulatable code should be efficient from a simulation viewpoint. Synthesizable code must abide to vendors synthesis rules. Any Queries ? Please Contact jawahar_a@ssnce.ac.in Thank You