 In the previous lecture, we have looked at various components of the VHDL language. We have looked at object types, we have looked at data types, we have seen how physical quantities can be represented with units and then we had seen how composites and various user defined types and subtypes can be used in VHDL. This defines the basic structure of the language. We now want to look at the styles in which we design or describe hardware using VHDL. We first look at structural description in VHDL. As we have discussed earlier, structural description means that we have to name all the components that we are using in a circuit and give a list of connections from one circuit one sub-circuit to the other. Therefore the language must provide the wherewithal for placing these components of hardware, attaching these components with a particular kind of behavior and a list of wires which will connect pins of this sub-circuit to pins of other sub-circuits. All the devices in the language which cater to this requirement, they are described as structural description languages, structural description commands and those are the ones that we look at at first. So therefore structural description consists of these parts. You have component declarations in which you declare the properties of each component that you would be using. Component instantiation in which you actually place the component at various positions in the circuit. The configuration refers to the choice of binding this component to entities to architectures and so on and very often we use multiple components of the same time and therefore it is convenient to have a repetition grammar. To give you an example, you might have 8 registers in a particular design. The register is declared as a component and described it maps to a particular entity architecture pair. However you do not need just one register, you need 8 and it is painful to go ahead and describe each instantiation of this component type called register and therefore it is convenient if you could using repetition grammar place 8 instances of this type of component. So therefore repetition grammar is an important part of structural description in BHDN. Let us look at the look at some circuit and see how we shall go about describing it structurally. So the structural design describes a design in terms of components and their interconnects. Each component declares its ports and the type and direction of signals that it expects through these ports. This is very similar to the declaration of an entity. So the next part is how can we describe the interconnects between these components? And we take this example, you have 3 components here u1, u2 and u3 and each one has its own declaration of various ports. So for example u1 has p1, p2, p3, p4, p5 and p6, u2 similarly and u3 similarly these might or might not be identical components. Now once we have instantiated these components the rest depends on how do we tell VHDL that p1 of u2 is in fact connected to p5 of u3 and so on. These are done using internal signals. So for each internal interconnect we define an internal signal. When instantiating a component we map its ports to specific internal signals. For example in the circuit above at the time of instantiating u1 we map its pin p2 to signal s2. Notice p2 is connected to this signal s2. So when we instantiate u1 we not only place a kind of component a component type here but we say that p2 of this instance of this component must be connected to the signal called s2. Similarly when instantiating u2 we map its pin p3 to s2. So u3 is a component, u2 is a component and u2 is mapped to a component type and when we instantiate that component type we shall map its pin sp3 here to that same signal s2. Therefore it is known to VHDL that pin p2 of u1 is connected to pin p3 of u2 through the signal s2. Now a purely structural architecture for an entity will consist of first of all component declarations. What this does is it associates a component type not individual instance of a component but a component type with their port list. It is very similar to an entity declarations. You also need signal declarations so that you can then use those signals to connect one component one instance of a component to another component. Component instantiations to place component instances and to port map their ports to signals. The pins can be connected either to internal signals or to the port signals declared by the entity which is now being described. We also need configurations. These configurations will bind component types to entity architecture pairs and these configurations can be in line that is they could be part of the architecture or they could be standalone units outside the entity architecture description. In addition to these basic requirements we require a repetition grammar for convenience. This is for describing multiple instances of the same component type. For example you have let us say 1024 memory cells all of them are identical it would be indeed very inconvenient to have to describe each instance of a memory cell individually and it makes a life much simpler if we could if we could just place all 1024 of them using a repetition grammar. Similarly a very large bus may have buffers associated with each line of the bus and it is convenient if we have a repetition grammar which will describe the placing of all these buffers in one go. So these are the components that we need for describing hardware structurally. And let us look at many of these components of the language as we go along. First is a declaration of a component and these are VHDL 87 and 93 versions of the component declaration. It declares a component type not a specific instance of a component and it is very similar to the entity declaration that we have seen earlier. I shall not drag you through the differences between VHDL 87 and VHDL 93 every time it is here for you to see and it is better to get used to the more consistent style required by VHDL 93. So in the discussions we shall mostly look at the VHDL 93 style of declaration. So then you have the declaration says component that is a keyword what appears in bold letters here is a keyword. So component and this is the name of this component type. So component name is is is also a keyword and then the list of all the generics and the list of all the ports. So remember this list is essentially the same format as a record data structure that we had discussed last time and then end component name. For example we can say component flip-flop is that means this declaration is describing a component of the type flip-flop. Generic t-prop which is the delay length which says what is the propagation delay of this flip-flop. And then a port list saying port clock and D as input and these are of type bit and Q as type output and bit and finally end component flip-flop. This format is identical to an entity declaration but be aware that you are not describing an entity here you are describing a component which will then be bound to an entity architecture. Because of this similarity in fact in VHDL 93 you need not declare a component type separately if you are always going to use the same entity architecture pair for this component and in such cases you can directly instantiate entity architecture pair. This option was not available with VHDL 87. So this is what we have been talking about in VHDL 93 you can do direct instantiation that means an entity architecture pair can be instantiated to specific pieces of hardware without having to go through a component type declaration first. So this is an instance name notice now I am not declaring a type of component I am declaring a specific part of the hardware for example this could be our U1, U2, U3 that we had seen those are specific instances so you have the instance name and then the keyword entity which wants the language that I am not using a component type I am going to instantiate an entity directly. So instance name could be U2 for example and then the keyword entity it will appear entirely like this E N T I T Y and then the name of the entity and within bracket the architecture which you want to instantiate. So this entity architecture pair is then instantiated into a specific instance of hardware here and then you have the generic map and the port map as before. Notice that this port map now will be for this specific instance that means it will bind those pins that you have declared in the entity to specific signals. This form is convenient though it does not have the full flexibility of associating alternate entity architecture pairs with a component because when you instantiate the component you have already bound bind this is this is already bound to an entity architecture pair. VHDL 87 did not allow the direct instantiation and because it permitted only component instantiation this keyword was not there at all it was taken for granted that only components can be instantiated whereas in VHDL 93 you can you have both options if you directly instantiate an entity you will use the keyword entity otherwise you must use the keyword component. So this is the normal instantiation when you have declared a component type and then you have instance name this is the specific instance that you are placing the keyword component then the component type name now and then the generic map and the port map. The association here is with the previously declared component type the type will be bound to an entity architecture pair using an inline configuration statement or a separate configuration construct. In VHDL 87 the keyword component is not required to be used because the only option you had was of instantiating component type. So there in that we used to use instance name and no keyword component directly the name of the component and then the generic map and the port list. Now let us look at configurations and the simplest of these is an inline configuration that means the binding of a component type to an entity architecture pair is made inline with a use clause. So for example we say for all component name that means you are now saying that whenever the component name flip flop is invoked then for all instances of this use the entity with this entity name and with this architecture name. You also have the option of not saying for all you could specify specific instances and bind some instances to one entity architecture pair and other instances to other entity architecture pairs. So this is the additional flexibility you will get if in fact you are using inline configuration or indeed a standalone configuration. So in that case instead of for all you will have an instance name list you might say for example that U1 U2 U4 and then component name and then you say use the entity these two are keywords and must appear verbatim in your description and here comes the name of the entity that you will be using and here is the architecture name. So these lines then constitute a configuration it simply says that when an actual instance is being placed we know eventually which entity architecture will be evoked when its sensitivity has been hit. If we use the keyword others instead of a list of instance name it refers to all component instances of this component name which have not yet figured in a named list. In VHDL the keyword others is used in different contexts involving lists and if some members of the lists have been specified then others refers to the remaining members. If none was specified it is equivalent to saying all. So recall we had said for all here. If we do not give a list and use others then that is equivalent to for all on the other hand we could give say U1 U2 and use some entity for that and then say others that means all other instances of this kind of component will use the entity name architecture name given in the other statement. Now this configuration could be hierarchical remember we are when are we using this we are using it in an architecture of some higher level component that means we have a higher level component which consists of a more detailed description using lower level components in the hierarchy. So therefore these configurations and such statements etc are going inside an architecture which happens to be structural in nature. So in that architecture we could use an inline configuration or indeed use an external configuration by specifying its name. Now this architecture will then specify a component type remember this component type will then be mapped using the configuration to an entity architecture but that architecture itself could be structural therefore we need to bind the components of that lower level architecture also by a configuration and therefore the configuration itself can be hierarchical. For example you could say in the current architecture U1 is a component this U1 is then is some component type which is mapped to entity E1 and architecture A1 but A1 uses some other components and they must then be bound to entity E13 and component and architecture 13. So therefore this binding can percolate down the hierarchies and such configurations are called hierarchical configurations. So this hierarchical association within an architecture you have a component that component is marked to an entity architecture and that architecture has other components and so on. So this hierarchical listing of components can be done once and for all in a single configuration. So here is an example hierarchical configuration can be fairly complex and VHDL contains fairly complex configuration statements. We now introduce a very simplified construct here which is an inline configuration. So for example you say configuration this is the name of that configuration this is actually a standalone configuration in that case. So configuration and this is the name of this particular configuration of this is the entity name is for such and such architecture of this entity. So remember the configuration is a standalone unit it has its own name and then it says that I am describing the configuration of this entity whose name is this and then for such and such architecture of this entity and within that architecture for this component instance name list use this component type name which must use then the entity such and such entity lower level hierarchical entity with such and such architecture. And notice that you have two fars here and both fars must be ended. This can then be followed for some other architecture of the same entity indeed inside this for architecture you could have for these component instance lists map thusly and for other lists map in a different way. So this whole construct forms a hierarchical configuration by itself. Let us illustrate it by an example. So this is in fact an XOR gate and we are constructing this XOR gate using NANDs. The inputs of this whole thing is an entity and this interconnection is in fact the structural architecture for this entity. This structural architecture uses four instances of the same component type which happens to be a NAND. So you have a component type called NAND and there are four separate instances of this component type NAND. So therefore you need to describe the NAND gate first. So in VHDL you describe entities and architectures and these are then compiled into a special library called work. The work library does not have to be specifically declared. So if you invoke some components which you have just now described then you do not have to invoke a library. On the other hand if you invoke components which were described elsewhere maybe by somebody else then you have to declare a library and then invoke the use clause to use those things from a specific library. So in some sense the work library represents the current state of the development of the project for designing something. So let us now build upwards from NAND here. We say entity NAND 2 is notice we are declaring now an entity. This is the elemental level entity of a simple to input NAND. This is our port list we are not using any generics here. So the port in 1, in 2 are inputs and are of type bit whereas P is of output direction and type bit and entity NAND 2 that is all there is to the entity NAND 2. Then we describe an architecture we happen to call this architecture trivial then architecture trivial of NAND 2 is and then we say assign to P the value of not in 1 and in 2. So this describes how P is the NAND of in 1 and in 2 not and and are built in logic functions. Now that we have this entity architecture pair we can use these to build our XOR gate. So now our work library contains this description of the entity NAND and this architecture of entity NAND 2. Entity is called NAND 2 the architecture is called trivial and it is the architecture of NAND 2. Now we want to build this XOR gate that we had specified we say use work dot all that means everything described in work is to be recognized as something to be used and now we declare the entity XOR. So entity XOR is and now we declare the ports of XOR now. So port A B are inputs so A B are inputs and of type bit and port AXB this is the name AXB is the output and is also of type bit and then finally NAND entity XOR with this we have declared the entity called XOR. Now we need an architecture for this and we happen to call this architecture we happen to name it as simple architecture simple of XOR is now remember we have to declare component. So component NAND 2 in is and if you recall components are declared the same way as entities are. So we declare that component NAND 2 in is and this is the port list port A B in bit AXB output for all NAND 2 in use entity NAND 2 with the architecture trivial recall that NAND 2 with architecture trivial was declared earlier in the work library. Now the architecture begins and the architecture is simply a list of instantiation because it is structural with all the signals that we should have declared earlier. So signals S1, S2, S3 which are the internal signals must be declared earlier and that is what we have done here signal S1, S2, S3 bit. Now we begin here and this is A B and then this is instance N1 notice all instances they are all NAND gates but they are separate instances. So N1 is an instance and we tell the language that we are instantiating a component we are not directly instantiating an entity architecture pair. So we use the keyword component and NAND 2 in is the name of the component recall that this component was declared here. So we say that instance N1 is it uses a type called NAND 2 in and it is to be port mapped to A, B and S1 that is to say A and B are port signals and the output is to be mapped to an internal signal called S1. Similarly we can instantiate N2, N2 is this instance of NAND. So N2 will use the component which we have declared earlier in our work library called NAND 2 in and we shall port map it to A which is a port signal and to the signal S2 which was the output of NAND N1 here. So A and S1 are then its inputs and then S2 is a new signal and that is its output. Similarly we instantiate N3, N3 again keyword component name of the component NAND 2 in and then we port map its ports to B which is a port signal of XOR, S1 which is the internal signal which is the output of N1 and then this new signal S3 which is its output. And finally we instantiate N4, N4 is also of the component type NAND 2 in and we port map this instance to inputs being S2 and S3 here S2, S3 these are the outputs of N2 and N3 as you can see here S2 and S3 and its output goes directly to the port AXB of the XOR. So with this now we have described the entity architecture for an XOR. We can now map a component to the entity architecture pair naming the entity as XOR here entity XOR with the architecture simple. So now XOR becomes a component and from now onwards we can use XOR as a component type just like we use NAND 2 as a component. Let us have a look at their repetition grammar. We frequently use a large number of identical components of the same type. We had looked at this example before for example we could be using a large number of memory cells or bus drivers or what have you. Now it is tedious really to instantiate and configure each one of them individually. So recall all this work that we did for N1, N2, N3 and N4 would have to be done for let us say 1024 components of a 1K memory and we can have much larger repetitive components in VLSI. VHDL provides a way to place a collection of instances of a component type at one go using a statement called generate. This that generate is interpreted and handled before the simulation actually begins. So this is in that sense a macro of the language so to speak that means the hierarchy is expanded before the detailed simulation occurs and generate is interpreted as essentially something which relieves you of the repetitive description process. From that point onwards the description will use this expanded form which is internally set up. So let us look at the generate statement. The generate statement contains a for loop which takes effect during the circuit elaboration step. So I had said that before the simulation begins there is an elaboration step and during elaborating the circuit we make use of the generate statement. After elaboration has been done it is as if the generate statement is not there in your description because the effect of this has already been expanded out in a more detailed circuit. This statement can be used to repeat instantiation constructs. Indeed in theory a generate statement can be used to repeat any concurrent statement but in actual use it is much more common to use it to repeat instantiation. Let us illustrate this with an example. Here you have a name which is the name of the entire group not a single instantiation or any these are this is the name of the entire group which is then being instantiate. Since this is a repetitive statement it has syntactic constructs which are very similar to other repetitive statements in programming language and we use a for here. So you say for any index here which could be an integer for index in the range 0 to width minus 1 generate. So this is the generate construct it simply says that what follows here and it happens to be between this begin and end pair has to be repeated for the value of an identifier called index which will span from 0 to width minus 1. This whatever follows here is to be repeated that many times. Then you have the begin and this is the instantiation some name followed by the keyword component this will appear verbatim as component. This is the name of the component say out buff and then port map. So suppose we are placing many buffers on a bus the bus is for example 32 bits wide. So then we are saying for index in 0 to 31 generate begin. This is the name of the group saying buffer group component which has to be placed repeatedly the type of that component is out buff and then you port map in terms of this index. So each instantiation will use different signals and the names of those signals will be derived from this index. Now the defined index in the for construct has local scope that means it has scope only inside this. You may use the same name outside the generate statement and that will not be this index. This index has local scope only inside here and can be used to pick specific signals from an array in the port map statements remember this port map is to be repeated. But the port mapping is different for different instances. So we get around this problem by using an array of interconnect signals and the index in that array comes from this. Here is an example you have a full adder this is an example of structural description you have a full adder it has three inputs a b and carry in and it has two outputs some and carry out. We must as always begin with an entity declaration entity full adder is this is followed by a port list saying port a b and c in as inputs of type bit and some and c out as outputs and also of type bit and entity full adder that is all there is to the entity declaration. Remember an entity is a look at this hardware from the outside and from the outside what we see are a b and c in as inputs and some and c out as outputs of course as is conventional some and c out represent the more significant some is the less significant and c out is the more significant bit of the two bit result of adding a b and c in. Now just assume that this is too difficult for us to figure out in reality you will be using much more complicated circuits but we would we just use this example as if designing a full adder is too difficult for us and that it must be a hierarchically broken down. So we would like to decompose this circuit into blocks which handle only two bits at a time. So let us say that we cannot design a full adder from scratch. We would like to describe it in terms of a simpler circuit called a half adder which adds only two bits at a time. So then we can decompose the full adder into two half adders the first half adder adds a and b and produces two outputs some one and carry one this some one is then combined using a half adder with the carry in. So we add carry in to this sum and the output of this again produces two bits s two is the sum of this half adder and that appears as the sum of the full adder. And the two carries need to be combined to produce a single carry out and it turns out functionally that the or of these two carries is the carry out that means if a and b produce a carry in that case the carry out should be one or even if they do not if the sum of these produces a carry from c in then also the carry out should be one. So therefore functionally the carry out of the full adder is the or of the carries of the two half adders each half adder. So now we have described the full adder in terms of half adder we must go hierarchically down and declare how the half adder is going to work the half adder is easy to design each half adder represents the sum and carry of just two bits carry occurs only if both bits are one and therefore it is the and gate. And the sum is zero if both bits are zero or one and one if the bits are dissimilar so this is an XOR gate. So now we have described the half adder in terms of known gates recall that just some time ago we had described the XOR gate as a combination of NAND gates. So now we are down to NAND gates for describing everything else. Now this is how in VHDL we will describe the full adder entity half adder is this is what we need for the full adder port in one into as inputs of type bit and port S and carry these are outputs of type bit and this entity half adder the architecture trivial of half adder is and you assign to S, A, X or B and assign to carry A and B and this is the trivial architecture. Now architecture simple of full adder is now we declare a component type half adder notice we have an entity half adder but we are going through the full route not instantiating the entity directly declaring a component type which is half adder. So we say component half adder is and this component has port A and B as inputs which are bits and S and carry as outputs which are also bits and this ends the component declaration and now we declare signals S1, CY1 and CY2 notice these are the internal signals of the full adder S1, CY1 and CY2 are the internal signals remember S2 is directly mapped to a port and therefore need not be declared as an internal signal similarly A and B are directly available as ports. So it is carry in. So these do not have to be declared as internal signals. So as a result it is only S1, S2 carry 1 and carry 2 which are internal to this architecture and that is what we are doing we are declaring S1 carry 1 carry 2 as the internal signals S2 will be directly mapped to the port sum and then we place these components there are two instances of the half adder. So HA1 component half adder remember we have declared the component half adder here and port map these ports that had been declared here to A, B, S1, A, B, S1 and carry 1 that is this half adder this half adder inputs are mapped to A and B and the outputs are mapped to S1 and carry 1 then HA2 is instantiated this is also the component half adder but this is port mapped to S1 and carry 1 and the outputs are port mapped to sum and carry 2 recall this is HA1 the inputs are mapped to A and B the outputs are S and S1 and Cy1 and then S1 and carry in bar carry in are the inputs to half adder 2 and sum and carry of this are mapped to sum directly here which is the port signal and Cy2 is then mapped to the input of this OR gate. So that is what we are saying HA1 is component half adder port mapped to A, B as inputs outputs are S1 and carry 1 HA2 is also the same component half adder and it is port mapped to inputs are S1 and carry 1 now and outputs are the sum of the entity and carry 2. Now we need to combine the 2 carry into a single carry and the that instance is called combination we have a previously declared component OR2. So we say component OR2 input and port map the OR gate to carry 1 and carry 2 and the output appears as C out of the full adder and this ends the simple architecture. Now let us look at the half adder the carry from the half adder is an AND gate and the combiner eventually is an OR but gates without inversions are slow AND gates and OR gates are slow. So let us improve this design and bring out carry bar rather than carry using a NAND gate a NAND gate is a natural in CMOS implementation. So then we redefine the half adder to produce sum and carry bar remember the sum is an XOR which can be constructed from NANDs as we had seen earlier. So rather than carry using a NAND gate we declare a carry bar. So now we declare a new half adder whose output is carry bar not carry. So entity half adder is port in 1 in 2 as before inputs bits and sum as before but now C Y bar which is an output of type bit and that ends the entity half adder and the architecture better this is new architecture of half adder is and you begin assign to sum A XOR B and assign to carry bar A NAND B this ends the architecture better of half adder this is hopefully faster because it uses only inverting gates. The combiner should now remember the carry is now negated carry is the bar of the carry C Y bar is output therefore the combiner should be an OR of negative true signals whenever is whenever the carry is true the output of half adder will be false. So therefore the combiner should be the OR of false signals and that is just a NAND. So now you have HA 1 with a better architecture HA 2 with a better architecture both giving carry bars and the combiner now is the OR of negative inputs which is in other words a NAND. So now we have the architecture better of full adder which uses component half adder so we declare a component half adder with these ports with signal S 1 C 1 B C 2 B and we instantiate HA 1 and HA 2 which is component half adder port map and so on and then the combination is a NAND 2 and this ends the architecture better. Then we have the efficient full adder which uses this better half adder and the combination is in fact NAND 2 this is this illustrates essentially how to instantiate components we have not instantiates instantiated generics and that can be shown by having a byte comparator which compares to bytes and each internal components is a bit comparator. So essentially we are making a byte comparator to give you an example of a hardware which uses repetitive hardware components and assume that you have input bit comparators and these bit comparators will then be stacked 8 of them so that we have to use a generic to describe 8 of them and then we have 3 outputs from each bit comparator when you compare the 2 single bits if the result less than equal to or greater than and then we stack these end to end to form a byte comparator notice that the most significant bit is compared closest to the output because if the most significant bit produces a greater than or less than result then the output is independent of the rest of the bits and can appear immediately at the output. So now you have this architecture compose of byte comparator byte comparator is and then we declare a component bit part with these ports and these outputs greater than in equal in and less than in as the inputs because you are concatenating design and greater than out equal out and less than out as output. So each bit comparator has a and b as inputs but it also has concatenating inputs from the previous comparator and it produces 3 outputs which is greater than equal or less than as outputs. So this declares the component and then we say that for all bit part use entity bit compare behavior. So hopefully we have already declared an entity called bit compare which has an architecture behavior and now we declare a signal called connect which will connect all these bit comparator 1 to the other. So essentially these 3 will occur between each repetitive components. So we declare connect as a bi-directional bi-dimensional array. So it is array 1 to 3 because of these 3 signals and 0 to 6 for all these where these 3 group of 3 is to be repeated of STDU logic. STDU logic is a bit type signal which we have not yet done but we could start using it here. This is a type that we have declared remember this is a type. So type connect is an 2 dimensional array and now we say signal cascade is connect that means cascade is a special signal which is a 2 dimensional array of STDU logic which is like type bit. So it is a 2 dimensional array of 3 by 6 3 by 7 actually 0 to 6 of STDU logic and this is the example that we wanted to show. Then we will say for i in 0 to 7 this is going for all the bits generate and then we have a special case if i equal to 0 generate component bit part and when we map it in case of i equal to 0 we map it to the port entries the 0 part maps directly to the entries of the entity and the outputs are a i b i these are the these are the other 2 bit inputs and the outputs are connect 1 i 2 i and 3 i is the bit number which will go from 0 to 7 and generate notice connect is a 2 dimensional array and here 1 2 and 3 are being mapped to the corresponding greater than in equivalent and less than in signals and generate. Also the last part is unique if i equal to 7 then generate and it is very similar except that the inputs are now cascaded but the outputs are the port outputs and the this is the interesting part this is the middle part and if i is greater than 0 and i less than 7 then no port signals are involved and then we say generate and then we say that the component to be used is the bit part and the port mapping is the array at the input and the array at the output only a i and b i are the bit specific signals which will come. So, by using a generate then we have used all the component parts. So, this gives an illustration of how we can use hardware we can describe hardware structurally using components using entity architecture pairs directly and with or without repetition statements we bring this lecture to a close here and then we will wrap up this series on hardware descriptions by describing how behavioral descriptions can be done in VHDL we stop this lecture here.