 In our previous lecture, we have looked at underlying principles of hardware description languages. We have seen that these are similar to programming languages in many ways. However, there are many important ways in which a hardware description language is very different from a programming language. In particular, two of the features which are different for hardware description language are that it treats time in a specific way, it keeps track of the simulation time, the circuit time differently and second it handles concurrency in a different way. So in hardware, many components are active at the same time, they must be accounted for and we have seen through a couple of illustrative examples, how delay is handled and how this concurrency is managed. If you recall, we had the example in which there was this inverter and a NAND gate and at different times, the sensitivities of different components were struck and then they were called upon to resimulate their outputs. Now, one principle which comes out from this then is that unlike programming languages, the place where a particular description is kept is unimportant. This particular description is run not when a turn comes up sequentially as would happen in a programming language, but when its sensitivity is struck and once the sensitivity is struck the data structures that we construct during the elaboration phase will take us to that line wherever it is kept in our description. So therefore, essentially the concurrent part of the description can be anywhere in the description without affecting the final outcome of the simulation. This is a very important difference from programming languages. This however brings forth a different feature which we should examine before we go over to specific programming languages. So let us look at what happens during simulation. If you recall, we had done that example of inverter and NAND. So let us and do not worry too much about the syntax at this level. Let us look at what happened when let us say the sensitivity of the inverter was struck. Somewhere we have a description which is the equivalent of the following. It says I will just redraw the circuit that we had simulated. This was node A, this was B and this was C and the behavior of the inverter and the NAND is described somewhere in our hardware description language. For example, it might be that for the inverter we said recall that the delay here was 8 units and this was 6 units. So we had somewhere the equivalent of assigned to be the value of node A after 8 units of time say nanoseconds. Similarly, somewhere in our description we would have the equivalent of this and again the syntax is not important, assign to C the value of node of A and B after say 6 nanoseconds. Now these descriptions are there somewhere there might be other lines somewhere in this description and we had described this initial waveform where you had the transitions on this was the waveform for A and the transitions were at 20 and 50. So the point is that whenever there was an event on A our programmer will have our simulator will have a pointer to these two lines and we will execute the code wherever this pointer takes us. If on the other hand there is an event on B then we want to execute only this part and not that part. So let us say internally that these two pointers are P1 and P2 then an event on A would have essentially a list which will say execute whatever is being pointed to by P1 as well as whatever is being pointed to by P2. On the other hand if there is an event on B then execute the code which is pointed to by P2. This data structure is built during the elaboration phase. So therefore the simulator goes through the time ordered queue updates the signals and looks for events. For every event there is a list like this and then it goes follows that pointer and executes whatever code that pointer takes you to. This is simple if the hardware being described is very simple. For example the behavior of the inverter is finished in just one line so is the behavior of the NAND but what if each one of these modules was quite complicated and in fact required a longish description. In other words we are looking at a case where we have several modules and let us say that you have P1 pointing to some complicated description and similarly P2 pointing to a much more complicated description. Now when a sensitivity is struck which requires you to execute the code at P1 you know where to begin executing but you do not know where to stop. You do not know where the description of this particular hardware ends. You do know where it starts and that is what P1 tells you but it does not tell you how many lines of code are to be executed. That is to say we do not know how long is the behavioral description of this component therefore you need constructs special constructs which will delimit the extent of code which describes one particular piece of hardware. Very often these might be statements like begin and end. Notice that these keywords might be used in other contexts as well but we do need to delimit an entire block of statements which will be executed when the sensitivity of this whole block occurs. Now we have a somewhat mixed case. These blocks of code are concurrent therefore their order is determined by the sensitivity but once you start executing them then the entire block must be executed and what that means is that within this block it must be executed as if it is a software program that means it is no more concurrent it is in fact sequential. That means these lines are to be treated as an atomic code all of which is to be executed just like software one line after the other and the entire block is to be executed because this is what delimits the behavior of the circuit module whose sensitivity has been struck. Similarly all modules will be delimited by some statements and when the sensitivity of that particular module is struck then the entire code which simulates that component needs to be executed and then now we have the flow of the simulation going in a mixed way. We have as before the time ordered queue we advance the time to the earliest time as we had seen during the interview during the earlier lecture and then we execute the code of all the hardware which is sensitive to the events which have occurred and this code now we realize need not be single line it could be an entire block of code and then that block must be executed as if it is sequential and program like. So now blocks are executed like concurrent and within the block statements are executed as if they are software programs or sequential. This mixture is the essence of the way hardware description languages operate and therefore they need to have syntactical devices which tell us which part of the code is concurrent and which part of the code is sequential eventually the entire description is a collection of concurrent code however each piece of concurrent code can be sequential this is what we are getting it. So let us look at it from a different point of view we have seen that the order of placing concurrent descriptions in a hardware description language is immaterial as we had seen in the example described earlier each concurrent block is handled when its sensitivity is struck wherever it is placed in the overall description. So what defines the limits of a concurrent block if it is a single line there is no problem you just execute that line and you are done with it if the description of the concurrent block needs multiple lines how are these lines to be executed we need to delimit them. So a multiline concurrent block has to be executed completely when its sensitivity is struck therefore the multiline description of a complex concurrent block must be executed sequentially line by line a hardware description language must therefore provide a syntax to distinguish sequential parts from concurrent parts after all a single line of description could be a standalone concurrent description or part of a multiline sequential code. So you do not know whether this single line is complete by itself or is it a part of a multiline sequential code. So we must have syntactical devices which will tell us how this line is to be treated and multiline descriptions of hardware blocks are concurrent outside and sequential inside. Now the describing description of hardware by sequential code raises a problem what happens when the sequential description reaches its end the hardware blocks are perpetual objects these cannot terminate like software routines. Therefore we must have an assumption about the behavior of this software block what happens when you reach the end of this block. So we can make sequential descriptions perpetual by adding the convention that is sequential description loops back to the beginning when it reaches its end in that sense now we have solved the problem this sequential code is the representation of a piece of hardware the piece of hardware is perpetual the software has a termination and we get rid of the termination by making it perpetual by making it loop back to the beginning when it reaches the end. So now this software block is also perpetual however this solution immediately causes yet another problem and endless loop will never terminate then how can we handle the next event the next event is waiting to be handled and the current event is represented by an endless loop. So this loop will go on forever and now we are stuck our time cannot advance and we cannot simulate the rest of the hardware the solution to this is actually easy we loop back to the beginning and halt there that is all that we need to do that means when we reach the end of the description which describes a particular piece of hardware then we do loop back to the beginning but having loop back we stop there and then go over and handle the next event now we have solved the problem. So the convention should therefore be that when a sequential description ends execution will loop back to the beginning and the execution of the loop will be suspended here the suspended loop will restart only when the sensitivity of this block is struck again by the way this describes the somewhat simple case of sensitivities which we have seen later we will have reason to see that there can be dynamic sensitivities that means a piece of software may actually suspend in the middle and wait for some different event to take place to restart from where it stopped that is a special case which will be looking at it later but right now it is enough to see how a piece of sequential code can represent the description of a piece of hardware. So now the hardware is perpetual software is not software terminates and we get rid of this by making the software loop back and stop there. So now the parallel is complete and we can represent hardware by such descriptions. Having done the background work of understanding how we carry out any hardware description we now look at an example of a specific hardware description language and in this respect we shall have a brief look at VHDL as well as Verilog these are the two leading hardware description languages used for VLSI design these days. Hardware description languages ideally are learnt by practice you cannot learn VHDL or Verilog through a course of lectures like this one. Therefore, the endeavour during these lectures is to explain the context the concepts which are important for understanding these languages. We strongly encourage you to actually use hardware description languages and hardware descriptions for simple circuits at first and complicated circuits later and that is the real learning of specific hardware description languages. However, in this series of lectures we have included some discussion on the underlying principles of specific hardware description languages as well. At this point I would like to say that excellent textbooks are available both for VHDL and Verilog. We do not recommend a particular textbook at this time many excellent textbooks are available later when we end this module will give you a list of textbooks that you might find interesting it is by no means exhaustive and new excellent books keep appearing for both VHDL as well as Verilog. I would also like to add at this point that very good public domain implementations of VHDL simulation and Verilog simulation are available. In some of the examples that I take up during this course of lectures I shall be using GHDL for implementation of VHDL and I shall be using Icarus Verilog which is also a public domain program both of these run on Linux but I understand that Windows versions are also becoming available. However, I shall be using only the Linux versions of these generally the most up to date versions are to be found for Linux. It is quite easy to install these if you have a Linux machine available and the specific examples that I take will in fact run on Linux. That done let us now have a look at VHDL. Now, we are going to look first at the design units in VHDL and then look at object and data types and how these are handled in VHDL. Now, VHDL is a hardware description language which uses the syntax of a programming language called ADA. Now, ADA is perhaps not very widely used for software but as I had said earlier all hardware description languages take a page out of software and therefore, they form the base as some programming language and for VHDL that language is ADA. Like any hardware description language VHDL is used for many purposes. It used for describing hardware as a modeling language, for simulation of hardware, for early performance estimation of system architecture, for synthesis of hardware, for fault simulation test and verification of designs etc. These are some of the major uses of any hardware description language and in particular VHDL. The basic design element in VHDL is entity. A piece of hardware is called an entity and entity represents a template for a hardware block. By a template I mean the following. In a hardware description language for example, you might describe the behavior of a flip flop but later you might use several flip flops in a design and during simulation each flip flop is to be used differently. Its inputs are different, its sensitivity list is different, it is connected to different signals. However, the behavioral description for each one of these components is the same. For a type of component we describe the behavior only once and this code will be invoked with specific inputs and specific output transactions whenever the sensitivity of a particular instance of this kind of a component is there. Therefore, we need a template for a kind of hardware and we can describe this hardware once and for all. We are quite aware of the fact that several instances which are independent and which will be simulated independently might exist in a hardware description language. Those will then be called components. However, the entity therefore is a template for a hardware block. It describes just the outside view of a hardware module. It does not say how it works inside. It simply describes its interface with other modules in terms of input and output signals. The hardware block described by an entity could be the entire design, a part of it or indeed an entire test bench which contains the circuit being designed. What is the test bench? It includes a circuit being designed, various blocks which apply test signals to it and those which are connected to its output in order to monitor its behavior. The inner operation of the entity, the external interconnect is described by the entity, but the inner operation of the entity is described by an object called an architecture. Therefore, each entity has one or more architectures associated with it. Therefore, a piece of hardware has a template. You might have many instances of the same kind in a hardware. However, the behavioral description, the structural description of such an object is done using a template. The exterior behavior of this template is described by an entity and the inner working of this kind of hardware is described by an architecture. Later, we instantiate components of this kind whose template is described by this entity architecture and specific instances will be independently simulated when we simulate the entire structure. So, this picture should be clear in your mind. Therefore, the entity architecture pair describes the template for a kind of hardware and not one specific instance of this hardware. The syntax is also important. The declaration of an entity describes the signals which connect the hardware to the outside and that is all. The rest is done by the architecture. These are called port signals. It also provides optional values of manifest constants which are called generics. For example, the delay or whatever, the width of a bus. These are called generics. The description of the architecture might be such that it is general. For example, you might have a buffer and the description could be for an 8-bit buffer or a 16-bit buffer. It does not matter. The description might be the same. It just needs to know how many bits buffer is being described. Such manifest constants are described during the entity apart from the interconnection with the outside world and then they are called generics. So, you have a list of generics and a list of signals which form the ports. Notice that the language has evolved over time. There are several versions of this language. There is VHDL 83, VHDL 87, VHDL 93 and much later versions also. But two versions are dominant. The more modern version which is VHDL 93 is more consistent in its syntax. The earlier version was not quite consistent. Sometimes you used like you can see here entity name is but end name. Whereas, VHDL 93 uses a consistent syntax. Entity something is and then end that object and the name. So, this kind of syntax is universal in VHDL 93. Whereas, its use was somewhat variable in VHDL 87 for entities. This specific keyword entity was not required for architecture and other things it was required. So, such inconsistencies have been removed in a more modern version of VHDL. However, most simulators are capable of handling both the 1987 syntax as well as 93 and more modern versions of syntax. Here is an example of how you describe a particular entity. We are describing a flip-flop. So, you have an entity flip-flop and you have a generic called T-PROP which is the delay of this. Then you have a port list. The ports describes clock and D as two signals which are inputs and R of the type bit and Q as a signal which is the output and is also of the type bit. An end flip-flop that is all the entity is supposed to contain. In the more modern version of VHDL, the first part is essentially the same entity flip-flop is generic and port list and then end entity flip-flop rather than just end flip-flop. However, most languages tend to support both kinds of syntax, but for all your new descriptions, it is better to stick to the more consistent syntax described by the later versions of the language. Now, let us go to the architecture. Now, an architecture describes how an entity operates. An architecture is always associated with an entity. The architecture name itself is not sufficient to determine which piece of hardware is being described. So, while architecture describes the inner working of a piece of hardware, it is always to be considered in association with the entity whose architecture is being described. There can be multiple architectures associated with an entity. For example, I might start describing a microprocessor. As we had discussed earlier, we would like to design it hierarchically. In this hierarchy, I might describe it in terms of various units like the bus interface unit, the instruction decoder, the arithmetic and logical unit, etcetera, etcetera. Each one of these units will then be an entity. However, at this point, I do not know how to implement these units. So, I will describe them behaviorally. So, it will have a behavioral architecture associated with each of the units. Later, as my design progresses, I might come down right down to the logic description of the ALU or what have you. In that case, the same entity will have a new architecture. The old architecture was completely behavioral. The new architecture is structural because I have finished my design and both architectures can exist simultaneously for the same entity. We choose which architecture will be used by a syntactical device called configuration. When we configure the design, then we specify that for this instance of this entity architecture pair, use this entity and this architecture. So, the entity could have multiple architectures and during a simulation, you may actually choose a particular architecture for simulation and which architecture will be used, will be described by a structure called a configuration. What does the architecture do? It describes how the entity actually operates. That means the logic of operation of this entity. Remember, entity architectures are templates for multiple occurrences of possibly multiple occurrences of a device. Now, an architecture can describe an entity in a structural style, in a behavioral style or indeed in a mixed style. That means the architecture could describe this piece of hardware as an interconnection of other components or in a what happens when kind of style or indeed mixed. That means part of it is what happens when kind of logic and the rest is a description of interconnection of various pieces of hardware. The language provides constructs for describing components, their interconnects and composition. These are called structural descriptions. It also includes signal assignments, sequential and concurrent statements for describing data and control flow and for behavioral descriptions. It is the combination of all such statements which forms the architecture of an element. Here is the syntax of an architecture. In the earlier syntax, you would say architecture. This is the name of this particular architecture. Remember, there can be multiple architectures for the same entity and therefore each architecture must have a name. So, architecture, this name, this is the architecture name of this entity name is, this is followed by declarations of internal signals and what have you. Begin followed by end architecture. This block describes the architecture of this particular component and begin and end will contain a list of concurrent statements. Each statement need not be a single line. These are concurrent statements and a concurrent statement could even be a process which is a multi-line description of a concurrent object. The current syntax is, as I said earlier, is consistent. Architecture name of entity name is and then end architecture name. In this particular case, there is not a lot of difference between the two syntaxes. Entity has changed and what the new VHDL 93 has done is to make the syntactical structure of all objects which make up this language consistent. Now, notice that the architecture inherits the port signals from its entities. The port signals are like global signals for the architecture. Those need not be declared. In fact, they are not declared. However, all the internal signals to the architecture must be declared and those are the ones which will come in this declarations component of the architecture. Concurrent statements constituting the architecture can be placed as always in any order. Here is a specific example. Architecture simple. This is the name of the architecture of DFF. DFF is the name of some entity. That is the entity name. So, architecture simple of DFF is, then follow declarations like signal this, that or the other, then begin and then end simple. In case of VHDL 93, you will have architecture simple of DFF is again declaration, signal, etc. begin and then end architecture simple. In the modern syntax, after end, you specify what kind of object is ending and also the name of the particular type. So, end architecture simple where simple was the name of this architecture. Now let us look at specific design elements in VHDL. We have looked at entity architecture. This entity architecture pair actually describes a template as we had seen, a type. In a design, we might use several instances of the same component type. Each instance of a component type must be distinguished by using a unique name. Thus, a component instance with a unique instance name is associated with a component type, which in turn is associated with an entity architecture pair. To give an example of this, it is like saying U1. U1 is a component instance. It is a D flip-flop, which is a component type, which is associated with an entity DFF. The entity DFF will describe its spin diagram or the signals that it is connected to using architecture LS7474. So, the architecture LS7474 describes its inner operation. So, this is a hierarchy of description elements. The entity architecture pair is a template. This is then linked to a component, which associates it with a type. And then specific instances of this component type will be used in an actual hardware description. Here is an example. You declare a component. Notice this is not an instance still. You declare a component by this syntax. Its syntax is very similar to the syntax of an entity. So, you declare generics and a port list for the component. For example, you say, I have a component flip-flop with generic t-prop, which is a delay length, with ports clock D in input of type bit, and Q a signal, which is an output of type bit. Now, this is a component declaration. It is simply telling the simulator that I can have multiple instances of this component. Later, I will associate this component with an entity architecture pair. In VHDL 93, however, this somewhat rigid descendency of hierarchy is relaxed. And in VHDL 93, you might instantiate an entity architecture pair directly. VHDL 87 did not allow an entity architecture pair to be instantiated directly. The entity architecture pair was something abstract. A component then declared a type, and then instances could only instantiate components. The modern version of VHDL has relaxed it a little bit. And in fact, that has diluted somewhat the utility of the components. Because you can, for the sake of convenience, at least for simple designs, instantiate entity architecture pairs directly. Now, which architecture will be used with an entity, and which entity architecture pair will be used for a component? That must be made clear. And for that, we need something called a configuration. Structural descriptions describe component instances actually, component instances and their interconnects. So, a component is an instance of a component type. Each component type is associated with an entity architecture pair. The architecture used can itself contain other components. It could be a structural description. So, you have an architecture which is a structural architecture, and it describes a component in terms of interconnection of other components. For example, you could describe a latch as an interconnection of NAND gates. Now, these NAND gates are also components. And then those must also be associated with entity architecture pairs. So, this connection of a component with an entity architecture pair, which is recursive, because the architecture itself can contain other components, which then are linked with other entity architecture pairs and so on. This connection is described by an object called a configuration, which describes linkages between component types and entity architecture pairs. It specifies bindings for all components used in an architecture associated with an entity. So, now we have looked at various elements which constitute a description in VHDL. We have looked at entity. We have looked at architecture. We have looked at component, which actually describes the component type. We have looked at instances of components. And now we have looked at configuration, which binds a component instance to a component, a component to an entity architecture pair and recursively because the architecture itself might contain other components. So, this is the function of a configuration. Now, let us look at some other things in VHDL, other elements and these are called packages. Related declarations and design elements like sub-programs and procedures can be placed in a package for reuse. A package has a declarative part and an implementation part. So, VHDL is a segmented language. You would have noticed this everywhere. Hardware is described separately as entity and architecture. Similarly, a package has a declarative part, which is the external interface and an implementation part, which is the innards of the implementation. So, this is somewhat like entity and architecture for designs. Objects in a package can be referred to by a package name dot object name kind of syntax. So, now related objects can be placed in a package. A description can include a use clause to incorporate the package in the design. This is somewhat like including a library during compilation of software. Objects in the package then become visible to the description without having to use the dot reference as above. So, when you say use this package, essentially it makes that package visible to the designs and now you can use all the objects which are available in that package. This facilitates reuse of descriptions. Readymade functions, signal types, etc are available as packages and indeed have been standardized for convenient use and therefore, you do not have to reinvent the wheel every time. Many frequently done jobs are already available as packages and you can just simply include those in your hardware descriptions. You can also have libraries. So, for example, many design elements such as packages, definitions and entire entity architecture pairs, they can all be placed in a library. The description invokes the library by first declaring it. For example, you might say library IEEE. All that it does is it wants the software that IEEE is the name of some library. That is all it does. Then objects in the library can then be incorporated in the design by a use clause. For example, you might say use IEEE dot std logic 1164 dot all. What it says is that the library called IEEE has a package called std logic 1164 and everything which is included in that package is to be made visible for my designs. So, we have the use clause for a library dot package dot package component kind of thing. You could have declared just chosen components of a particular package. For example, you might like certain elements of a package but may want to rewrite certain other elements of that package. Then you have the freedom of using the use clause in which you use only selected packages which do not conflict with what you are describing and describe the rest yourself. Once we understand this super structure of objects in VHDL, we should now look at objects and data types. VHDL defines several types of objects. Please be a little patient with this terminology. There are many things that we have introduced today. We have introduced various design units. Now, I am talking of objects. So, there are various kinds of objects which are included in VHDL and these includes for example, constants, variables, signals and files. Now, the types of values which can be assigned to these objects are called data types. Some data types may be assigned to different object types. So, be careful about this classification. These classifications are orthogonal. For example, you have a data type called a bit. Now, an object type constant could be assigned a value of a bit. For example, you might say a constant which we will call true is assigned a value of data type bit whose value is 1. A variable which is not a signal which is only a computational device could also have a data type called a bit and finally, a signal which is actually the kind of object that we have been talking about in our tutorial and so on. So, that signal can also be of a data type bit. So, make a distinction between object types and data types or object types can be constants, variables, signals and files and then there are a few others and one or more of them can use different data types. When you declare an object, you include their object type as well as the data type of values that they can acquire. For example, you would declare signal enable bit, then the object type is signal, the name of this particular object is enable and its data type is bit. So, the declaration involves both these types. We shall stop at this point in this discussion and then continue in our next lecture describing how these object and data types appear in actual descriptions.