e e e e e e e for yes video is not on YouTube I think if I talk uh that's what says no are you Ser yeah [Music] okay good afternoon everyone Let's Get It Started is my audio okay on Zoom okay okay welcome back to another lecture in digital design computer architecture lecture five today we first going to continue uh what we have left off in Hardware description languages and very luck and then hopefully we're going to have time to start timing and verification and tomorrow we're going to basically continue that and finish uh timing and verification and potentially finishing the first part of this course which is digital design and from next week we're going to start learning about computer architecture to use fundamentals that we learned how to design uh computers a processor microprocessor and so on so forth uh we had some live stream issues and record recording issues last week uh for for Friday lecture so that's why we actually uh uploaded a new video uh for the last week lecture if you couldn't attend last week lecture uh you can actually check that video which it was premiered actually yesterday uh but you can also check anytime you want okay are there any questions then we can get started so this is agenda for today which is going to be related to uh Hardware description languages and these are the week readings for this week um this chapter for Hardware description language and also this is for today probably and tomorrow about timing and verification we discuss about why we need a hardware software um Hardware description languages um last week but I'm going to quickly go over them to jog your memory so essentially htls enable easy description of Hardware structures and you know that in Hardware we have wires Gates a lot of components like flip-flop clock and also some specification like Rising falling Edge as well as combination of sequential logic elements and also uh in Hardware we have a lot of concurrency so defining all these uh in in a using normal and you would say general purpose um software languages is not easy so that's why people came up with these specialized languages for Hardware uh to basically provide that uh you know easy description so we discuss about this key design principle in designing uh our system that we need to come up with the hierarchy and U we discussed about this top- down design methodology that you have a top level module and that is needs to be identified using sub modules uh that they are necessary to build and then subm modules can also be divided to Leaf cells some other subm modules and also IND thean some leaves uh which your leaf cell can be circuits component that cannot further be divided it can be logic gates or sometimes primitive cell library elements that we're going to see a bit uh we also have this bottom up design methodology that you need to start for your leaves and then make bigger modules and then combine them to make uh to uh construct your top level measure and I said that in the end uh usually we combine both uh methodology we always kind of think kind of top level top down modules top down design methodology and then when we want to implement this usually follow bottom of design methodology and this is really important for testing and verification as well so once you have this kind of design methodology you want to make sure that you verify every single maju before going to the higher rank so if you don't for example test your um any of these modules that you have here and then you combine them to make the sub module and then you start testing your subm module in this area if you get some error then uh good luck finding your errors essentially you know source of Errors because this can be combined some some accumulated errors that happening from any of these prior levels so it's important that in any level that you are designing you need to verify your Mau make sure that it's correct and then go to the another level uh we're going to learn about verification um probably tomorrow but that's the kind of insight that you need to get here okay and then we discuss how we can define a module in very L that essentially you need to Define name of the module direction of the ports input output and also name of the ports and then we need to describe the functionality of the module we see this kind of module definition as an example that you have three inputs ABC and one output which is y and then yeah we go over this syntax and we discussed that these two following codes are essentially the same and it depends on your style when you are programming and also we discussed about having bit vectors uh that for example a here represent a 32bit value so we prefer Define it as uh 31 to0 a and we we do not use the other way around like 0 to 31 when we want to Define uh bit vectors we use this when we want to kind of uh have a array in your design so sometimes in your uh in your code you want to Define an array so for that you can actually make it like this you can also have an array of bit vectors essentially so um you can combine all these together okay and this part uh we left off and then we continue from this part so now I want to essentially discuss some uh syntax that we have in veryl so one very important operation that we want to do is manipulating beats one of them is B slicing which is we want to assign partial bosses so here is an example you have a long boss which is 16 bit and you have a short bus which is 8 bit so you can assign short BS to Long BS uh 12 to5 which is uh basically a slice of that long bus essentially so you can actually select uh a portion of that long bus and assign them to your short bus this is one of the um syntax that we have another syntax is Con concatenation that you can essentially concat a lot of different uh signals together to make a bigger signal or bigger bit Vector so here we know that U for example this Y is a 4bit u bit vector and you can actually concat uh these four uh basically values here to make this four bit vctor A2 A1 a z and a z for example and each of these a two is one bit another way is to uh use duplication so you can also uh use this U syntax here uh we want for X we want to have four a z for example you can write it like this using concatenation uh command or you can also use this duplication command which essentially you are duplicating a z so this kind of syntax help you to you know write uh your code a bit uh easier or maybe smarter there are also some other basic syntax that I'm going to go over so very like is case sensitive uh someone some people actually uh find it a bit annoying which is but it depends on your sty so essentially these some name and some name are not the same in very be careful and names cannot start with number so too good is not a valid name white spaces are also ignored uh you can have command uh commands like this uh it's very similar to C++ I guess notation here you can have this slasher slash and you have a single line command and then you can also have this SL a start to have multiple multi multi-line comments so we have two main styles of HDL implementation this is not actually only U specified to very l is actually more or less related to any hardware description language but here also more specifically about very log we can have a structural uh way of implementation is also called as gate level but does not need to be essentially gate level uh the definition is that the module body contains gate level description of the circuit but these Gates can be also some instances of your prior modules so you have sub modules so you you have some gates you combine these Gates and make some sub modules and then you want to combine these sub modules to your to make your top module essentially so these sub modules if you instance them instantiate them your code you are actually using this structural way of programming so we need the modu has this gate level description or um module instantiation of the circuit and we describe how modules are interconnect and each module contains other module which is instances and interconnection between those modules and we need to describe a hierarchy of modules that Define as Gates essentially another way is behaviorial which the module body contains a functional description of the circuit and contains logical and mathematical operators so writing uh modules in behavoral is usually quite easy but then U because level of abstraction is higher than gate level but it also comes with some issues and overheads that we're going to see later and in the end many practical design actually use a combination of both and you're going to also see in some examples today okay any question yes how do we decide where the wires go like does it decide automatically no we're going to see in the syntax yeah soon okay so now assume that we have this design uh there are this top module and this top module actually has two sub module which is small small module and you can see that this is the first instantiation this second one and these are our input to the top module a cell C and this is the output and also we have some intermediate wire here N1 see how we can actually write this code for example in very luck so we first uh need to Define this top module I mean there is no first and second you can actually do it the other way around but this is one way you have this module top uh which is uh you have these inputs a cell C and output y so you know this notation also there is a intermediate wire here that you need to Define it wire N1 with this syntax and then you have these two sub module you also need to define a module for that module is small and this has a y so a are the input and why is the output and there should be some description of a small that we kind of ignore at this moment and then end module so now we need to instant instantiate from these uh small subm modu essentially so this is the first instantiation small and then the name of this instantiation can be anything so here is that I underline first and then you need to say how these uh ports are connected so you know that for example input a is going to the input a of this first modu so you just this is a notation you say that a is connected to a so this this a here is actually this A and A is actually saying that uh the the input Port of a is connected to that wire and you can do it for other things for so for B also you you can say that b is connected to cell and Y which is the output is actually connected to this wire N1 that's why we need to Define this wire essentially here so this is the first instance and the second instance we have it here so uh essentially yeah the output of it which is again N1 is going to go to the port uh a and then C goes to B and the output of this module goes to Output y so with that we actually finish the the definition of this top module we still need to define the def description of the module is small we should kind of ignore at this moment but this is if you write your code in this style you're actually using a structural way of programming any question does that answer your question sort of this but like you could imagine a line like the Y going diagonal or like how does it figure out where to best how to best like put the wire on like the chip itself not in act so you are defining uh you're defining it no we Define the end point but not the way oh okay so you're you're talking about the routing of that wire so that's actually in another level um so when you def you when you program your HDL you need to test and verify and then when you're okay you're sure that your design is at okay and running correctly at that moment you need to synthesize it there are other tools for that which call them computer aided design so you need to synthesize your htl code to some gate level using some sell libraries we're going to see actually that a little bit but then after that when you have the description of that gate level then you need to do use some other tools which they uh do this uh floor uh place and Road and floor planning essentially so different companies actually have their own tools uh that they use to place and Road and floor planning and the question question that you're asking is actually the question for that moment when when people want to do floor planning and place on road they need to solve this question that uh where should I place these components and how should I rot wires them so that's uh that's out of a scope of this course but we can discuss maybe later offline if you want any other question that's also happening kind of in V also so because for f you also need to do this operation as is so the the tool chain that I describ is actually for um ASC kind of design like custom chip but for FJ we also have the similar uh tool chain so your htl code needs to be synthesized and mapped to some Luts and then these LS need to do place and rot essentially you need to place these Luts and then rot them somehow and that's the job for V to essentially question but that was very good question okay great so we can also have some other form of module instantiation um so this kind of notation you can actually also write it as this like a cell N1 here you kind of assume basically you're uh relying on the order of the port so in the definition of a small you that you know that we have three ports a y and this is order essentially a y so when you want to connect these ports these wires to these ports if you've put exactly three um signals here and you follow the same order you are you're making sure that you're connecting correctly essentially but as you can see this is not reliable um so that's why better to use the other notation which is happening here and that's much better for uh to reduce BAS basically for better uh maintainability of your code question okay great I also forgot to mention that these uh htl uh very like slides that we have are kind of tutorial for you so I may actually moving fast on some of these slides but in the end you're going to use a lot of this information in your Labs so in in the lab assignment that you're going to have you're going to actually look into all these slides and follow the B symbols syntax and all these stuff so don't worry if I'm going over some of these slides a little bit fast okay so in a structure H example we say that very supports basic logic gaze as predefined Primitives we actually this is very important so these Primitives are logic gates and they are instantiated like modules except that they are predefined in very and we don't need to add a module to Define it like these Gates like not and and or you can just simply write and and then G2 G2 and then this is the basically uh instantiation of that like the connection of these ports so yeah so essentially uh for for these kind of Primitives you don't need to Define them very luck has already defined them in the in library here also we can look quickly to this example you can see that this is the definition of this multiplexer and uh so you simply say that okay we have this two input d0 and D1 and then this is output Y and this is our selector right so you can easily write this code like there is also a little bit notot here this tiny knot so you need to Define this knot as well so that's why we have this wire NS and then we put not uh J1 NS and S another important thing for all these primitiv is that the first uh basically signal that you put in parentheses is actually your output and then the rest is the inputs so that's the syntax little syntax that you need to memorize but that's the only thing so for not we have this NS meaning that okay this is my output and then s is the input for and we have this Y y1 which is the output and then this d0 and NS and for this and also we have um output is Y2 and then D1 and S are the input and then we have this orgate which or y1 and Y2 and then output is y so that's your definition of your multiplexer two to one yes pref option we should inputs and outputs theet no this is actually completely related to your style essentially whatever I actually I remember I was following this sty when I was coding but some people just following the other so okay okay now we are done with a structural htl example so let's also look into behaviorial remember these two main Styles in behaviorial essentially we are using equations and they can be arithmetic logical equations so here um this is an example from fun ality that you can uh we are providing here like you have this module example and then you have three inputs and one output so you are use this is the key uh word here that we use assign this is you need to always use this keyword when you want to assign um you know a value to a signal this is a notation you need to write assign and then the output like the the output or the signal that you want to assign value to it which is y here for example and then some equation and here is a for example equation that negate a and negate B and negate C and then or and then many many other things so you can actually do a lot of these things and that can make your life much easier and this can be actually synthesized to exactly this uh implementation these are all these ends like the first one and the second one is this end and the third one is this end and then you need to order yes like they are not automatically simplified uh they are simplified uh so all these uh synthesizing tools they also have this logic minimization uh operation that they are doing so they are trying to do a lot of optimizations okay and they are simplifying but uh I I should also say that the way the simplification that we learned in this course like very simple was to make your signal in two levels essentially your circuit in two levels one level is and and the other level is or right and and or but uh in reality usually circuits are actually mult they have much higher depths and the reason is that uh making big large and operation for and like big gates are not easy having gate that have like tens of input is not something that you can assume easily so that's why in order to reduce the number of inputs uh to to your Gates synthesizing tool try to increase the depth of the circuit so they actually logic optimizations algorithm are much much more sophisticated uh they also considering this area of increasing the depth of the logic and that adds a lot of another angle to your optimization essentially but at the same time they can not also they don't guarantee that they have the best possible with with somehow some definition of the best because in the end it actually trade off you need to kind of you have some constraints and you want to make the best out of these constraints essentially but within that also because they are using a lot of euristic in all these algorithm optimization techniques so in the end they cannot get to Optimum whatever um design essentially yeah very good question okay so we have the different bitwise operators in Behavior very log here is for example and operation this is or operation this is X or this is n and this is nor for example and you can easily use all these operations and this is the basically uh synthesized version of or schematic view of your circuit that we have seen here we also have reduction operators in behavioral very assume you want to reduce uh you want to do reduction and operation in a bit Vector so you have a bit Vector of 8 bit for example you want to add all the elements so one way is to write something like this assign Y and then you need to and all the all these elements but there is also reduction operator that you can just easily say y equals to ERS sign a and then it going to be it this this means that you are redu over an essentially so all those operators that they have this meaning of reduction you can actually use them like this and this a schematic view of this synthesized version like if you say assign y equals to and a it's going to be like this in the end okay we can also have this conditional assignment uh which I think you are aware of this operator in C++ programming also probably but essentially you can for example easily say that uh it's kind of implementation of if else right you say that assign y equals to then you check your condition which is s and then s question mark if if it is one uh one then y should be D1 and if it is zero it's going to be D zero so you have a condition and that if it's true then we pick the uh this second item here and if it's is uh false we get the third item you had question okay and the good thing with this question mark operator we can easily Implement multiplexers and as you can see you can also make uh multiplexer of 4 to one for example so you first need to Branch out on U the most significant bit of your selector S1 and if it is for example one then you need to check the value of your second bit of your select which is s0 and based on that you can decide on uh the input that should connect to the output any do everyone convinced that this is multiplexor 4 to1 okay good um yeah this is also another way of writing it uh you can for example multiplexer you can also write this way like the code is like if something and then you check if again if if else and else if else but you can also write it like if else if else if else for example and this is another way for example you can say that a y equals to then you check this condition first if it is true you assign it to D3 if it's not then you check another condition which is kind of else if again another L if and then in the end you get your else value these are quite simple because I think you already know from C++ programming also uh which I'm not sure if do you study C++ in your basic programming or oh Java okay but Java also we have this operators as far as I remember yeah okay I kind of assumed that you learn C++ that was wrong okay so we have also this precedence of operations in verog that you can also check if you are interested but I usually prefer to not rely on these precedence and use parentheses you know just to make sure things are okay okay now let's see how to express numbers in verilock we have a very exciting notation uh for numbers in verilock which is uh n and then uh the base and then the value so n is actually number of Beats because in numbers values are actually you need to somehow synthesize them right so you need to have have some wires for them or or some registers for them so you need to think about okay how many bits you want to use so that's why we have this n here to show the number of Beats and then we have base which you uh if you for example put B your the values that you're uh writing here is going to be uh interpreted in binary if you for example H is going to be interpreted in hexadecimal or D is decimal or or is octal for example so you need to also specify the base here and then the number and in the number you can actually also have X which is invalid and also Z which is floating so you kind of know about X which is kind of don't care or un or invalid or Z which is floating which we use Z for trate buffer for example if you remember so let's see some examples um let's see for example this one uh we are saying that four we have a value which is 4 bit and then it's going to be binary of 1 0 01 so the stored number is going to be 1 z01 here we have a very like sorry we have a number which is 8 Bits And then binary 1 z01 so whenever you have less number of value here as as much as you need you need to add zeros here um so here for example it's going to be stored as 0000 1 0 0 1 because you need to eight bits here you can also use this underscore for better readability so this is just for better programming style it's not something related to the number that you are presenting if you don't specify the length it's going to be considered as 32 32 bits which is the default size in very L you can also change the base and and you can see this example also later any question good so these are kind of reminders for you that we have these floating signals that and we use this concept for triet buffer as remember and then we talk about uh how we can use this uh basically tricet buffer in order to manage a shared boss so in this example for example we have a we have CPU and also we have memory and both CP and memory needs to access a boss like your memory boss so both of them cannot drive the bus at the same time so we have this triet buffer in order to gate CPU or gate memory uh when it is zero it means that CPU cannot drive the shared B and memory can drive essentially if the gate memory is one for example and we also use this uh we for other for example interfaces as we can see here so the TRU table for and gate with z and X in your input can be something like this um so the this part is similar to what you have already seen which is and gate but whenever you have uh for example Z and X let's see what's going to happen in your output if you have uh if you have one if you have one if you have zero in one of your inputs the output is always zero no matter the other input is z or X which kind of makes sense for and gate right whenever you have zero one input zero then output should be zero but in other case when you have uh one input as one then the the output depends on the other input which going to be Z or X and in the end your output in very log notation consider as X so that's why we are so whenever one of your input is z um and then the other input for example is one the output that very L going to show you is actually X so very L is not going to show Z in the output which kind of makes sense because your output is still connected to pull up or pull down Network it's not float right uh it's not floating so z uh so that's that's why we don't use Z for the output uh in for the and and operation for example and I think you are also aware of this priority uh circuit that we use for um priority encoder for example and you can easily Define it in very L using this notation any question okay great so now let's see what happens with htl code once you have your htl code what what you can do with so one is actually synthesizing so you need to you can synthesize your circuit into Hardware into Primitives in these Gates and then after that gate also needs to be synthesized actually to transistors and in the end your circuit uh all these transistor needs to be layout on your uh chip which is because for for that for example all these operation process of litography that you want to design your IC integrated circuit you need kind of uh layout of all these transistors and where they are placed such that you make uh make some mask and then based on that mask and you know and this L graphy process you can build your IC so but essentially the synthesizing is very important and modern tools are able to map synthesizable htl code into low-level sell libraries and they can perform many optimization as I said like optimization in order to for example based on your constraints sometimes your constraint is that you want your circuit to work with a frequency of one gahz so that's your constraint and then the synthesizing tool tries to synthesize your circuit in a way that can work with that frequency so that's a constraint you are providing or for example you saying that you want your circuit to be um the area the area cost of that circuit needs to be less than uh 1 mm Square for example so once you have that uh constraint then synthesizing tool tries to make sure that your area is not is less than that and all these sometimes this actually constraint can be a bit conflicting so synthesizing tool actually does a lot of job tradeoff between the constraint that you define and your goals and to get you know to make you an designer in the end happy hopefully but the problem is that they cannot guarantee that the solution is optimal and it's mainly due to computational expensive placing and placement and routing algorithms okay it's actually a bit of our job also that we need to also do our job well so we need to describe our circuit in HDL in a nice to synthesize way so when whenever you program in HT you need to also think about okay what would be the hardware structure of that if you don't think about Hardware while you're doing htl you're going to end up something that you don't like in the end I'm going to actually show a quote later that has that message okay and another important uh thing that you can do with your htl is to simulate so we can simulate our code that allows the behavior of the circuit to be verified without actually manufacturing the CC this is really critical as I said because we don't design we don't make our top level module and then you know place and rotate and then test it so with every uh step we want to test and make sure things are okay so every single modu needs to be verified and once you are okay with the functionality of that you go a little a bit higher and then you design combine them make a bigger circuit then you need to test that and also go up and up until you get to the top level once you're uh fully okay and fin with the correctness of your design you can then synthesize it and then U basically through the place and Ro so simulation is actually very very important and exciting part of using htls and the good thing is that all these simulators can work on a structural or behavioral htls and also for functional and timing verification that we're going to also see later okay so this recall this example that we have shown and then and this is the synthesiz it's going to be kind of simulation that we're going to do in this course as well so you need to give some basically Design This wave from diagram so for these inputs you need to Value them uh you need to basically make some pulses like in this time frame uh which when they are going to be one when they're going to be zero so there is a uh time frame and pulse uh specification for all these inputs and then for the output uh the simulator is going to generate you the vform and then you can actually um you know convince you yourself that this circuit is working correct or not question but this is not as easy as it looks and uh and actually test is one of the most expensive and time consuming part of actually designs and lot of money is actually going into making sure that that this design this ship is actually working correctly so verifying our modules and U basically circuits is is not an easy task espec because of when your design gets bigger and bigger because when you have only this kind of design ABC you know the only three inputs so there are only eight you know the basically patterns of ABC and you can actually check every single pattern you can also go a bit uh also deeper and say that changing from one pattern to another pattern so there can be a lot of rotation between that you can also test all of them but once your design has tens input or hundreds of input then you cannot test all different patterns so you need to uh have a kind of sample you know you need to sample and somehow assess that okay these patterns might might be more problematic so I'm going to test them so that's why actually verification is one of the active still active research in U cat tools and also designs okay question so this is also a note on Hardware sentences you can actually also read it from your book but I'm going to also read it very very quickly so one of the most common mistakes for beginners is to think of htl as a computer program rather than a shorthand for describing digital Hardware if you don't know approximately what Hardware your htl should synthesize into you probably won't like what you get and that was my point essentially so you need to think about the hardware when you are programming with HDL you might create far more Hardware than is necessary or you might write code that simulates correctly but cannot be implemented in Hardware instead think of your system in terms of blocks of combination logic registers and finaled machine sketch this blocks on paper and show how they are connected before you start writing code so that's why following this methodology of top down and then implementing bottom up is really important and actually using a structural uh way of programming in very L is kind of very important so you can actually use uh functional Behavior behavioral uh style of programming for some simple some modules you know that they are close to the leaf but then after that you need to essentially combine these modules and make bigger bigger modules so that then that's where you use a more structural way of programming okay so these are what we have seen so far we know how to describe a structure hierarchy we know how to use functional um how to describe functionality using behavioral modeling we know how to write simple logic equation and also design for example multiplexor functionality we can also describe constants um there is a keyword for that that you can also check uh but there is more so the thing is that uh we can write very L code in many different ways um we can express the same functionality by developing very L code at the low level of abstraction we have full readability but it's easier automated optimization especially for lowlevel tools but at the high higher level of abstraction we have better ability but at the same time we have more difficult automated optimizations so let's uh see with this example we want to compare two numbers and uh like this equality check so you know from last lectures that equality check can be done easily with X nor and then ending the output of them like if this equal is one meaning that uh a and B are completely equal and if it is zero it means that they are not equal so one way to write it is completely following gate level implementation so you have okay you can also I kind of uh ignore this part you can also Define this uh two input xor gate and also two input and gate which is kind of unnecessarily because I mean these uh gates are already implemented uh as as PR Primitives so you don't need to do that but this this example wants to you know show the extreme case that we Define everything so and then you can actually combine all these uh Gates um in your design so this is instantiation of this xor so we have three xor and then we have three ends because each end is actually two inputs and then basically you can uh get your equality check but you can make it simpler using logical operators you can use assign statement and then for for and operation you can make it simple then you can turn all these three assignment to actually one assignment which is you can use for and operation then uh then actually yes you can also instead of instead of ending all these you can define c as a as a vector as a bat vector and then you can use this reduction and operation in order to get the equality check we also we can get rid of all these xor definition and then Define one assign c as you know X node of all A and B we can even get rid of these two assignment and combine them easily with this notation saying that equal if and then the condition is a equal B if through one if not zero so this example wants to show you you know you know kind of how much you can use these operations uh in order to make your code simpler but you should be careful because some you are actually removing some of the some insight and readability from your code so once you have this kind of xnore operations for example you are sharing some information to the to the reader which might not be needed probably this might not be the best example in the world but uh but in the end this is a trade-off that you should be always aware of that and that don't overuse this behavioral way of programming and also use it as much as possible because that's that makes your life much easier question like in this example would the last like would this final solution be slower than the other one because it's more diff for this example probably no like for more difficult for more difficult yes it might be because uh because when synthesizing tool wants to synthesize your code uh they may since they don't know what you were thinking of they may actually end up adding more gates that's needed you know uh but again I mean this problem Rises much more when you your design is much much more complex it's not for such basic designs but in the end yeah exactly if you follow a structure way um you're going to get to the hopefully optimize design for example for a processor you're going to learn that we have data pass and control unit and you're not going to you're not open a very like say that module very L and module processor and then write the whole data pass and control unit you're going to have every component data pass also contol unit and then going to instan shate among them so let me finish this and then we can take break so in order to have more reusable very lck code some you want to do operation on different BDS of numbers 5 bit 6bit or nbit there is a good way of in that you can parameterize your modules so you can Define this parameter you can see that this hashtag parameter with eight and this is the default value of this parameter and then you can actually use this parameter to Define your bit vectors and with that you can actually set this parameter and this design can be work with different size this is an example of your multiplexer if you don't specify your parameter this going to be synthesized exactly as the default value which is eight so each of these input are eight bit Vector but you can also Define this parameter here like hasht 12 meaning that you want to have uh bit vectors of 12 and this would work you can also make it a bit more verbos and then have this um bits 12 which is useful when you have different par several parameters in your design if you have only one parameter maybe you don't need it but if you have several parameters this notation might be better because you are specifying much better for readability of your code so in very long we can also add timing um to our circuits but this I think I will cover it after break so let's have a break until the ring bells again and then we'll continue e e e e e e e e e e e e e e e e e e e e e e e e e e okay let's continue so we we talk about how we can define a parameter and how to use it but also we can Define timings in our very log code so is it possible to Define timing relation in very log for example you can say that what would the latency of your Gates uh or yeah exactly for for every gate you can Define latencies and also you can add these notations like timing notation in to essentially enforce some delay into into your circuit so this is possible but you should know that these are only for simulation uh which is quite useful actually for simulation when you want to design some test bench you know when you want to uh design test bench to provide a wave form for your input you can you actually use a lot of these notation timing delay notation in very L that you're going to also see in your Labs also uh backing to my U basically uh backing to my example about synthesizing so you you you simulate your code in the functional you do this functional simulation and then you see that your design Works correct correctly but then you synthesize it when you synthesize your code uh your circuit is actually completely different because now it's your circuit is with all Gates that they are defined in the cell library that you gave as an input to your synthesizing tool now you want to see that your design actually works corre correctly with those Gates as well so this is actually called as post synthesizing uh simulation so it's after simul after synthesizing you want to simulate and you want to make sure that your design works correctly so for that actually people also add the latency of all these gates gates that they are defined in library in your uh in your very lck code in order to see that your design works correctly considering all these delays essentially so that's why I'm saying that uh defining these timings are actually very important and very Lu but they are only for simulation and they cannot be synthesized so whenever for example when you have a delay of four nond in your code that for nond cannot be synthesized so make sure that you don't have these values or timing u in your code when on the code that you want to synthesize it on your test bench sure you can do it and you should do it actually okay so they are used for modeling delays in a circuit as I said for example here you can say that um a sign sharp 5 Z1 neg of a meaning that whenever um input a toggles output basically Z1 will uh we have that value like the negate of a after 5 nond for example here also for example we are defining n n nond delay for example you can also Define different uh rise and fall and I don't know minimum maximum typical all these delays but these are not so important at this moment okay let me share some good practice of U programming so it's important that we develop and use a consistent consistent naming style uh we prefer to use mult MSP to LSP ordering for bosses so we use a31 for example to zero not a uh 0 to 31 this notation is actually used more or less as I said for array not for bosses and we prefer to Define one module per file so makes um that makes managing Your Design hierarchy much easier and we can use a file name that matches the module name for example module is try this we can have a very L file which is tries. V for example and we always should keep in mind that veryl describes Hardware this is I would say the most important note here that essentially you need to think about the hardware while you are using htl so you cannot really program htl as the way you are for example programming with Java or C++ or whatever okay so this is a summary of htl for combination of logic as we have already seen like we have seen an overview of very they discuss the structure and behavioral modeling and they studied combination of logic constructs but now let's see how we can Define sequential logic using berock uh this is a reminder for you that sequential circuit actually consists of combinational circuit and the storage element and we know from FSM for example that the storage element are states and we use them to use we use def flops for example to store the states and then we have two combination of circuits want to generate next State uh which inputs from external inputs and also the current state and also we have another combinational circuit for the outputs and that uh combinational circuit can get input only from external input or which is the mo machine or from the external input and also the current state sorry I me I message it wrong so the the the combinational circuit for output if it gets input only for current state that's a more machine if it gets input from both uh States and external input is going to be the mlie machine as you probably know okay so we need to Define blocks that have memory like flip flop latches finite St machine and we know that sequential logic State transition triggered by a clock signal which is like positive Edge or negative edge of the clock so there should be a way to define such uh specification very Lu so for that the problem is that combinational htl constructs that we already covered uh so far they are not sufficient or I would say easy enough to express sequential logic actually in some cases they cannot work because some of these like the latch logic or def FL FL logic that we already covered it actually works by considering some delays in your Gates while you are defining your structureal behavior uh in that functional simulation you are not considering any delay by default if you don't consider any delay that those circuits may not work so that's why actually very like come up with new constructs in order to Define for example these kind of uh Behavior so this always block is the block that you're going to use it a lot um this is a notation you have always and then add sign and then there is this sensitivity list and one statement and one or many actually so this statements are are basically should come in the block of always that they will be executed if this sensitivity list asserted essentially so whenever the event in the sensitivity list occurs the statement is executed so this is a recall for you the FL flop that we have these two latches so this is the way that we Define the flop in bck for example so module flop we have input one clock and also input is actually kind of register at this moment uh four bit input and output r 4bit q so this is a notation you say that always add sign and then you for the sensitivity list you want to make it sensitive to the positive edge of your clock so this is a notation for positive Edge you say POS and clock and then whenever it happens Q uh gets the value of d okay and this is the notation so also um you cannot use assign statement as you seen in this uh the previous slides in the always block so that notation should only work outside the always block the assign and this notation which is uh um smaller smaller or equal uh this describes a non-blocking assignment this is actually notation for non-blocking assignment we're going to actually see what is non-blocking and blocking assignment later soon here also I want to emphasize on this definition so whenever you want to assign a value to a to a signal which is in the always block you always need to Define that as Ri so signals in by default are wires in very log notation but if you want to assign them in all block you need to Define them as R but this R is not actually does not mean register so the name r does not necessarily mean that the value is a register it could be like here but it does not have to be so we're going to see examples that we have uh actually R values here but they are synthesized to combinational logic but this is a notation that you always need to follow whenever you want to assign anything to the in the always blog you need to define it R question we also talk about asynchronous and synchronous reset in the past uh you know that with asynchronous reset the reset signal is sample independent of the clock and reset gets the highest priority and we know that this is sensitive to glitches and may have mental stability issues but people uh usually and people prefers a synchronous reset when they want to make it high priority essentially we're going to discuss about glitches and metal stability also later in our timing verification lecture we can also have synchronous reset that reset signal is sample with respect to the clock and this res should be active long enough to get sampled at the clock Edge because this going to be um basically treated as similar as other inputs and we discuss about basically overall a synchronous and synchronous State changes in the past also in our lectures um we mostly consider assume synchronous system in this course but this reset can be asynchronous so in our synchronous circuits you can still have asynchronous uh reset also okay so this is a notation when you want to Define as asynchronous reset so you have this always at positive Edge clock and Negative Edge reset so you you want to make it sensitive to the negative edge of reset which is kind of definition for asynchronous reset and in this always BL you say that if reset equals zero then Q is zero and else Q takes the value of D so yeah clock is rising Edge and reset is falling Edge we also have need to use this begin end when we have multiple lines here actually is not needed because we have this if and else and if lse is considered as one block so you don't need to add begin end but it's good to add beginning end because it makes your code better I me for readability is better okay so first reset is check if reset is zero Q is set to zero and then this is an asynchron reset because we can enter this always block without clock so if without having this positive edge of clock if we have Negative Edge of resar reset we just enter the all block and if there is no reset then the regular assignment takes effect here is an example for synchronous reset so your in your sensitive this you you only should have positive edge of clock and in this code you say that if reset equals zero then Q is zero the other one the other case Q takes the value of D you can also add enable signal to your uh to your definition so that enabled def F flop so if if reset so here is an example with a synchronous reset so you first check the reset if it's zero then Q is zero but then you need to check the enable signal if it is enabled Q takes the value of D otherwise Q needs to you know keeps the value that already have essentially so there should be a memory here and that's why this is going to be sent aside as a register and not a combinational circuit question so far yes why do we use negative on this Um this can be positive Edge also I don't know the exact reason usually people prefers to use Negative Edge I don't know the exact reason but this can be also implemented the other way so any other question okay so uh another example would be DCH um you know that in DCH we are sensitive by the so whenever we are um basically are enabled or when our latch is in the transparent mode we are uh moving everything in the input to the output so our sensitivity list is sensitive to clock and also the input so whenever uh our clock is basically gets active we need to we enter this always block basically whenever we have uh exactly we have some changes in our clock when if it is one or zero so when your clock is one in the initial um situation you don't enter always but it is one and then you go to zero so now there is a transition your clock so this sensitive list is going to be asserted so you're going to enter this always then your clock goes to one then you enter always again so whenever there's a transition you enter right when whenever there's a change essentially but also here we are sensitive to the D also maybe your clock is in the in is one maybe your lch is in the transparent mode and now your input is changing so you want to transparent the input to the output so you need to enter this always and change the output essentially so that's why we put D also in the sensitivity list here okay so always add clock and d and then if clock Q takes the value of D and in another case basically Q should uh keeps the the value that already has okay so this is a very quick summary sequential statements are within and always block the sequential block is triggered with within with a change in the sensitivity least and signals assign with always must be declared as a r uh this is important if you don't follow it you're going to get syntax error essentially with your with your for example V 2 and we we use non-blocking assignment and uh and we do not use assign within the always block this assign as a keyword essentially okay so these are some also basics of always blocks so we can actually have as many always blocks as needed so you can add as many as you want but assignment to the same signal in different always block is not allowed for example you cannot um have spal here and also spal here so that's a compiler essentially which doesn't make also sense you want to assignment happens only in one always block I mean to to every single uh signal okay so and also why does an always block remember so we need always block to remember um specifically for memory elements like latches or flipflops so here we are saying that this statement describe what happens to Signal q but what happens when the clock is not Rising so the value of key is preserved meaning that remember so that means basically always block remembers uh the value uh and you don't need to Define it every in all different cases but an always block does not always remember this is an example that for example you have always add sign and these two input as sensitivity in Van data and you're actually defining all different um basically uh combination of the inputs you are saying that if in is one result takes the negation of data else result takes the data so you there is no ambiguity there is no uh no so you're defining all the cases there is not such a case that you don't know what to do so in such cases always does not need to memorize and that's why um when you synthesiz your circuit you don't see latches or flip flops for example in such circuit it's going to be actually your com combinational circuit so that's the way you can actually use always block for combinational circuits and always block defines combinational logic if all outputs are always continuously updated so you need to mention in all the cases so there shouldn't should not be a situation that you don't know you don't know what to do with the output right so when you have latch or when you have flip flop you can say that okay I know I always know what to do when I don't know uh when when I don't have updated value I just keep the current value but in combination of circuit you don't have that option you always need to assign in different values so that's why you need to continuously update meaning that all right hand side signals should be in the sensitivity list all these right hand so these are right hand and also this if so all these things that you are actually relying on their value they all need to come in the sensitivity list of your always and all left hand side signals get assigned in every possible condition of if else and case blocks so it is easy to make mistakes and unintentionally describe describe memorizing elements like latches viado will most likely warn you so make sure you check the warning messages so like VI for example say that when I'm synthesizing I'm using I'm synthesizing using latches for example as a warning if you want latch then good but if you don't want want if you don't want to latch then it means that you have a problem in your always statement and that's that warning can can actually be used in order to fix uh the semantic of your circuit okay so in always block you can actually use a lot of this if else and cases statement so a lot of these uh structure um that you have used a lot in your programming languages you can also use in all these blocks so let's have some fun uh we can actually I'm going to show some circuits and you're going to tell me that if it is sequential or combination let's just start with this one is it sequential or comination and why any thoughts yes um combinational combinational why because it always triggers I guess the start yes that's correct but there we had two conditions yes because always get yes so we fulfill the first requirement which is um we are using always at the start meaning that all right hand signals are in the sensitive list which is good but we are not um assigning out B in all different cases so that's why it's actually a sequence circuit so out a is going to be simple combinational but out B actually is going to be u synthesiz in in a latch in this circuit this one the second one yes that combination why oh no no it's not combination data sorry so no it's it's sequential sequential yeah there is no other real like that's true it's sequential because um the sensitivity list is not complete essentially so we also need to add this enable in the sensitive list or use at a star which is actually using using this at sign star is a good practice whenever you want to define a combination of circuit was that easy good so the always block is not always practical and nice so here for example you want to define a multiplexer so using always um you need to for example have this sensitive list and then say that if Cell result gets a and L's result gets B while you can easily write this multiplexer in assign statement right so you don't have to use always you use always block whenever it makes sense and whenever it helps you but in some cases actually always blocks are quite handy for example when you want to Define case switch cases for example which is very useful in finite State machine that we're going to see very soon okay so in always block we have this if and else but and they can only be used in always blocks and the always block is combinational only if all RS within the block are always assigned to a signal and we we should use the default case to make sure that we do not forget an unimplemented case which may otherwise result in a latch we can also use case X statement to be able to check for don't cares so there are some that makes your basically case um structure easier and faster so you can also summarize Whenever there are some cases that you can actually combine them you can use this case x uh notation okay so let's also quickly take a look at non-blocking and blocking assignments so non-blocking assignments uh this is a notation and the meaning of that is that all assignments are made at the end of the block so whenever you see the evaluation of that assignment takes place but the assignment does not take place until we get to the end of the block so here we say that this is nonblocking assignment a to basically one so we evaluate we know that we want to you know assign or yeah exactly assign one to a but we don't execute until we get to this uh end meaning that this actually here you can see why is important um when we have this B assignment non-bl blocking again to a this actually takes the old value or the current value of the a which is not actually to bit binary 01 because this evaluation has happened but we didn't execute it while in the blocking assignment this actually goes completely sequential so you have this A2 two with binary 01 and then immediately after this blocking you have this value for a and then when you say that b takes a basically B is going to be 2 bit uh 2bit binary 01 make sense so why use non-blocking assignment nonblocking statement always operating on Old values and this enable easy sequential logic uh descriptions so in your actually in your circuit you have a lot of concurrency and that's why we usually want nonblocking assignment non-blocking assignment makes this um a lot of concurrency because all these assignments are kind of concurrent they are not really sequential while in blocking assignment all they are all these assignments are completely sequential because you're going one by one so that's why actually for sequential logic we want to use this non-blocking assignment but blocking statement allow a sequence of operation which is so people that they want to you know use the style that they have from programming languages in the very log they actually tend to use a lot of blocking assignments which is not necessarily a bad thing sometimes actually blocking assignments can help you to write faster codes like faster in uh your designer time code not necessarily in your uh senten siiz code but uh B basically you can use this opportunity but not you should be aware of the tradeoff but this is also important if the sensitive list is correct a block with non-blocking statement will eventually evaluate to the same result at the same block with blocking statements but this may require some additional iterations let's elaborate with this example so we have uh this block and these are the assignment all of them are actually blocking and these are the value for pgs and C out uh these all are initially zero so after executing this um basically always block um sorry if a changes to one so you have a trigger in your sensitive list meaning that you enter this always block and then you're going to evaluate all these statements so you're going to get to these numbers essentially you can convince yourself but essentially every statement you should go one by one and update all these values whenever you execute it while in the non-blocking assignment you consider the same situation that a changes to one p needs to get the value one but this will happen at the end of this G needs to get zero but here is important like this s um reads the old value of P which is still zero because this is non blocking assignment so s going to actually uh get to the value zero and then see out also you can see that it's going to be zero so while at the end of this always um you update values to 1 0 0 0 and then you see that okay now I have assertion on P so I have a change in a p so you need to enter your always block again so that's what I'm talking about iterations so now you have another iterations and you Trigg it again and then you evaluate and then in the end you get the values that you can get by first iteration in your combin in your blocking statements okay okay these are good for exam questions not necessarily but yeah you can't think of it like that okay so rules for Signal assignment we'd like to use always at the whenever we have this um add the positive Edge clock we tend to use non-blocking assignments so whenever you in your you want your defining sequential circuit is better to use non-blocking assignment for many many reasons uh one of them is actually keeping the concurrency another one is also the way that U synthesizing Tool uh behave when they see non-blocking assignments we can also use this uh continuous assignment assigned to model simple combinational logic and for blocking assignment uh we use them only for complicated combinational logic if we need it and we cannot make assignment to the same signal in more than one always block or in a continuous assignment so this is no no like because you cannot assign a in two different alwayss this is also no no you cannot do it like this kind this is actually wrong in many ways because when you want to do this assign uh this a actually needs to be wire in the notation when when you want to assign to a in all this block this a needs to be R so this is fundamentally wrong you know you can in many ways you cannot Define a signal wire and rake essentially okay now let's see any question by the way yes it is not then yeah well uh so the thing is that non-blocking so when your sensitiv leas is correct it's like at sign star nonblocking assignment will eventually actually uh converge to the blocking assignment but this takes it's no if but if it's not if you don't get this Chang to enter the always block again that means you don't need iterations and that means actually your non-blocking assignment and blocking are the same for the from GetGo actually from the the first iteration as well I'm not sure if I understand the question correctly we can discuss offline more yeah any other questions okay now let's quickly see how we can Implement um Finance State machine with verock it's actually one of the nicest thing about verock I really like how to define fsms in verock so you know that each FSM consists of sequential circuit which is State registers and also combinational circuits which one for next state logic and also one for output L essentially in your very code needs you need to Define all these uh blocks let's say this example that we want to divide the clock frequency by three so you um design an FSM for it when you reset you start from this state and then after one clock you go to another state so in this state you keep your uh for example clock one the output is one then after one clock you go to S1 then after another clock you go to S2 and then for the third clock you go go back to the s0 and then you get your output again to one so if you use this one as y as your new clock you can see that the you're actually dividing your clock frequency by three even though we're going to see actually later in timing and verification that this is not a way so you don't need to you you shouldn't mess up with the clock frequency this way this kind of you know this way so there is a actually analog logic in your uh circuits that they actually does these operations uh because because of because since the clock latency is very important we're going to learn about it later but this is just an example uh that you can divide your clock frequency by three like this so now we want to Def implement this FSM U using our basically very log so this is the module name divide by three FSM and these are input clock reset and output q that output Q is going to be your new clock so we know that we have three states so we can code them encode them in two bits so we have this reg one to Z state which going to be your estate registers and also you need next state um as a input to your state essentially we also Define uh three parameters s0 S1 and S2 as these values so this way you are encoding actually your States okay so this is this part is also a bit actually optional you you can actually you don't need to do it but if you do it like this uh and you talk you basically code it as s0o then you can make your code much more better I mean it's more readable so this but is optional so for a state Register is actually so easy you need to write this always at at sign positive edge of clock and positive ede of reset this can be actually positive ede of reset for example here here and then uh if reset you um go to the state s0 else you go to the state which is the next state so you input next state to the state so this part defines the state Register question okay now you need to implement the next state logic so here actually switch case is very handy you say based on case uh case on State if it's s0 next state should be S1 if state is S1 next state is S2 and so on so forth and make sure that you have also this default here is actually very very important because uh we have three states but we are encoding three Estates to two bits so there is a coding one one which can which is not related to any of these Estates so if you don't have this default this can actually run into some issues when you synthesize your code some meta stability or for example some it it might happen that you go to the state one one for no reason and you cannot get out of the state because there is no way but once you have this operation synthesizing to make sure that whenever your state is one one or whatever next state is going to be a zero so this makes your code safe and also the output logic another assign uh that we assign Q to State um so basically Q should be one when whenever we are in the S ser it's the more machine so Q equals to State equal to s z essentially and then we need to put all this together in a code like this this is your module this is your parameters and always for state Register this is the uh combinational always um always circuit sorry always the statement for the next state logic and also this part is for output logic easy right good we can also continue this kind of example uh with our favorite smiling snail example so in that example for example we had this uh four states in a m machine you can Define these parameters and then based on this estate register you can basically uh you you need to assign in always if reset state is s otherwise state is next yeah exactly otherwise um state is next state but now you also need to have always blocked for next state logic so you use this switch case but this also now uh it matters on the number as well so this should be always at Star and then based on the state for example S zero if number meaning that if number is one next state should be S1 otherwise I would next state is is s z so you have if else ifs ifs for all these cases so that's your next logic and for the output logic um we basically our snail smiles when we are in the S3 and the input is one so smile equals to number and state should be s0o which kind of M type of fs and then you need to basically put uh all these codes together in one module and that's all for our smiling snail any question okay so we learn about basic of describing sequential circuits the always statement difference between blocking and non-blocking statement and how to describe fsms in very luck and that brings me to the end of uh 5A so I like to start 5B a little bit just to give you some insight but I'm but definitely we don't have much time so we're going to finish by four so can we switch to 5B very very quickly I just want to prepare your mind for tomorrow e okay thank you that was fast so for timing and verification uh these are the readings uh you can check and also readings for next week um these are reminders for extra credit assignments so what we're going to learn probably tomorrow but I just want to give you some insight is that so timing in combination of circuit we want to learn like how propagation delay and contamination delay what are these different delays what are glitches also we want to learn about timing in sequential circuits how we make sure that our sequential circuit actually works considering all these different delays and also delays in our flip flops so that's why we going to define the setup time and hold time and we determine how fast a circuit can operate and after that we're going to see how we can verify our circuit which is the part for testing uh verification so there are some tradeoffs in our design like for example area uh circuit area is proportional to the cost of device so some sometimes your constraint is area you want to optimize for the area sometimes you want to optimize your uh designed for a speed and throughput so we that's why we want faster and more capable circuits power and energy also another uh important design points mobile devices for example they need to work with a limited power supply and high performance devices dissipate more than 100 Watts um per cm square so that's definitely for example these devices cannot be you know added or implemented on mobile devices for example design time is also another important metric uh which is designers are expensive in time and money so you guys are important are expensive in time and money and the computation will not wait for us so we want to the time to Market is very important and we want to minimize that time to Market as much as possible that's why fjs are very uh exciting for us that they can reduce time to Market and in the end actually all these Traders of depends on the basically for what you are designing if you are designing uh variable devices uh then you probably need to make sure about power so you don't want to put something your ear that's going to consume hundreds of wat for example if you are designing for I don't know for a rocket you have different trade offs and so on so forth so essentially you always need to know your design and your goal and then do your trade out based on that so for circuit timing until now we investigate logical functionality but what about timing how fast is a circuit and how can we make a circuit faster and this is also so interesting what happens if we run a circuit too fast sometimes if you run your circuit too fast then your design may not work a design that is logically correct can still fail because of real world implementation issues and that will bring us to combination of circuit timing that I'm going to actually cover tomorrow but that's what I wanted to basically motivate you about timing that essentially if you don't consider timing Your Design sometimes a correct the functional design that for example you have a correct Tru table and you code it nicely it may not work and we need to take into account a lot of different timings values okay so are there any questions if not then I see you tomorrow tomorrow