 It's the risk five instruction set manual. I think I'll just Peruse this like you do Let's see. I haven't looked at loot and store instructions in a while. Oh I think I've made some horrible mistakes. I'm building a risk five processor not on FPGA Now what does little endian and big endian mean? Well, suppose that I had a value of 1 0 2 0 3 0 4 it's a 32 bit value now Let's suppose I were to take this value and write it into memory now memory is byte oriented so we have a word and Little endian means that we're going to take the least significant byte and put it first So in other words the little end comes first so this is what it's laid out in memory as so that's little endian and big endian would be the opposite where we're taking the Most significant bite and putting it first so the big end comes first 0 3 and 0 4 Now this is the layout in memory. What about the layout in a register? So let's suppose that we were to load in a little endian machine This value into a register. Well, what is the layout of this in memory? Well, it is actually going to be 0 1 0 2 0 3 0 4 and first of all It's extremely convenient because when you start doing shifts and you know logical operations and Arithmetic operations, it's very convenient to have this as a unified 32-bit value If we were to take this and of course stored in a register, we would just get the same thing And if we were to take the register contents and store it into memory You can see that when we store it into a little endian memory We have to shift around the bytes a bit while with big endian you wouldn't actually have to So we know that if we take this little endian value, which is just you know 1 2 3 4 and stick it in a register and shift it by say 24 we expect the result to be 0 1 that should be pretty obvious because we're simply taking this value a 1 0 2 a 3 0 4 and Shifting it by 24 so we get the most significant bite But what happens if we reinterpret this memory as an array of bytes and We get byte zero Well, then we would expect the answer to be four. So the interesting thing is There's a bunch of ways that we can do this we can either simply Let's suppose we have a union for example, and we'll just call it thing and in thing We have a unit 32 and we're just going to call it I and we also have the bytes and We're going to say it's an array of like that So that way if I say that this is a thing Then of course I is going to be the 32-bit value stored in the memory, which is just going to be olex one two three four However in terms of bytes this is going to be an array of four three two and one So in fact by getting B sub zero we're going to get four and of course if it were a big ending in machine This would be the opposite zero one zero two zero three and zero four again The difference is that when you interpret a byte array as a 32-bit value Then the endianness is taken care of for you. So that's why when you get I it's not going to just be 04030201 It's going to actually be the 32-bit value that you expect based on the memory layout So now the question is what happens if we look at a register like a zero in risk and Let's suppose that we slap this on top of a zero well Then things are a little bit different because the compiler knows that Registers aren't laid out as if they were laid out in memory. That just doesn't happen So let's take a look at godbolt.org and prove that So here we are on godbolt.org and I've set things up so that we are compiling using the risk 532 compiler from clang or selang or however you want to talk about it And I've set it up so that it's optimized so that the output is optimized So what I've done is I've written One function called foo which takes a 32-bit value and then simply shifts it by 24 And we expect to get the most significant byte out of that and I've written another function called bar Which also takes a 32-bit value? sticks it in this union and reinterprets it as bytes and we're simply taking the first byte out of that array and What we expect is that if this is a little endian machine We expect the least significant byte to come out of bar And now we're going to call it with 01020304 both functions And if we look at the assembly language output we can see that when we call foo the result Of course is 1 because that's the most significant byte and when we call bar The result is 4 which is the least significant byte And if we look at the generated assembly language for the functions We can see that all we're doing is we're shifting right a 0, which is the input value by 24 and putting that in the output value and For the reinterpretation function what we're doing is we're taking the register and we are ending it with ff So in other words again, we are taking the least significant Value which is 4 So we can see that the compiler knows that Or it seems to know that the layout in the register is you know just from most significant bit to least significant bit Now that does not have to be the case When you build the machine you could if you wanted to Have the registers also be little endian, but then when you do ands you would actually have to reinterpret your little endian data as Big endian and then do the logical or arithmetic operation Which is kind of a pain so of course we're not nobody's going to do that now We're just going to take the register as most significant bit first in other words registers are big endian and Memory is little endian Okay, so what's the horrible mistake that I've made well if we take a look at a At an instruction that we expect our ALU to be able to handle and I'll simply copy the instruction That we saw for shifting right Okay, so basically we expect this to be source Register one and this is going to be source register two in other words These are the two operands and this is the destination register. Okay, so we have our ALU Which is typically represented as this funny shape All right, and the function is going to be shift right logical and Here is source register one so it's going to come from a zero and this is the SR one bus Here is the SR two bus and we're going to put the literal 24 from the instruction into that and the output is going to be placed on the destination Register bus and we're going to write that to a zero so we're going to set up all the inputs and then we are just going to You know let the combinatorial logic happen and then we are going to clock whatever value is in the destination Register bus into the destination register and that's how we do it Likewise, if we look at something like and I a zero comma a zero comma two fifty five Well, now that's no longer interesting because now we're just replacing this with two with And I and we're just replacing this with two fifty five and the same thing actually happens Here is an ad I zero comma zero Z zero zero comma one and of course we know that that is actually going to be x zero so again not as interesting we're simply replacing this with x zero replacing this with one and This is ad I and this again is a zero so so far There's nothing new, you know, this is what our ALU circuit does and we've designed it to do that pretty well So let's take a look at a different instruction store word register a zero into Minus 12 s zero. Okay, so what does this mean? Well, it means that we're supposed to take the s zero register or the contents of it and then we add negative 12 So let's do this and let's do this and We take a zero and This is the address and Here's our memory and here is our data So all we're doing here is we're taking s zero is some pointer to memory somewhere We're subtracting 12 effectively. That's the address in memory and we're going to store that here Here's another instruction Lw that's a load word s zero comma 8 sp Okay, now, of course sp is an alias for some other register So is s zero and a zero of course. They're all x registers somewhere But what this basically does is as you would expect it takes the sp as a pointer to memory Somewhere and we're going to add 8 and we're going to treat that as the address into memory And we are loading so the data Get stored in s zero so far so good There is just a bit of a problem though so let's suppose We treat this as source register one and in fact it is because the layout of The store word and the load word registers Do use this as source register one and of course this is a destination Because we're storing Whoops, I got that backwards. This is a destination because we're storing This is a source because we're This is a destination because we're we are loading into the destination and this is a source because we are Storing the source into the memory. Okay, so store word and load load word Each have format load word has register one and destination register and store word has One source and a second source Okay, well if we were to map that on to our buses, then this is source register one and Well, this is something we don't know what it is. This is source register two Well, okay, where does this come from and What is this and let's take a look at load word Well, we know that this should go on the source register one bus and again, we don't know what this is This is actually the destination register bus. So what is this and what is this? well For here what we could do maybe is say that We're we're using the ALU for this Addition operation, which would force this to be source register two But then that would force this to be the destination register which doesn't make any sense because the destination register is The output from memory. So that's not going to work The same thing over here You know the negative 12 could be on source register two, but unfortunately we're already on source register two So it's almost like we need an extra bus and you know, I'm just going to call this You know bus zero and maybe this is bus zero And then of course we're going to need a second bus over here So all of a sudden You know instead of having source register zero I'm sorry source register one Source register two and destination register buses now all of a sudden we're adding two extra buses And I don't really want to do that first of all Nothing needs to use these buses except for accesses to memory And second of all that would be an additional 64 bits Which I just cannot fit on the interface that I'm using So It seems like we're going to need in our memory card These internal buses. So, you know, here's our memory card Memory card. So, you know, here's our memory chips And we have the address going in here and we're actually going to need an adder so The only function that this thing performs is addition right, so we will have sr1 And then of course the question is well, how do we get this thing in here? Well, this is the offset and we're going to have to figure that out at some point Where does this offset come from? Because again, it can't be on any of the sr1 sr2 or rd buses And the data, of course Well, we're going to have to Switch it, you know between The destination register bus and source register two bus Depending on whether we're doing a store or a load operation So, of course, we're probably going to have to have an operation Bit somewhere in here to tell us whether we're reading or writing So that's what the memory card looks like, but there's an additional complication And it's really bad So the problem is that It's 32 bit user data But it's a byte oriented address Now originally and this is my horrible mistake. I thought that address Zero would be some 32 bit value address one would be Another 32 bit value and address two would be another 32 bit value In other words, the memory was 32 bits wide because well, I thought that we've got 32 bit data words But it turns out that that's not correct because the key phrase is it's a byte oriented address, which means that address zero consists of four bytes So far so good, but the next address is four Because this is address zero address one address two and address three This is address four five six and seven and so on address eight and so on So this is a bit of a problem because now we also have the concept of unaligned memory access And what this simply means is that once you've got a byte oriented address and you want to load 32 bits Are you stuck with just loading from address zero and address four and address eight? Well, what happens if you load from address one? Well, you've got two things either allow it or disallow it If you disallow unaligned memory accesses then Accessing a 32 bit value starting at a non 32 bit aligned address in other words address one two or three Or five six or seven that will actually cause an exception in the processor And that basically means the processor is going to halt because well, you know the processor doesn't know how to deal with unaligned memory accesses So the same thing if you try to access address two or three those are all 32 bit unaligned Now when you allow unaligned memory accesses There are two ways of doing it. You can either do it in software or you can do it in hardware Now in software what that basically means is that any unaligned memory access will cause an exception But there is an exception handler to basically load the aligned address 32 bits throw away the part that you don't need Load the next address Throw away the part that you don't need and combine them all done in a software routine Now the interesting thing about that Is that it has certain consequences in terms of atomicity Whether you can atomically access an address or not because you know, let's suppose you are in that exception routine And you've just read the first address, but you haven't read the second address and then an interrupt happens Well, that interrupt could actually modify this address and then when the interrupt is complete You go back to your exception handler and now all of a sudden you're reading different data In other words, you've failed to atomically read Your unaligned memory access And in fact, uh, you know in the risk five Specification, uh, it it says that unaligned memory accesses are not guaranteed to be atomic. In other words, it's basically up to the machine how it's built So the other way of doing this is in hardware Oh, and I should also say that one of the cons of doing this in software is that well First of all, you've got an exception. So you need to store state Second of all, you've got several software instructions that you need to execute and then you need to restore state So that all takes a lot of time. So unaligned memory accesses are almost by definition slower Well, we want to do things a little bit different. We can do this in hardware Now in hardware what that basically means is Um, you would detect that you're doing an unaligned memory access and then you would Access the bytes that you actually need and then Combine them in the way you need them And it doesn't take any delay whatsoever. And here's how we're going to do that So here we have our memory So again, I'm going to say address zero and there are four bytes here And let's have address four And there are four bytes here. So here zero, one, two, three, four, five, six, seven Now let's suppose we were to do a load word instruction Um, we're going to load Load it into a zero say Or here, let's say x one just For the sake of argument And we're going to let's see The offset is going to be one From x zero. So in other words x zero is always zero So we're going to load a 32 bit word from address one and we're going to store it in x one So if this were the actual contents zero one zero two zero three and zero four Then we would expect x one to get and remember this is a little endian machine So we would expect oh four, oh three, oh two, oh one to get loaded into x one Again, because this is a little endian machine zero one is the least significant byte So what do we want to put on The destination register, right? This is going to be the destination register so If this is the destination register rd from Bit 31 to bit zero and we're going to divide it into the four bytes that we want Well, we want Let's see one to go into here two to go into here Three to go into here and four to go into here So the way we're going to do that is like this We're going to have source register one Going into our dedicated adder and this is the offset That's what this number over here is So load word and store word both take a source register and an offset And what we're also going to do We're going to treat this as address And we're also going to take the address and four And we're going to call this next So now we have address one And if we add four we have address five Uh, however, what we're going to do is we are also going to take The address only from 31 Down to Two in other words, we're going to skip The bottom two bits Okay, so now in other words, uh We can say zero out The bottom two bits So this would be zero and then next would be four right because we've got zero plus four So if we were accessing If sr one were say zero and the offset were zero then this would simply be zero and four if sr one Let's just ignore the offset if sr one were one Then of course Zeroing out the bottom two bits makes this address again zero and this is four same thing with two and three But then when sr one is four then this address would be four and the next address would be eight So really what this is are what what address and next are Are 32 bit aligned addresses Okay So these are the 32 bit aligned Addresses And of course what we could do is we can simply you know take the lower Two bits and you know that would be kind of an offset from The the aligned address So in other words, uh in this example load word From address one This address over here would be zero This address over here would be four and the offset would be one now The advantage of doing it this way is that if we layout in hardware our memory in terms of separate Eight bit chips in other words one byte chips Uh, then what we could do Is we could have the address Go into here And again, these are 32 bit aligned address addresses and this one's address is next So, um, again, this isn't actually zero and four. This is you know, because these are What 20 no, uh, 30 bit addresses right 30 bit addresses in terms of 30 bit address space address would be zero and next would be one So, you know, I guess we could have this adder be a 30 a 30 bit adder and change this to one You know, that's another way of doing it So in other words, this address will be zero zero zero and one Okay, and then the data So, uh, let's see The data is just going to be Like this So This is going to go here. This is going to go here. This is going to go here and this is going to go here Okay, now that's that's an example of the unaligned, uh, address Access now what happens if this were unaligned access? Well, um, in that case, uh, the offset here would be zero Um, this would be zero and this would be one again, except that in this case We would want our chips To have the address Over here address and address So this would be zero zero zero zero and then To load that onto our destination bus, we would simply copy the bytes like this So what we need is a way of telling what addresses to put into the memory chips and how to shuffle around the bytes And that pattern is based on strictly the offset, right? This is offset zero This is offset one and offsets two and three would have You know comparable things where offset two would have this be next And then well the shuffling is going to be completely different. Let's see what it let's see what it actually is So let's say this is offset two And this is next Right, so, um, you know in terms of bytes, this is memory address two This is memory address three. This is memory address four and this is memory address five So in that case we want to put, um, again, this is little ending, right? So we want to put this here Right this here The next one is here and the next one is here. So that's offset two So that's what that pattern looks like and then for offset three This is going to be next So this is address six And then the pattern is going to look like this again, this is little endian So three goes down here four five and six so you can see that Uh, based on the the four different offsets We have four different patterns in terms of the addresses that we give to the memory chips and the Shuffling that we do in the bytes So that's basically it so To summarize We have sr one going into a dedicated adder, which will add the offset which can be both positive and negative We have an offset One to zero We have an address Which is now A 30 bit address So i'm just going to say 31 to 2 with the understanding that this is a 30 bit address And we will add one And call that next So what we need is an adder and basically an incrementer because this actually doesn't do anything So instead of making this a An adder i'm just going to call it increment So we need an adder circuit and an increment circuit We also need some sort of a shuffler so So what are we going to have we're going to have these four Things and We're going to need some sort of a multiplexer To multiplex the addresses Right, so we have address here and Next here and Depending on the offset we'll switch between one or the other so these are the memory addresses Now here's the data data data data data And here is um rd And we're going to need some sort of a shuffler circuit So i'm just going to call it you know shuffler at this point Shuffler and of course you feed it the offset Okay, so that's load So that's a store now in terms of No, that's load now in terms of store In terms of store You get the data to put into the memory from rs2 So it's going to be something like this actually So here's the memory data Here's the memory address And here is the memory So that's basically what our memory circuit is going to look like So in summary, it's a little more complicated than I thought it would be Because again It's not 32-bit word addresses the addresses are byte oriented byte oriented addresses So that was my big mistake It makes the memory circuit a lot more complicated But we decided to do unaligned memory accesses in hardware Which is nice because it means that we can accomplish Unaligned memory accesses in a single cycle, which is nice to preserve atomicity So I can actually make the strong statement that my memory accesses are atomic Regardless of whether they're aligned or unaligned, which is great. I think it's great. Don't you? all right Let's see. What else do we have to talk about? Well, uh, this addition Is not a generic alu all it does is add now if you will recall Our alu we used four-bit slices So we had you know x and we had y And they were four bits wide the output was four There was a carry in and we also had propagate and generate and Again, you might want to review That video where I talk about the alu propagate generate carry in And on the top we had a carry look ahead unit carry look ahead unit where all the propagates and generates fed into and We were able to create all the carry ins for each of the bit slices Now how many bit slices are there? Well, there are eight of them So this is bit slice zero. This is bit slice one bit slice two bit slice three and so on And of course, uh, this is for addition and subtraction. Uh, we were also able to to Based on the function do other things such as you know bitwise operations Comparisons that sort of thing But this is this is your basic adder. There was also a function that went into here and I think it was I don't remember how how many functions there were functions I think there might have been like three bits of function or something So in other words, this isn't 256 anymore. This isn't 16 bits anymore Here's the function. So again, this is for a generic alu which can perform multiple functions Yeah, and there were three bits here. I think Or possibly four because I think there was like a Oh, yeah, there was a there was a shift thing going on here. So I think this was also for I may be wrong But in any case, so how many bits is this? This is 12 bits 12 bits In by well actually, sorry, it's 13 bits, isn't it? 13 bits in by Four five six bits out and this well again, there's a carry in so we have Uh eight and eight is 16 plus four is 20 plus one is 21 bits By 10 So 13 bits right two to the 13 is 8k by six, which is you know reasonable But 21 bits is I think two megs by 16, which is probably not that reasonable You have to multiply that by four. So we would have four of these chips As opposed to eight of those chips So I believe that we settled on this simple 8k by eight Chip rather than a two meg by 16 chip Now That is for the generic alu We don't need a generic alu I wish I could like erase whole sections, but apparently I can't Now this adder Doesn't have to have this function because All it needs to do is add which means that we can have eight inputs and a carry input and basically that is 17 bits Which is reasonable um, it is if I'm doing my math very quickly 128k and this is eight and propagate and generate So by 16 That's I think kind of more reasonable. So It's nice because uh, you know, no, I only need four of these and then of course there's a carry look ahead unit up above So there's two there's three there's four the carry lookaheads generate the carries for these dudes Propagate and generate go up here We don't need propagate and generate from here and we don't need to carry out on any of these because of course Risk five doesn't use carry outs So basically this is two this is two and this is two two two two and we need one one one out So this is how many bits? six bits by three So, you know, basically this is a 64 by you know four memory. It's really simple Okay So That is what this adder looks like now the incrementer is even simpler because We don't need the second operand because the operand is always going to be one So we could in theory just do this We can have 16 bits in Don't need to carry in bit And uh, let's see we do need I guess the carry actually we don't need a carry lookahead unit I don't think because we can feed the carry out directly into the carry in of this Uh, so this is 16 bits in 16 bits In by and of course we have 16 out So by 17 and this would be 16 bits By 16 so that's a little unfortunate because you know We would have to go to the next step up which would be another 16, but Maybe we could finesse it by having The first chip just be 16 16 And the second chip just be 16 and all it does is it generates the carry So this would be a 64 k by 16 chip. This would be a 64 k by one chip And this would be well, there's an input here. There's 16 here. There's 16 out So this would be a 128 k by 16 chip. So that's what the incrementer is So there's the adder unit and there's the Incrementary unit. Okay. So, um, that's how you would implement the adder and the Incrementer that of course there's the multiplexer that we need to talk about Let's uh, let's see. What would a multiplexer look like? What would a 16 bit multi a 32 bit multiplexer look like? Well, it certainly wouldn't look like a single chip because they don't really make those Or if they do they're probably in a bga package and I don't really do bga Although it's something I should look into So what we want to do Is have a one bit input and you know, we'll just call this I don't know a And we'll call this b. These are all 32 bits And we have 32 bits going in So typically what you know, I like to do is implement them using buffers and we can certainly do that like this So there's a and there's b. These are tri-state buffers And these are just connected together and that's your multiplexer So this is a 32 bit Tri-state buffer And of course, uh, only one buffer is active at a time And if they are both active at the same time, then it is so brief that it doesn't really matter that much And this goes into memory So now of course we have four of these multiplexers one for each memory chip Memory memory Uh, so basically we need some kind of a unit that takes in our two bit offset and Outputs four bits one for each of the multiplexers And this is probably going to be a simple combinatorial chip So Well, let's take a look at what it's going to be right. Let's just call this You know m zero m one m two and m three and this is you know offset I don't know. We'll call it f F one f zero. So that's your offset. So it could be zero one two or three So here's f here's m zero m one m two and m three and let's see what these are supposed to be zero one two and three Okay, and we'll say that uh, you know, these are going to be zero equals that address thing the aligned address and one equals the next aligned address Okay, so if the offset is zero, then of course we want that Uh, if the offset is one, then we want this if the offset is two Then we want this and if the offset is three, then we want that Which is interesting because well, we've just realized that we don't need a multiplexer for the very last memory thing. So we can change this to three And we can remove that and remove that final column Okay, so um, basically this is our lookup table And uh, let's just have some fun. Uh, let's Change this to f one f zero. So this is zero zero. This is zero one. This is one zero and one one Well, this is obviously F one or f zero This is obviously just f one and this is f one and f zero. So that's that's pretty simple. You know, it's one gate No gates and one gate. So that's pretty neat. So that's how our multiplexer now. What about our shuffler? Oh boy, the shuffler is going to be a lot more complex So here is uh, our memory Layout mem mem Mem and of course one of the shufflings for offset zero is simply straight through Another shuffling So this is offset zero. This is offset one here. Let's just do this. There's our memory And there's our result And for offset one basically, uh, let's see. This is the least significant So it goes like this and then like this and then like this and then like this Okay, so first of all the question is, uh, how are we going to do that because it kind of sort of looks like, um, we will need again a multiplexer And this time it's an eight bit multiplexer and we have four inputs one from each memory chip So that means that we have to select one of four and the output would be eight So what does that look like? Well, you know, again, we can just, you know, make it look like tri-state buffers like this One two three four and these all just go together and these Are basically the decodes Of a two to four decoder And we need four of those So that's what a shuffling unit would be And of course this offset isn't So this would be Actually, no, that's not quite correct. This this would be a lookup table Because again, uh, you know, we depending on the offset we need to change these, uh, buffers to Shuffle the the bytes around properly. So anyway, uh, that is how we would do that I'm not going to go through the exercise of calculating the lookup tables. Um, and determining, you know, which multiplexers we don't need I suspect that we're going to need them all Um, this is times four These are all eight bit tri-state buffers. So, uh, and there are four of them per per byte So we would need 16 of them Which is a little unfortunate. That's, you know, a lot of chips But I think this memory circuit is going to just require a lot of chips and that's all there is to it So And then the question is well, there's reading versus writing Which I haven't fully thought out yet Um, because again, we need to apply this shuffling except in the reverse direction Um, so it would be sort of like this So these would actually be bi-directional buffers And you know, this would be for reading and you know, the opposite would be for writing Well, the opposite. I mean that if this one is active for reading, then this one is active for writing. So Um, that's how basically that would work. So You know, so now basically all that's left is to actually do the work of, you know selecting the chips and you know, deciding what the signals should be um, and then there's also that, uh, unfortunate consequence of The offset not being able to fit on any bus And now we sort of need to Put that on the bus Oh, the other thing that I wanted to talk about is that there's not only lw, but there's also a load half word And there's also load byte Uh, and what that does is, you know, if this is memory And let's suppose we're loading an unaligned address Uh, well, what load word does is it takes this, this, this, and then of course the next address and it combines them What load half word does is it only takes two of these and what load byte does is it only takes one of these So we're also going to have to have some adjustments to this circuit um, or will we because Even with load byte, even if we load all four And shuffle things around well the byte that we want is always going to be down here And the half word that we want is always going to be down here So again because we're doing this in one cycle We don't really care about the fact that we're reading these two memory addresses and then not doing anything with it So what load half word would do, uh, there's also a load half word unsigned and a load byte unsigned And what load half word does is it sign extends And load byte what this does is it zero extends So we could add some circuitry here to either zero extend or sign extend So in other words, uh, you know, if we were doing a load half word unsigned Then we would just fill these with zeros If we were doing a load high with sign extend, then these would be either zeros or all ones depending on the high bit over here Um, so, you know, we could sort of have an adjustment circuit maybe over here. I don't know I don't know. I'm just guessing so, you know, we need to know whether it's signed or or zero extended Or you know or nothing, you know, if we're just loading a word Um, we need to know whether it's a word or a half word or a byte Uh, we need to know the offset, which I believe is 12 bits. I'm not sure but it's it's signed So there's a lot of things that we have to think about Um, the other thing is that in our register card we had, uh, these, um, you know What was it? low low Something load low high high low and high high so that we could, you know, decide to um Decide to access any bytes we wanted. Well, in fact, I don't think we're actually going to need these because Load word load high and load byte the results are always 32 bits because again, these are sign extended and zero extended So I'm not sure that we need those four signals So we could save those four signals and use them for this and I know we've got a bunch of no connects Leftover so we might just be able to stuff this in So we'll see anyway. I think that's probably about it for this video I hope you enjoyed it and I hope you're kind of getting a sense of How difficult this whole thing is and sometimes I'm just sort of like throwing my hands in the air and saying This is way too complicated. Why did I even start this? So um, yeah It's a big complicated project. Uh, so Maybe that's why that I haven't been putting out a lot of videos recently Uh, because it's just so overwhelming But you know, as you can see, it's not so much overwhelming as just Large the individual issues themselves aren't so bad It's just that the work after planning is Just a lot of work not complex, but just a lot Uh, I think in the next video um For the elmar series, I'm going to talk about the tester Which is a little testing card which I can put Into the back plane and inject and read signals on the bus to make sure that all the other cards work And I'll talk about the design of that I know I've already talked about it a little bit on one of the live streams, but I don't think I you know really completed any thoughts um And now I think I have completed the whole idea and again It's just a question of actually putting it together in an actual printed circuit board. So I guess until then I'm building a risk five processor Not on an FPGA