 So, welcome to this lecture on VHDL in the course digital system design with PLDs and FPGAs. In the last lecture we have seen various packages and various operators and how to use them and so on. Then we have started with the delay modeling available, the constructs available in VHDL. We will complete that delay modeling today, also we will see some examples you know that we have discussed quite a lot of things and we will try to integrate to some kind of data path, sequential circuit, this whatever we have learned we will apply, we will take simple example so that it is not that we are going to do big things but the examples to illustrate what we have studied so that the basics are clear then you can do big things where the complex things are nothing but many simple thing integrated put together. So there is nothing very serious about it, so we will see simple things which illustrate the basics in the class so that we have limitation you know of the slides suppose if I show you huge code with which runs into some kind of 10 slides you will not be able to keep track of it maybe when it comes to some case study I will still show the whole kind of VHDL code for reasonably complex designs but for the time being we will stick to simpler example which illustrates the concept okay. So let us run through the previous days lecture that is the packages then delay modeling and then we will complete the delay modeling today and see the examples. So let us run through the slides so we have looked at the packages and this is the primary standard logic definitions were involved in defined in this particular package. So you have standard u logic, standard logic, standard logic vector which is an unconstrained array, standard u logic take all these values, standard logic is a resolved standard u logic that it resolves the multiple drives, standard logic vector, standard u logic vectors are unconstrained array and what extra defined in this mainly are the logical operators in standard logic 1164 does not contain any arithmetic or relational operators. So if you use only standard logic 1164 package you will not be able to do much you have to do very basic things or you have to build everything of your own but the moment you start using other packages many other things will be available. So we have the next in line is a standard logic unsigned package that uses standard logic and standard logic vector, you have all arithmetic operators, relational operators, shift right, shift left and a function to convert to integer okay. So what because what extra defined other than the standard library is only the standard logic and standard logic vector. So what required normally is a conversion function from standard logic vector to integer that is what this does you know you can convert given a standard logic vector you can give on give this as argument to this function and will return the integer which is very useful as I mentioned maybe to refer to some indexes of memory array and things like that. Next the package which is not IEEE kind of defined package which is a synopsis package with IEEE library. Now instead of standard logic vector it uses array of standard logic as unsigned and signed and you have also signed would mean it supports 2's complement for negative numbers and you have arithmetic operators, relational operators you have exactly like standard logic unsigned as in the previous case you have SHR and SHL here. But this works as far as shift is concerned if it is unsigned data type then it will be a logical shift if it is signed then it is an arithmetic shift. So it takes care of the basically the sign extension. So if you have a 2's complement number if you write shift the sign number is shifted along I mean the sign bit is shifted along. So that the value is correct for that width that is the basic idea in signed arithmetic otherwise basically it is something to do with the right shift not the left shift okay. Then the next package is no there is the conversion function in the standard logic package is this one convert integer convert unsigned convert signed or convert to standard logic vector. So this converts like if you take con underscore integer it converts to integer all other 3. Similarly if you take convert standard logic vector then it converts all the other 3 to this things like that and the usage is this has to be in this order standard logic 1164, standard logic arith and standard logic unsigned. So there are some recommendations use basically arith for numeric operation that is why it is put at the top of the unsigned and for counters and test bench you do not use this arith you put just use unsigned and do not use a package standard logic signed at all. So you have an alternative IEEE numeric standard instead of using as standard logic unsigned and standard logic arith you can use this that also contains a similar definition unsigned and signed are the arrays of standard logic. Then you have arithmetic relational logic operators you have shift left, shift right, rotate left, rotate right and you have the conversion function and this is the usage you know you have the standard logic 1164 package then you specify the numeric standard. And when it comes to the type conversion between the base type and the sub type it is you do not have to do anything. But if it is between say standard logic vector and integer you use functions in the appropriate package like to integer, convert integer and so on. But thing to remember is that suppose you want to kind of do type conversion between signed and standard logic vector or unsigned and standard logic vector both being defined as arrays of the standard logic you can do a type casting as in C that means suppose you have an unsigned vector you want to convert it into a standard logic vector you just say standard logic vector open bracket and you write the unsigned vector and the closed bracket then it is converted to standard logic vector. Similarly about the others and if you have a numerical value you can cast it to any of them by giving it using this kind of syntax. So that is about type conversion now mind you the type conversion is a requirement of the VHDL basically to guarantee that the interface is proper like you have an 8 bit data bus it is connected to only an 8 bit data bus not like you define something in integer something in standard logic vector then if you connect it together and 1 is 8 bit and another is 16 bit there is an issue. Similarly there is an issue with the most significant bit and least significant bit all that is kind of guaranteed by this and the code we write for conversion should not be synthesized. So that is indicated in the library that synthesis should be off during that conversion and but I said when you convert and index many a times it can imply a decoder kind of thing. So that is more to do with synthesis but then it is better to understand these things so that you have clarity with which you can solve lot of problem at least you do not get a false alarm and this is how the arithmetic is done normally if you have a, b, s as 8 bit say s7 is a 7 bit number s9 is a 9 bit number. So when you do simple addition like a, a plus b the result is also 8 bit you do not get a carry. Suppose you want a 9 bit along with the carry which is a requirement when you do any kind of say shift and add in multiplication you need the carry bit carry out. So in that case what you do is that you append convert this a and b to 9 bit and the only way to do is that append 0 at the MSB. So 0 and a plus 0 and b then these are 9 bit and you know that automatically the carry will come in the most significant bit and that is assigned to s9. Suppose you want only you have an 8, 2, 8 bit numbers you want only 7 bit result then you can take the 7 bit of a and 7 bit of b add it together. So a6 down to 0 plus b6 down to 0 is assigned to s7 and some case you want a carry input which is required say you are forming a 2s complement number. So you have to invert some number and add 1 to it you know then to get a 2s complement number for kind of signed arithmetic then that can be achieved like this you have a and b are 8 bit and result is 9 bit and what we do is that we append the least significant bit of a with 1 and then c in is the least significant bit of b then this being 1 if the carry in is 0 no issue nothing will be propagated to the next one but if carry in is 1 this the result at the least significant bit is 0 but there is a carry into the next place. So we have to ignore that last bit because that was you know added to get the carry into the chain. So we ultimately cast I mean or assign s98 down to 1 to the result ignoring the 0th part because 0th part is just we have kind of manipulated to get the carry into the number okay that is how the arithmetic is used. And when you want to do arithmetic with time because the time is a physical unit which uses a integers okay. So if you want a period to be multiplied for whatever reason then what you do is that you take the time data divide by 1 nanosecond then you get the number without unit cast it to real then you get the period then. You can recast it back to the time at the end of it or many times this number is enough to keep on the computation. So that shows how to convert a time to real number to do some computation. Then this was what we started last lecture we have in VHDL two types of delay inertial and transport delay. Inertial delay is what a delay through the capacitive network. So if you have a on a bus a capacitor and you apply a pulse it takes some time to build up and so there is a delay okay. Or if you have a gate with a threshold value you apply a pulse for the input to charge above the threshold it takes a time and also propagate through the device. So unless the input value exceed the threshold the output won't come. So there is a minimum pulse width which is required for this any gate to respond okay. So this inertial delay captures that minimum pulse width also the propagation delay both should be there and the syntax is suppose we say x gets a after phi nanosecond it means that if a will appear at the x with the delay of phi nanosecond. But here it is assumed that you require a minimum pulse width of phi nanosecond for the output to come. So anything below phi nanosecond is it makes no I mean it doesn't appear at the output okay. So another way of writing that is x gets inertial a after phi nanosecond inertial being the default even if you don't say it same as inertial. But if here the assumption is that the propagation delay and the pulse width are same. But if you have a different pulse width and at the gate level as I said it is difficult to model that you have to look at the transistor level implementation do the spy simulation and get those parameters. But having if you know that parameters this is an accurate depiction of the reality okay. So y gets reject 3 nanosecond inertial a after phi nanosecond which say that anything less than 3 nanosecond should be rejected in output doesn't come. But if it is greater than 3 nanosecond greater than or equal to 3 nanosecond a will appear at the y after a delay of phi nanosecond. And we also said that you could write a continuous assignment like this you gets 1 after phi nanosecond 0 after 8 nanosecond 1 after 12 nanosecond. It means that from 0 to 5 it is 1, 5 to 8 it is 0, 8 to 12 it is 1. So you have a pulse width of 5 nanosecond at the beginning then 0 width of 3 nanosecond again 1 bit high for 4 nanosecond. So this is very useful in creating waveforms when you do delay modelling especially it is useful in applying some input waveform in the test bench. Because in a test bench we give input to the various input of the entity and check the output okay. So this is quite a useful syntax and transport delay is a delay which is modelled the delay through transmission line. So suppose you have a long transmission line even if you give a narrow pulse it travels all the way to the end but it does not reject any pulse width. So that is done through this model this index which say z gets transport a after 5 nanosecond okay. So which just you know z is an exact replica of a with a delay of 5 nanosecond that is the meaning of it. That is what we want in a transmission line case and more than I mean do not think that we are going to probably model the transmission line. Yes it can be like in an IC you have a wire delay and the wire delay can be kind of model this but there are some kind of some time some limitation with this when you do the timing model with these syntax. So the transport can be used in such places. So let us see an example the behaviour you know the behaviour of this inertial delay and transport delay. So this is a code I have written for simulating that and you can write this code in any tool and try to simulate you will get the result. I have not done a demo of a tool but we will do it in the coming lectures. And first thing to note is that we are only doing a simulation and not a synthesis because it is just purely simulation this cannot be synthesized because this talks about time delays and all that. So there is no entity so entity is empty we are not defining any port we could define only signals I mean we can define signal that is good enough ok. So entity is kept we give some name it is kept empty the architecture we give some name and of this entity is and before the begin we declare all the signals we are going to use. So we have an air signal to which we assign some values and make a waveform and to x, y, z we apply this syntax of inertial delay and the transport delay. So here you look a gets 1 after 5 nanosecond, 0 after 11 nanosecond, 1 after 18 nanosecond and 0 after 22 nanosecond and so on. So to start with you get 5 nanosecond, 1 pulse, 6 nanosecond, 0 pulse, 7 nanosecond, 1 pulse and so on ok. And when it comes here you see here the 28 30 is a small 2 nanosecond small pulse then 30 to 32 is also only a 2 nanosecond pulse and so on ok. Now x is we have written a after 5 nanosecond it means that x is a delayed version of a by 5 nanosecond but it rejects all the pulses below 5 nanosecond. When it comes to y it is again like x it is a delayed version of a by 5 nanosecond but anything less than 3 is rejected not 5 now ok and z is transport a after 5 nanosecond and that is a delayed version of a by 5 nanosecond no rejection. So if you simulate this you will get a waveform something like this. So this is the original waveform we have created so 5, 6, 7, 4, 6 and 2, 2, 6, 2 and it remains ok. Now if you look at the a, a is a delayed version of 5 nanosecond so we have 5, 10, 15 time is shown here. So x is delayed by 5 nanosecond but you see because a minimum pulse width requirement is 5 nanosecond everything below 5 is rejected. This 4 goes this 2 goes and this 2 goes and you get like this 6 pulse width and this 6 combine because this goes it gets merged with that and you get that ok. And the next one rejects below 3 nanosecond so you can see it is exactly like a, x, y is exactly like x but now the 4 appears earlier the 4 was rejected because of this 5 nanosecond. So the 4 appears and the last one is a transport delay. So z is an exact replica of a with a delay of 5 nanosecond. So that is how the various delay models and when it comes to simulation I will show some kind of peculiarities what happens because of certain syntax. One time it may give if you use this for simulating some what to say not so real life effect you should understand that we will see that when it comes to some demonstration with the tool. Next thing we are going to try is that we write a kind of timing check a VHDL code to check the timing of a flip flop ok. Once again this is used only while simulation it cannot be used for synthesis. So you know that in a flip flop you have a clock coming and the data for proper transmission of data to the output data has to arrive at the input some time called setup time TS before the clock edge and also it should remain there the data should remain there some time after the clock edge it should be stable during this window and this time after the clock edge is called hold time that means you hold the value at the input and the time before the clock edge is called setup time that means you setup the data before some time. Now we want to write and if that happens the Q appears at the output with the delay of TCO ok. Now in our code we are going to incorporate to check this timing violation that means we have to check when the clock comes the setup time was correct or not. That means the data was setup some time before whatever the setup time before the clock and when the data changes we want to make sure that the data is changed after the whole time ok. So the trick is basically we will whenever there is an event like a positive edge on the clock not the negative edge what we will do is that we will check the difference between this time and the last event on D if that is greater than setup time no issue otherwise you just flag a message saying that setup time is violated. Similarly whenever there is a data change and of course we will update that time as the clock time last event on the clock. And whenever there is an event on the data we will check that that time minus the previous event on the clock time is greater than the whole time. If it is violated we print a message saying that it is violated and we also update this time as the last event on the clock because whenever there is an event on the clock we have to make sure that the difference between that and the last event on the data has to be greater than setup time. So we will keep two variables one is to keep the last event on D one is to keep the last event on the clock. Anytime an event happens we subtract the last event on the opposite check greater than that time that is a game okay. So we will look at the code. So this is a code which can be used in principle for simulating the behavior as well as for time check. So the library package clause entity is dn clock or input Q is output. Now in the architecture declaration region we need to specify this setup and whole time. So we are specifying for EC instead of hard coding it we could have said that this time minus that time is greater than 3 nanosecond. But to make it easily modifiable easily configurable we are defining a constant. So constant setup time some name is type time equal to 3 nanosecond. So we have kind of define that constant as 3 nanosecond. Constant whole time is type time equal to 1 nanosecond. So then we begin and now you know that we write a process wherein we write the behavioral code for D flip flop and we also check what happens if there is an event on D and if there is a positive edge on the clock. Now if you write only the behavioral code you need only the clock in the sensitivity list since we are checking the event on D we are including the D in the sensitivity list otherwise you will not be like this process will not be computed whenever there is an event on the D. So we define two variables D, L event and clock L event of the type time to kind of remember the time and the simulation time when whenever there was an event on the D and event on the clock. And then begin this is a process begin earlier was architecture begin. Now we write the behavioral code for flip flop if clock tick event and clock is equal to 1 then Q gets D after 10 nanosecond and if as I said when you write any code please include reset to make the code short because I have less screen space I am avoiding it. So that is the behavioral code and we are not like in this code we are not checking that whether there is any violation or at the input like actually if the input is violated then we cannot say Q gets D after 10 nanosecond. But our interest is in doing that checking the setup and whole time violation than reflecting that at the output okay. Anyway the message will be printed so we know that the output is not going to come. So let us check the whole time violation. So that is a if D tick event then okay now we are using a new syntax which say assert for a moment you forget about this now assert now is the simulation time the current simulation time okay. Now means the current simulation time minus clock last event. So that means that we are here there is an event on the D and we have subtracted or here it does not matter anywhere we subtracted the last event on the clock which was stored and we have to check it is greater than whole time that is what it does now minus clock last event is greater than or equal to whole time. So the syntax of assert is like this you say assert some condition which is we are expecting it to be true we want it to be true. So and report some message severity some level. So the game is that if the condition is met it keeps quiet okay it does not do anything but if the condition is violated it will report that message on the screen and depending on the severity say if it is there are 4 levels of severity it is called note warning error and failure. If it is note and warning it will just print a message if it is error and failure it stops the simulation okay. So that is what we are going to use here which say assert is now minus clock last event greater than whole time that means if it is true if there is no violation do not do anything. If there is a violation report whole time violation severity note that means it will just print on the screen on the console of the simulator and we have to now update the this variable so D last event is now okay that is what we do similarly we checked for the positive clock edge whenever clock tick event and clock is equal to 1 assert now that is the event on the clock minus D last event. So we are here so if there is an event on the clock minus the last event on the D is greater than or equal to setup time. So just if it is violated then report setup time violation severity note then we have to update this variable so clock last event is updated with the current time and if end process end time check so it is done. So if you give this code and if you give a simulate assigning some clock to the clock input assign some input to D then if it is violated that will flag the violation or if this is interconnected to some other logic or registers and together you simulate then this again shows the timing violation you can catch the timing violation by message then you know on the otherwise you have to go through the waveform and something is wrong then you have to catch it. So this is one way of doing it one useful way of doing it so it illustrates this delay modeling or timing violation check just an example. So I think that is where we kind of a brief look at the delay modeling as I said there are two delay models one is inertial delay which is used for the gates which has two parameters minimum pulse width for the output to come a propagation delay in the simplest case the propagation delay and the minimum pulse width is assumed to be same which is somewhat kind of near the kind of real life but it need not be kind of exactly same and you can specify a different pulse width then you have a transport delay which is which kind of model the wires of the transmission line the delay through that because it does not reject it appears at the other end of the transmission line and we have seen a waveform to kind of study this effect by writing a code then we have seen a timing violation check on the setup and hold time of a flip flop we have learned a new syntax called assert. So that is what we have done as I said as we go along and we do a tool demo then I will illustrate some kind of peculiarities of this construct. So let us now since I think I would like to soon go back to the digital design to complete a little more there then we can probably come to this VHDL back again for a short stint and then we can go to the PLDs and so on. So let us take some example so we have seen the example code for a demultiplexer. So I am not even showing the entity definition but if you remember if you refer to the last lecture this is a 1 to 4 demultiplexer. So here the y is the input which is 4 bit a, b, c, d are the output that means it is a 1 which is demultiplex to 4 output okay y is input a, b, c, d are the output s is the select line. So since there are 4 outputs 1 to 4 the select line is 2 bit okay. So we have seen this code the code is that since select line and y are the inputs we write in the sensitivity list and process sy begin and the ideal the best syntax for it is case because there is no priority and it for all the select line values we get the various outputs. So that is what case s is when 0, 0 a gets y all others get 0, 0, 1 b gets y you know all others get 0, when 1, 0 c gets y and others get 0, when 1, 1 d gets y all others get 0 and when others everything gets 0 but this is more of a kind of completion of the syntax that you know but not matters to kind of the synthesis. So that is a code now let us look at all possible ways of writing it even we will write if using it if though the case is the ideal syntax just to get a practice. So let us look at it the first let us write the simplest level the Boolean equation. So you know that select line 1 is 0, select line 0 is 0 because you have s1 and s0 in select line then a gets y. So the equation is a of i because there are 4 bits a0, a1, a2, a3 or a3, a2, a1, a0, y3, y2, y1, y0, a of 0 is nothing but y of 0 and s1 bar and a0 bar okay. Similarly for other things when it comes to b of 0 it is y of 0 and s1 bar and s0 so on okay. So we write the equation so this shows the library the entity where y is input which is 4 bit vector 3 down to 0, s is select line which is 2 bit vector, a, b, c, d are the output which are all 4 bits. So it is a 1 to 4 d multiplexer with 2 select line architecture begin and symbol we write a0 is nothing but y of 0 and not of s1 and not of s0. Similarly a1, a2, a3, b of 0 is y of 0 and not of s1 and s0 all others are similar except for you know these index changes c of 0 is nothing but y of 0 and s1 and not of s0 because this is a 1, 0 and when it comes to d of 0 it is y0 and s1 and s0 okay. Now this clearly shows if you write you can write equation but there is no point in repeating that this index is very neat a0, y0, a1, y1, a2, y2, a3, y3 and this remains the same. So we can write a generate loop for this, this, this and the next one okay. So that is what in the architecture now onwards I am not going to write the entity and library and all that. So you could write a generate loop which is say a label glp for i in 0 to 3 generate and n generate in that we say a of i is y of i and not of s1 and not of s0, b of i is yi and not of s1 and s0, c of i is yi and s1 and not of s0, d of i is y of i and s1 and s of 0. So this is simple enough I mean you can write an equation and if you are comfortable with it though there is nothing wrong with the earlier one you know that that is nothing but truth table and we have seen how the equation of the case is and that is exactly similar to this. So there is no absolutely no difference between this equation and the case statement. So that is another way of writing it is mainly kind of playing with the syntax so that you are thorough and so let us try with the concurrent statement the same thing. Now you know that when we use concurrent statement like with select and when else unlike case and if you can only specify one output ok you can say a but you cannot say a and b together ok. So the one main problem with the concurrent statement is that you have to write a code for a another code for b another assignment for c and d ok. So let us use the with select so here we say with s select a gets y when 0 0 that means when s is 0 0 in all other cases it is 0 a is 0 when others ok. So that is the code for a similarly for b after right with s select b gets y when 0 1 0 0 when others with s select c gets y when 1 0 0 0 0 when others and with s select d gets y when 1 1 0 0 when others. There is absolutely nothing wrong with this coding because you know that though we say 1 to 4 d marks if you look inside the circuit for a circuit for b circuit for c circuit for d can be separated only thing is that a b c d all are the functions Boolean functions of y and s ok. So it is natural like you know that a b c d all are the functions of the same a b c d it is very natural it is very good that if you put it together in a case statement or if statement it is very easy to understand then write it separately ok. It depends on synthesis tool as far as the circuit is concerned there is no issue that it should kind of you should get the same effect but definitely there is an issue that synthesis tool should understand that this together it is a function ok. So maybe a naive very simplistic kind of synthesis tool will give you the correct result correct circuit but it may not infer that it is a 1 to 4 marks that could pose some problem when you it will be good if synthesis tool knows that is a 1 to 4 marks because when ultimately you try to implement that in an FPGA using primitives you can map it to the correct primitive if you do not know that it is a kind of multiplexer or demultiplexer to kind of to place it to the correct primitive to map it to the correct primitive it could be a problem. But otherwise there is no issue with it I have in kind of looked at it whether synthesis tool you know infer that it is a MUX I am sure it more synthesis tool will do that but you can check it. Like let us see the when else exactly like with select you have to write the 4 concurrent statement for when else so it is a a gets y when s is 0 0 else you know 0 ok b gets y when s is 0 1 l 0 similarly c and d exactly same effect though a b c d y are functions of same y same as we write it separate. But you know that is one kind of issue with this kind of coding so I would suggest that you stick with for my opinion this is the best code of course we can have a concise version we will see that and you could use yeah this is the concise version so we initialize a b c d to all 0 at the beginning. And you say case s is when 0 0 a gets y rest all is 0 here since whenever there is an event on s of y the process goes from top to bottom say here a was assigned to 0 at the beginning for say the event happens at 100 nanosecond a was assigned at 100 plus delta. But when it comes here a is reassigned with y so that is replaced with the y so there is no issue this is a very nice code you know when 0 0 a gets y when 0 get 1 b gets y when 1 0 c and so on. And here you can instead of when 1 1 you get say d gets y I have said when others you know it is null but you could combine others along with this it is better to be precise with coding than take liberty so in my opinion you can write others here that is a better coding than writing like this. So this is perfect but then you can write if also because instead of case if you write if though it kind of as a kind of priority. But since these are mutually exclusive and if you specify all the condition in if it will kind of it is redundant like you say when 0 0 like you say if 0 0 else if 0 1 but else if 0 1 is not of 0 0 but not of 0 0 will kind of when you make the truth table and kind of you know optimise it everything comes back to the same thing. So you could write with an if there is no issue there because the priority will be thrown out because all the conditions are specified it will default to the same as old. So in principle you can write in the process S y instead of case you can write if so you say if S is 0 0 then a gets y all others get 0 else if S gets 0 1 then b gets y everything gets 0 else if S is 1 0 then c gets y everything gets 0 else d gets y and see this else will capture everything else and there should not be an issue. And similarly you can have instead of repeating all the other signals here you could write you know initialise everything at the beginning and only what is changing could be written like in the case and so these are kind of different ways of coding but you know that like you can use if but the case is better you can use with select and when else but definitely the case or if is better in that the case is better. In that there are two ways of writing it one is very concise less error prone easy to understand so I think you should be essentially using that so sometime when you are faced with I think it is important that you stick to the correct coding. So let us take another example let us come back to the coding let us take an example of an adder we will look at a ripple adder the code for a ripple adder we will also look at the code for a carry looker adder and how to write the adder though we may not use a carry looker adder anywhere in our design it is not required because it is huge it is exponentially complex in terms of the product terms use so we do not use it but then it is a good example good practice for writing the code. So let us go to the slide so let us look at this this is the ripple adder say I am considering I am showing the picture of a 4 bit but we are trying to implement an 8 bit adder so I am only showing the 4 bit you know that this is a full adder you have A0, B0, C0 as input you have some as the output and the carry as the output to the next stage and here A1, B1 comes some one is the output carry 2 is the output to the next stage. Now that is the equation sum is sum 0 is A0, XOR, B0, XOR carry 0 carry 1 is A0, B0 or A0 or B0 and carry 1 carry 0 okay. So basically the carry 1 is generated if both are 1, 1 then definitely there is 1, 1, 1 plus 1 is 0 there is a carry or if either of them is 1 then it is 0, 1 is sum is 1 a carry input 1 will make it 0 and generate a carry that is a game. So this is many a times is called generate A, B is generate A or B is propagate okay. If A and B are 1 it generates a carry from this stage if A or A and B are kind of either of them is 1 then it propagates a previous carry to the next stage and that is how the rippling happens. Suppose this input is 1 and this is in propagate mode, this is in propagate mode, this is in propagate mode that means you understand what it means it is all 101010. Then there is a rippling there is a delay through this and or circuit then that goes delay through the two level and or circuit, delay through the two level and or circuit. So you get by the time the carry input comes here C3 comes here there is 6 levels of logic and it delays everything the sum is delayed because the sum is going to use C3. So when it comes to the fourth one it is much worse okay. So that is a ripple adder so let us look at the code first then we will go with the carry look adder. So here there is library and we are going to write a neat code so we have a carry in and we have a carry out. So we are going to have A0 to A7, B0 to B7, sum 0 to sum 7, A carry in and a carry out okay. So that is it port A, B is 8 bit, sum is also 8 bit but we have a C in which is a carry in standard logic, C out, out standard logic okay. Now when you write the equation it has to be elegant now if you start you know we are going to write a loop generate loop to say if you keep this as C in there is an issue because then this that C in part has to be outside the loop because that is that will not work because then A0, B0 should be kind of combined with the C in. So it will be good if you declare an internal signal carry because this is an internal signal and we say carry 0 is C in okay. Similarly we have a carry 8 ultimately we assign it to the C out. So that is what we have done, signal is carry which is standard logic vector 8 down to 0 now. So because we have C0, C1, C2 all the way up to C8 which is a 9 bit vector that is it. We say carry 0 is nothing but the C in, C in we are assigning it to carry 0 it essentially like changing the name you know there is no as such there is no this assignment does not mean anything it is just we are changing the name. Similarly the carry 8 we are assigning it to C out. Now we can write a neat loop for GLP label for I in 0 to 7 generate we say sum of I is A of I, X or B of I, X or carry I carry I plus 1 is AI BI or that is generate or AI or BI propagate and CI. So it becomes very neat if we had not made this assignment not define the carry like this we would not be able to write everything in a loop something has to be outside. So every time you write a code make sure that you define the signals as assignment so that things are very generic kind of concise, elegant and things like that. So now let us look at the carry look at adder. So in the carry look at adder the game is that what we are trying to do is that in the ripple adder when it comes to the carry 2 first the carry 0 is generated with A0, B0 and sorry carry 1 is generated with A0, B0, C0 and that is used in this A1, B1 to generate C2. Now what we do is that we kind of when it comes C2 instead of rippling through what we do is that we expand this C1 you know what is the equation, equation say that carry 2 is A1, B1 or you know A1 or B1 and carry 1. So if you just expand it in terms of the carry 0 and flatten it you will when it comes carry 2 will generate it straight away from B1, A1, C1, B0, A0, C0. So that it is a two level structure. So instead of kind of what say a kind of modular adder this is an adder which is see this is it is also surprising you know it should many times people do not question like any combinational circuit you design you know buy from the specification you write a truth table and you try to implement it. But surprisingly when it comes to the adder we make a 1 bit unit then you use that modular unit to cascade and build a kind of ripple adder okay. But that is not what we have used in a basic combinational circuit design the essential thing we used to do was that make a truth table and work out the equation and try to implement. And frankly if you have a 8 bit adder you write an 8 bit truth table yeah it is quite complex then you make the equations out of it you try to implement you will get a carry look at adder. So at least if you are kind of doing it properly in any learning the carry look at adder should come first and we should be saying that there is an issue with such a scheme because it is exponentially complex in terms of area. And then so we adopt such a ripple adder it is not that the ripple adder comes first from the principle and the carry look at adder comes second definitely the carry look at adder comes first. And because of these particular issue we default to the ripple adder that should be understood. So maybe we can quickly look at the carry look at adder structure in the next lecture maybe we will look at it in detail and kind of look at the VHDL coding which is quite straightforward but then it is a good exercise to do. So let us quickly look at the carry look at adder. So this is basically say the C1 so the equation is SFI is AI XOR BI XOR CI no issue with it I mean for each stage the sum is same but the main issue is with the carry which it you know when it is modular it when it cascaded it ripple through. So we are trying to kind of expand it and try to build so as like C2 comes we are building A0, B0, A1, B1 when C3 comes it we are building you know it in terms of A0, B0, A1, B1, A2, B2 and so on okay. So that is a game maybe that we will see in detail in the next lecture. So the last part we have looked at the various coding and example we have tried various syntax of demultiplexer I mean we applied for the case of a demultiplex of various syntax though there is an straight forward EC elegant solution. We have looked at the ripple adder code reasonable code once again we will not be using any of these but then as I said it is a practice we briefly looked at what is wrong with the ripple adder though as I said the other way should have been a better thing to do. And so I wind up here please revise it and I wish you all the best and thank you.