 Modern electronic design has become very complex and traditional design styles therefore are inadequate to carry out these complex designs. Most of these designs these days in particular in the digital domain are all done using hardware description languages. In this module we shall look at hardware description languages in general and then we will have a brief discussion on specific hardware description languages. In this lecture we will look at the underlying principles of all hardware description languages. Hardware description languages have evolved over time and the standards have changed however in this course we shall look essentially what is the core of these designs or design styles. You are encouraged to practice designing using these and excellent textbooks and tutorial material is available on these. I shall mention some of these as we go along and when we come to specific hardware description languages. But in today's lecture we want to look at the general underlying principles behind hardware description languages and how they are connected to the modern design process. Let us begin with asking ourselves the basic question what is electronic design? There is no textbook answer to this however since the hardware description languages are so closely linked to the requirements of electronic design we should surely think about this question a little bit. So what is electronic design? To my mind and this is not necessarily an encyclopedic definition. Electronic design is that given specifications we want to develop a circuit by connecting known electronic devices such that the circuit meets the given specifications. The whole design process begins with somebody giving us specifications that I want an electronic circuit which will turn such and such lights on or which will turn this relay on or will display such and such thing when such a thing happens these are all specifications. A designer is then supposed to sit down and think up an electronic circuit which will which is essentially just an interconnection of known electronic devices such that this circuit has the behavior which meets the specifications. To me this is electronic design however this is a somewhat lax definition. What are specifications? We have introduced a new term specifications and we should actually understand what specifications are. Specifications refer to the description of the desired behavior of the circuit obviously there has to be a standardized way in which we specify the desired behavior. There is another term that we have used in this definition that is known devices. What are known devices? Known devices are those whose behavior can be modeled by known equation or algorithms with known values of parameters. Essentially what it means is that if the model and the model parameters of a device are known then this device is known. The model and model parameters could be a device level at sub-circuit level or even at module level. That depends on the level at which we are simulating this. Once we have the model equations then we can put many such known devices together and since we know the behavior of each one of these components and indeed the way that they are interconnected. Given a good enough simulation program we can now predict the behavior of this interconnected circuit and then we can see whether the behavior of this interconnected circuit is the same as the specifications. So therefore if we have a standardized way of giving the specifications and then a program which takes devices whose models are known and can put these together and predict the behavior of the entire interconnected circuit then we will be able to know before making the circuit whether our circuit is likely to meet the specifications or not. So therefore in some way electronic design is really the process of converting a behavioral description. What is the behavioral description? It describes what happens when kind of things to a structural description. What is the structural description? What is connected to what and how? So we begin with specifications which is nothing but a behavioral description. It says that if the door is opened then the light comes on or whatever. So that is a behavioral description what happens when kind of description and the process of electronic design is the conversion of this kind of description to an equivalent description of electronic devices and their connection which is a structural description. In our conversion to structural description we may need to do one more step which is physical design which involves choosing device sizes, placement of blocks, routing of inter-technic lines etc. This part is already done for us if the design is on an FPGA. On the other hand if it is want to design an ASIC or indeed a custom circuit then these parts will have to be explicitly done. However most of the work of design is essentially converting this specification to an interconnection. So what is the problem with this thing? What is the main challenge? The main challenge for modern electronic design is that the circuits being designed these days are extremely complex. It is not so easy to take this huge complex specification and to translate it to a circuit and while IC technology has moved at a rapid pace, capabilities of human brain have remained the same. There is no scaling of the human brain and we cannot handle too many objects at the same time. Therefore, we must break down a complex design into a small number of manageable objects. At this time we do not know how to design these objects. However, we can set down the specification of what each one of these objects will do. Then we see that if we had such objects what would the interconnection of such objects will do? Will it meet the specifications or not? At the end of it if each object is still too complex to handle the above process has to be repeated recursively. That means we take the object and then divide it down into sub modules as we did for the whole circuit and we continued this process till we find that the whole description contains only the known devices. So, in other words initially we design the circuit by breaking down into modules and these need not be known objects. These are some things which are yet to be designed. However, for example, you might take a microprocessor. The microprocessor might be thought of as a combination of registers, ALUs, bus interface unit, instruction decoder or what have you. Right now we do not know how to design the instruction decoder or the register file or the bus interface unit or what have you. However, we can write down that we intend to design an ALU which is the which is which has essentially the capabilities which we desire. The bus interface unit should have such and such behavior and assume that in due course we will have the design of these things done. So, we can pretend that these modules are in fact known devices. Currently they are not, but it is reasonable to assume that they are known devices. We have a behavioral model of these and we can treat these as known devices. Then we complete the circuit design as if these known devices were available. Once the circuit works to our specifications, we are happy with it. Then we look down on these objects and say whether these objects are really known or not if they are not, then we further apply the same process to them till they have been simplified to a level where they consist of transistors, flip-flops or whatever all of which are known devices. Once we have done, then we have reduced the entire circuit to an interconnection of known devices and that is indeed the design procedure. However, the complexity is high and therefore systematic procedures have to be developed to handle this complexity. So, how do we learn how to handle this complexity? And we can take a page out of the software designer's book. After all, very complex software has been written for quite some time. What have they done? Well, we must adopt hierarchical design. We have already seen an example of this. That means you design the circuit in terms of modules. Then design these modules in terms of sub-modules and so on. So, there is a hierarchy of complexity. The architecture must be modular. That means the changes to one particular module should not affect the design of other modules. The descriptions should be text-based rather than pictorial because then we can use standard parsing techniques, programs and so on to handle these descriptions. And we must reuse the existing resources. So, for example, if the design of an ALU is already available, we can just add on other things to design our microprocessor. In fact, if the design of a microprocessor is already available, we can build a much more complex circuit by using one or indeed even more of these microprocessors. So, therefore, we must reuse existing resources. These are the lessons that we have learned from software. In software, the design is hierarchical. Subroutines are written to be modular so that if we change a subroutine, the rest of the program need not change. And the description is text-based and we have libraries. And we do not rewrite libraries every time we write a new program. We use the libraries. So, these are the techniques which have been used by software designers for a long time and even for complex hardware designers, designs we must use these techniques. So, how is the hierarchical design carried out? We have agreed that the design process has to be hierarchical. A complex circuit is then converted to a structural description of blocks which have not yet been designed. We had just discussed this. However, these blocks can be described behaviorally. They have not been designed. That means their structural design is not known. But their behavior, that means their specification has been set down. So, at this stage, the complex circuit is converted to a structural description of blocks which have not yet been designed. But whose behavior can be described? Each of these blocks is then designed as if it was an independent design problem of lower complexity. This process is continued till all blocks are broken down into known devices. It is essential that any departure from proper operation is detected early when the complexity level is low. Therefore, once we go from one level of hierarchy to a next, more detailed hierarchical level, at that time we must make sure that everything works properly at the less complex hierarchy level. And therefore, if we have to design a language which will handle all these tasks, then the hardware description language must be able to simulate a system whose components have been designed to different levels of detail. For example, I have a circuit. I break it down into modules A, B and C. And I say that if the modules A, B and C work as desired, then my circuit will work. Now, I design A to a higher level of detail. And before I proceed any further, I would like to put this more detailed description of A with the less detailed descriptions of B and C, put them all together and see that the whole circuit works properly. Therefore, the hardware description language must be able to simulate a system whose components have been designed to different levels of detail. However, let us not get carried away in emulating software. After all, hardware is different from software. These are the major differences of hardware from software. First of all, hardware components are concurrent. All parts work at the same time, whereas traditional software is sequential. It executes one instruction at a time. Therefore, only one part of a very complex piece of software is active at a given time. In case of hardware, multiple parts are active and interactive. Description of hardware behavior has timing as an integral part. Changes in timing can change the entire behavior of the hardware. If this set input comes first or the reset input comes first, can change the eventual behavior of a flip flop. Therefore, the hardware is time sensitive. The timing of every signal is crucial to the operation of this hardware. On the other hand, traditional software is not real time sensitive. It may run slow, but it will eventually produce the same results. Therefore, the design of complex hardware involves many more basic concepts beyond those of programming languages. All the concepts of programming languages will be used in hardware description languages, but we must now introduce other components of hardware description languages, which take care of these requirements which are peculiar, which are specific to hardware description languages. And two of these are major. One is the timing is integral part of hardware and second that various components of hardware are active at the same time. So, therefore, this parallel operation of different components is something which is peculiar to hardware description. Other than that, hardware description languages are going to look very much like software. Indeed, so much so that sometimes we do not take the pains to understand that a hardware description is inherently different from software and tend to think of it as a software program, which can often lead to very serious problems. Therefore, in this lecture, we are underlining those concepts which are specific to hardware. So, let us look at hardware description languages and see what are the abilities that these must have. Hardware description languages need the ability to describe a circuit of course, but also to simulate the behavior of the circuit at behavioral structural and mixed levels. And finally, to synthesize as far as possible the structural description from behavioral description. So, if we have a hardware description languages, language here, we would like eventually to have these capabilities. That means, we should be able to describe a very complex circuit no mean feat by itself, but having described the very complex circuit, we must be able to simulate it and the simulation should be possible if all parts of this are described structurally, behaviorally or in a mixed way. Also, once the description is in a standardized form, which design tools can understand, then all the mechanical work of converting a behavioral description to structural description should be done by a program to the extent possible and this activity is called synthesis. When hardware is described specifically in a particular way, which permits a synthesizer to convert this behavioral description to structural description, then that kind of design is called synthesizable hardware description. Not all description needs to be synthesizable. However, much of useful hardware design must be synthesizable. However, there is a large part of hardware description languages, which is not synthesizable, which is meant for testing debugging circuits and so on. So, therefore, we must learn both kinds of hardware description language and we must be aware that this part is synthesizable and this is not and for what is the non-synthesizable part to be used. The basic concepts involved in hardware description language are timing, concurrency, because we have seen that the part which is peculiar to hardware is that different components of this are working concurrently and the hardware stimulation process, which itself involves several stages. These stages are analysis, that means you analyze the given description, elaboration, that means you build up the circuit from the components that have been described and finally the simulation. The simulation step itself needs two distinct phases. First is signal update, that means you bring the signals to their current values and because signals have changed, you must find out which components of this very complex circuit need resimulation and resimulate only those. This resimulation will cause changes in signal values and therefore, you will go around this loop updating signals at every time and then resimulating only those components of the circuit, which need resimulation. So, this is how the simulation will proceed, it will proceed in a loop and in phased manner, that means all signals will be updated first, then we will analyze these updated signals to see which signals have changed and if inputs have not changed, the output will not change. Therefore, those parts of the complex circuit description need not be reawoken. However, when the inputs have changed, we must go to those blocks which must be resimulated, resimulate only those blocks and find out as a result of this resimulation which signals will now change. So, this whole cycle continues till the circuits settle down to its final values. We shall actually see a tutorial of this because it is very important to see this for a very simple circuit to see exactly what is going on behind the scenes when you use hardware description languages and what are hardware description languages used for? Well, these are used for description and description of interfaces, description of behavior and description of structure. These are also used for describing test benches which essentially test the circuit to see whether it meets specification or not and these are also used for synthesis, where if we have been careful in our description of the circuit, then rather than we reducing the behavioral description to a structural description, a program can be let loose on this description and a program itself will convert this behavioral description to a structural description. Let us look at the basic components which are different from software in a little more little more detail and timing is one of those. So, let us look at delays and see how delays are actually handled in hardware description languages. How do we describe delays? Well, the actual syntax is not material at this stage when we look at specific description languages, then we will look at the syntax right now the syntax need not bother us. However, we choose some specific syntax here this happens to be VHDL syntax and see how do we describe delays. So, I have an input signal in hardware and I want to describe this delay of 30 microseconds let us say and the output is essentially the signal when it has been delayed by 30 microseconds. We need to examine this very important question that is this description unambiguous. Let us see why I raise this question that indeed that this very simple description could at all be ambiguous. So, let us implement this delay in a circuit and here is a circuit notice that this circuit is not all digital this delay part is in fact analog and these waveforms are somewhat stylized these are not actual waveforms. However, the input is digital and so is the output this is the discriminator it looks at the voltage at level x and if it is below some threshold it outputs a digital 0 if it is above some threshold it outputs a digital 1. Assume and the values of this delay element R and C are so adjusted that we get an overall delay of 30 microseconds. Now, assume that we apply an input to this black box inside the black box is this circuit our black box of delay equal to 30 microsecond has this circuit and we apply to that circuit this waveform. This waveform has a pulse which is much narrower than 30 microseconds and another pulse which is much wider than 30 microseconds. And let us figure out in our minds what is expected to happen when the input is held at 0 then of course, this capacitor is already discharged initially and it remains at 0. So, the input remains at 0 as the input rises to 1 it starts charging this capacitor through this resistor. However, the time constant of this is large and the pulse is relatively narrow as a result the charging process has not proceeded too far when the pulse actually comes down. Because the pulse comes down this point is now connected to ground and therefore, the capacitor starts discharging. So, the capacitor discharges as I said before this diagram is somewhat stylized the actual waveforms will be exponential charge and exponential discharge as you very well know. At this point the wider pulse arrives and the capacitor starts charging again and because the pulse is wide enough this charging will now be complete. When the pulse goes down the capacitor will start discharging and if this level lasts long enough the discharging will be complete. Along this charging and discharging waveform we will pass that discrimination level of this discriminator as long as the voltage is below that discrimination level the output will remain at 0. However, as soon as the voltage exceeds that discrimination level the output will become 1 and it will remain 1 as long as the voltage at the input that node x remains higher than the discrimination level. Once it falls below the discrimination level then the output will come down to 0. As a result we can expect to get a pulse like this at the output notice that the input is fully digital and so is the output this point x is completely internal to that black box. And what has happened well the narrow pulse is vanished, but the wide pulse appears in a delayed form as we wanted. This vanishing of the narrow pulse is somewhat unexpected it is not clear from the description whether this is desired or not. We could have just as well implemented that delay in a different way. So, here is our black box again and somehow we are able to see inside this black box and what do we find inside that black box in order to implement a delay of 30 microseconds. Somebody has an interface here which converts a digital signal to light. This light is coupled to a long optical fiber which introduces a delay of 30 microseconds and there is an output circuit which converts this light back to a digital circuit. What do you think will happen now? This input this narrow pulse will result in a narrow flash of light. This wide pulse will result in a wider flash of light and both these flashes will arrive here 30 microseconds later. These light flashes will then be converted to an electrical signal and we will get an exact replica of the input at the output delayed by the amount of delay which corresponds to the length of this optical fiber presumably adjusted to give us a 30 microseconds delay. So, notice that our black box does not behave the same in the two cases. Both cases were designed to introduce a delay of 30 microseconds. In the first case this narrow pulse vanished. In the second case it did not. Therefore, just saying that you delay by 30 microseconds is not adequate for accurate description of physical systems. There we have learnt that there are two kinds of delay. One kind in which pulses which are much narrower than the delay vanish and the other in which they do not. These kinds of delays are called inertial and transport delays. So, the same amount of delay which was in our example 30 microseconds can result in qualitatively different phenomena. In one case the narrow pulse vanishes in the other it does not. So, therefore, we must define two different kinds of delay. Inertial delay is the RC kind of delay the first circuit that we saw which swallows pulses much narrower than the delay amount. Transport delay is the optical fiber kind of delay which lets all pulses pass through irrespective of their width. In most hardware description languages delays are inertial by default because these are normally caused by RC kind of circuits. However, there are cases for example, specifying an input which are then transport by default. So, if you do not specify the delay at all then the amount is taken to be 0 and the kind is taken to be inertial. However, you do have the option of not only specifying the amount of delay like 30 microseconds here, but also the kind of delay and if you so choose you can specify either inertial or transport kind of delay. If you do not specify the kind it will be taken in most circumstances as inertial and if you do not specify the amount it will be taken as 0. We should now look at the other thing which is specific to hardware description and that is how to handle concurrency. Now, to represent real hardware signal assignments have to be associated with a delay when a value is assigned to a signal the target signal does not acquire the assigned value immediately. The value is acquired after some delay. Therefore, there are two values associated with any signal one is its current value and the other which is potentially different it could be the same it could be different, but which is potentially different is the value that it will acquire in near future. That means, when you assign a new value to a signal it does not acquire this new value immediately. Indeed you put a marker on that signal saying after this much delay this signal should acquire this value this marker is called a transaction. Thus when an assignment is made we imply that the target signal will acquire in future will acquire this value after so much delay of this type. So, the acquisition of a new value is not automatic. However, if you do not specify a delay then as we said that the amount of delay will be taken to be 0. However, we must understand the case of 0 delay a little carefully. When a transaction is placed on a signal the default type of delay is inertial and the default amount of delay is 0. In fact, inside the language this delay is not made 0. In fact, it is implemented as a small delay which is called a delta and then when we report the result we take the limit taking delta equal to 0. So, why do we take this round about way? If the user wants a 0 delay then just let us give him 0 delay. Why do we take this indirect way of actually implementing a delay and eventually making that delay equal to 0 and the reason for this is that scheduling is very important in simulating hardware. It is very important to know what occurred before what and what occurred after what. Therefore, for scheduling purposes we keep track of these delta delays. Something might occur at time t something with a 0 delay will cause a signal change and that signal change will take effect at t plus delta. This change may cause yet another change and that change will occur at t plus 2 delta. The cause and effect will always have a delta time difference. Therefore, if we ever have to resolve which signal is earlier and which is later which is important at times then internally we always know which was the cause and which is the effect which signal arrived a delta time earlier and which signal arrived a delta time later. Finally, when we report back to the user what is happening the user always wanted 0 delay and it is only at this time that we put delta equal to 0 and report the final results as if delta was 0. But internally we keep track of all these deltas and treat as if delta is non-zero. Remember the actual value of delta is unimportant. It is some infinitesimally small time. The only point which matters is at how many deltas did this signal acquire its value so that we can do a time ordering. The time ordering of signals is indeed very important in hardware description languages and as long as events are ordered in time things are fine. If the user does not want to specify a delay so be it we shall order it in time using delta delays. So, this concept is very specific to hardware description languages. You will not see such a concept in any programming language and indeed lack of understanding of hardware description languages very often springs from the lack of understanding of this delta delay concept. Now, let us see how we handle concurrency. Concurrency is handled by following an event driven architecture. So, in a concurrent system many things can happen at the same time. It is not as if one latch is being set many signals might change at the same time. However, since we will be writing a hardware description language which will run on a computer we can efficiently handle only one thing in real time at a given time. Therefore, we need to control the passage of time. In simulation we are doing various things one after the other, but we want it to appear as if all the things appeared at the same time. Therefore, we need to control the passage of time and we manage it by treating the time as a global variable. Things which happen simultaneously are in reality handled one after the other, but we keep the value of this global variable time the same. Then the time value is incremented explicitly after all the events which occur at the current time have been handled. So, in other words the actual time as it passes when the program is running has no value whatsoever as far as the simulation time is concerned. The simulation time is changed discreetly it is brought to a level then in whatever time that it takes in real life we handle all the events which are said to have occurred at this time and then we increment the time value inside the variable time is incremented to the next time value. Therefore, as far as the results of simulation are concerned it appears that all the previous events before incrementing the value of the time occurred at the same value of time. Obviously, the value of the time variable represents the time during the operation of the concurrent system and has nothing to do with the actual time taken by a computer to simulate the system. You may have a slow computer you may have a fast computer and the actual amount of time taken to simulate may be different we are not talking of that time we are talking of the time which is being simulated for the behavior of the circuit and that is handled in this special way. So, let us see how hardware simulation then proceeds we have given a description in a text form conforming to a particular syntax described by some hardware language. So, the first step is when we want to run that simulation the syntax of this hardware description is checked and interpreted only if the syntax is correct and makes sense to the language that will proceed to the next step. The next step is called elaboration this is a preparatory step which sets up a hierarchically described system for simulation. So, there are many things which are done at this level even though the description follows a hierarchy we flatten the hierarchy because eventually the circuit is the same the circuit does not know that it was designed following this hierarchy the circuit is the final circuit. So, we flatten the hierarchy for structural descriptions components are expanded till the circuit is reduced to an interconnection of single simple components which are described behavior and then we set up data structures which describe sensitivity lists of all elemental components. So, we know which component receives which signals as the input and this sensitivity list says that if this signal changes then resimulate this component remember the circuit is very complex and we cannot afford to simulate all components at all the time which we resimulate only those components whose inputs have changed or in other words if there is a change in a signal to which this particular component is sensitive and only after analysis and elaboration the simulation is actually carried out the simulated simulation itself is a two step process as I had described earlier. So, what does analysis do it checks for syntax and semantics syntax is the grammar of the language semantics is the meaning of the model you analyze each design unit separately you place analyzed units in a working library and generally in an implementation dependent internal form to enhance the efficiency remember your description was a text description and it need not be kept in this form. Then you go to elaboration this step builds up a detailed circuit from a hierarchical description you flatten the design hierarchy you create ports which are interfaces with other blocks create signals and processes for each instantiated component you copy the component template to this particular instance remember you may not have just one flip flop you describe a flip flop for once. And now you may place say 20 flip flops in your circuit each instance is different the description occurs only once, but the actual copying has to be done at the elaboration level you are elaborating the entire circuit. So, you take the template as the description and make copies of this template for each instance of the flip flop and you repeat this recursively till we are left only with behaviorally described atomic modules whatever these can these may be. For example, basic gates might be our atomic modules anything which occurs in a library might be our atomic module or indeed single transistors might be our atomic module. The end result of elaboration is a flat hierarchy free collection of signal nets connected to behaviorally described modules through defined ports these defined ports describe which way the signal is flowing is it an input to a module or an output to a module. So, this is what elaboration will do and finally, we go to event driven simulation we maintain a time ordered queue of signals which are waiting to acquire their assigned values. If you recall our discussion our discussion on delta times now you realize how important that is because for the user many events might have occurred at the same time, but for the hardware description language their time ordering is very important and therefore, we maintain a time ordered queue of signals which are waiting to acquire their assigned values. Now, we go to the earliest entry in this queue and the time variable is given a value which is equal to the earliest entry in this time ordered queue. All signals which are waiting for acquiring their values at this time are then updated to their values this is when they acquire the desired value. So, therefore, all these updates or transactions were kept in this time ordered queue and then we take up one time instant at a time look up all the transactions which were placed for this time and these transactions now fractify that means this signals actually acquire the value which they were assigned perhaps at an earlier time. After updating these values we notice which values have changed and if this updating results in a change in the value of a signal then we say that an event has occurred on this signal. This is very important because only if a signal has changed that we want to resimulate a part of the circuit. We maintain as I had said earlier a sensitivity list during the elaboration phase we determine which pieces of hardware are affected by or are sensitive to which event and this is called a sensitivity list. The data structure is optimized for reverse look up while describing we describe hardware and then the hardware is sensitive to certain inputs. But we keep the data in the opposite way that means if we know that an event has occurred we can go back and look up all the pieces of hardware which were sensitive to this event. So, that means given an event one can quickly get a list of all hardware which is sensitive to this event. Notice that hardware could be sensitive to a particular kind of change. For example, you could have a flip-flop which is sensitive to a rising edge of the clock and not a falling edge. So, therefore, if the event is for a 1 to 0 transition the hardware does not bother about it. But on the other hand if the change is from 0 to 1 then this hardware would like to reassign new values to its output. So, in short we have a sensitivity list the sensitivity is to particular events and then whenever an event occurs we have an efficient data structure which then goes around looking for all pieces of hardware which are sensitive to this event which has currently occurred. When this event has occurred then all pieces of hardware which are sensitive to this event are resimulated. The resimulation will then result in further transactions. So, the simulation cycle consists of the following. The time variable is advanced to the earliest time entry in the time ordered queue of transactions. Then we entered the update phase in which all signals which were to acquire their values at the current time and then so we update their values and then delete them from the queue because after all we have updated their values. Then we enter the event handling phase. So, remember all updates are done before you enter the event handling phase. When all the updating is completed then we have a list of various events which have occurred and it is only when we have prepared this list that we enter the event handling phase. And now if the value of a signal changes due to the above update it is said to have had an event and all events which resulted at the current time are handled by a scheduler. This scheduler will handle all the events in a particular way. For this lecture we shall stop at this particular point and we shall resume in the next lecture and see an actual example of a very simple circuit how it goes through the process that I have described somewhat abstractly here. It is only when we look at an actual circuit undergoing those actions that it will become quite clear to you how the transactions are handled in a time dependent way, how the time ordered queue is maintained, how events occur due to updating of signals and how are these events eventually handled. So, we shall do that in the next lecture. We stop here at this point in this one.