 My nice new brother WP1 word processor. I could connect the Raspberry Pi up to the UART. Sadly, this turns out not to be viable. This is a very cheap Psoc 5 development board and Wire that up. We're gonna write this in Verilog by returning 5a, which is the right value It's kind of vile, but it does seem to at least build. Nope. It doesn't like that and We are out of space. So let's run the program and they should produce 1, 2. 1, 2 it is. We now have Nearly all of the Verilog stuff working and then next time I'm gonna work on the actual software side of things Okay, it is the next day. I am reasonably refreshed Let's do the software side of things Now we have two Registers effectively. We've got this of course. We've got the status and control registers Index zero is going to be the data register. So when the brother Right to this it's going to be sending a byte and when it reads from this it's going to be receiving a byte Register one is going to be the control register When the brother writes Thank You windows when brother writes to this it's going to be sending Information to the interface about what it's doing when it reads from this is going to be fetching information from the interface now one thing you may have noticed is That there is no way To what I put the schematic There is no way for the bus interface To tell the CPU in the interface When something happens the interface is just going to have to poll This is by design as it simplifies things no end Normal you are if you write to the data register This triggers a right in the interface Because of course the interface knows when it's being written to but the CPU here doesn't so we're going to have to interlock everything through control bits Now We are going to have two state machines for doing the reads and the writes so that's Prepare for this so this is going to be Read state machine. This is for the brother to be reading stuff from the uod we have The idle state This is when there is No data in the register waiting to be read and nothing available from the uod Readable is when there is data in the buffer waiting to be read done is when The data has been read So the flow is that the interface starts in idle a Bite arrives in the uod The interface puts the data in the buffer and transitions to readable The brother then reads the data out of the buffer It then signals to the interface that it's done the read at which point interface Transitions to done at which point the Brother has to signal the interface that it's acknowledged that the read is done So there are actually two steps here of to read the brother has to Wait until the interface is in the readable state. It then reads the data It acknowledges this so the interface goes to done and then the brother acknowledges it again So that it can transition from done back to either idle or readable the reason for doing two acknowledgments is That The brother Can otherwise not distinguish between a transition from the readable state Back to the readable state It doesn't know that another bite is available Because when the brother sets the acknowledge bits that we're about to do To tell the interface it's done the read. It doesn't know when the interface actually handles The handles those bits Hopefully that makes sense. I suspect it may not anyway, let's do the acknowledgement bits so read acknowledgement we have We are acknowledging that data has been read from the buffer and Ra done Signifies that the brother has seen that the interface is in the RS done state Okay, let's go for writing So we have a right state idle This is going to be When there is nothing in the buffer and we're waiting for the brother to put something there Actually, let's call that writable this indicates that the data has been picked up out of the buffer and Is currently being sent? And I think that's actually all we need because writing is simpler so acknowledge bits We have Um, we don't know we do actually need AWS done because again We need to be able to transition So the board writes the buffer It sends a WA data acknowledgement bit the interface transitions to writing Yes, we need another acknowledgement bit to force the To force the brother to wait For it to be in a state other than writable so it can transition back to writable and wait for the next byte so Yeah, let's let's just do it like this Okay, so the acknowledgement bits will be placed in the status register by the brother the Enumeration Values Actually, we'll start put that up for that way that These occupy different bit fields and can be just ordered together. So this is zero one and two This is four five and six Okay, let's just make a quick schematic change so The brother is going to be Sending acknowledgement bits to the interface and these will arrive here in status reg one Now we want the status we want the acknowledge bits to all be independent Currently the value of the register will be captured into the status register directly However, we can set this to sticky sticky bits Work especially When a sticky bit is seen as being one It sets the value in the status register to one when it's seen as a zero it doesn't change the value So the status register will now remember any bits that have been set to one then they all get read and reset atomically Which is nice that is exactly what we want for the status bits because it means that the brother can set Any of these bits one at a time and they will all get accumulated and ordered together Okay, I think that's fine for the For the state machine so we now actually have to start doing it. Oh, yeah, we also need to define some variables to actually put the state in so Start in this we start the read state machine in idle We start the right state machine in Rightable, okay So we get we loop forever and The first thing we want to do is to read and reset the acknowledgement bits We now going to process The read state machine so we are in idle mode If there are any pending bytes in the UART, how do we actually do this? I'm gonna have to look at the documentation for that One nice thing about this SDK is that every component has a data sheet button Which takes us to the description of the data sheet So you are the APIs now you are to get char receives next data element from receive Buffer Zero indicates an error occurred or no data is present That's not what we want because we want this thing to be a bit clean Get bite seems to be slightly different We are now we do need to make sure the RX software buffer is enabled but otherwise We get the data in the bottom eight bits and one of these things in the upper bits Okay, so let's make sure we have the buffer enabled Is that this? I think so software buffer Setting RX or TX size greater than the FIFO depth name was usage of the RX and TX FIFO and a circular buffer Okay, we may have to call a function to enable this is there a set RX buffer size I think that might just be for SPI actually Okay, I couldn't find anything off hand, but it occurs to me. There is actually a very easy way around this so We know that the the UART is going to be writable if the TX buffer size is zero It's a little bit wasteful because we want to keep the buffer full when it's As often as possible because that will Mean that the UART will be writing stuff in the background, but this should work so if data has arrived No, that's wrong. Yeah, the thing is that The acknowledgement bit will be read exactly once So that if the buffer is full then we consume the acknowledgement bit so in fact We want to consume the acknowledgement bit and go straight into writing Writing is then going to wait for the transmit buffer to empty and Then it is going to transition Well, it's going to So we read the byte from the register and then we send it to the UART Which we'd know is going to be non-blocking because the buffer is empty And then we transition into done and then in done We wait until We see the acknowledge bit and then transition back to writable Okay, so the brother is going to write the data Into the data register set the WA data acknowledge bit The interface will then transition to writing Then transition to done The brother then waits until it sees the done state And then acknowledges that and it transitions back to writable waiting for the next byte Yikes, okay Actually, that is also not my copyright message. Let's remove that. Why do we need to comment saying it's the end of the file? Okay, I think that is It so now we want to go back to the workbench and Actually try it I think Yeah Okay, so let's program it Done yep over to the workbench Okay, here we are at the workbench and an amazing video editing tour de force I have both the Output from the brother and also the serial terminal output captured I hope from my little laptop, so we should be able to see everything and in the middle I Have a cheat sheet with the various Bit values on it so Here we are in BBC basic. We should be able to print the value of the status register and We get for Thus indicating that we are in write state writable and Read state idle which is exactly What we expect to see so let's try and write a byte to do this We need to write a byte to Port 40 and I realized I now I can't remember the syntax how to do this equals 40 65 rather comma 65 Okay, so we've written a byte we now need to transition we now need to acknowledge that we've done this by doing put 41 comma W a data is for and Nothing has happened So I'd expect to see the byte show up in the In the serial terminal So what state are we in? We are back in writable. Okay, it thinks it's done something Hmm So I wonder what has happened We can't capture from manual testing like this. We can't capture the actual All the states one thing I can try is putting the cursor in the serial terminal and typing something Just one key and let's see if it's transitioned to the readable state it has So now we should be able to read the byte Which was a 6b so if I print that That is indeed the character I typed We now want to Acknowledge that we've read it should now have transitioned into it is still in readable It should have moved on to done Okay So what we can see from this is that a lot of it is working But there's something wrong with the state machine and of course, you know what this means Back to the desktop Okay, let's see what's going on here now we tried the right state We tried to we wrote a byte to reg zero and then we Wrote a for which is one shifted left to This should be one two four eight hmm, I Wonder if something we're doing is dropping all the acknowledge bits that would make sense actually Let's just double-check this so we put this into sticky. Let me just double-check what sticky does Goes high on the writing as of clock goes low after the status register is read This mode is associated rooting at a sample neat cycle and status of other status control clock If the signal is high Just captured and say spitter remains high When the CPU firmware into status register the bit is cleared So if we're in so we should be in writable We set the acknowledge bit This means that it will show up in this loop precisely once and it should hit this and switch states Once we're in writing We are then attempting to actually send the bite at which point we switch to the done state Okay, well we can put some debugging in Okay Now what happened here? We read the bite and it transit transitioned to readable But then we either Never saw it transitioned done or it went to done and then back through idle to readable again So again, let's add some Tracing the thing I'm worried about is If we were to read one of the acknowledge bit if we could read the acknowledge status register When we're in the wrong state We will lose the bits So let us program this and back to the workbench Okay, it's programmed so Let's read the Status register state for we're waiting for write data So let us give it what it wants give it some data Acknowledge that we've done the data and indeed We see nothing show up on the serial terminal So it has not switch states Interesting, let's try typing something we're going with our K again Right it transitioned from idle to readable we can now Read our bite and we acknowledge it with sending it to one and Nothing happened, okay. I think all our acknowledge bits are being dropped, which is interesting Okay, so That is happening through this logic Now I spent a lot of time fiddling with this so it's entirely possible. It's wrong the way this is supposed to work is The decoded wire indicates whether A io transaction at the right register is happening Every clock cycle We look to see if we are now decoded, but weren't By recording the old state of decoded in this reg this means that this will only ever trigger on Positive edges of decoded Then we say is this is a right transaction if so actually copy the data to the output reg and the outputs are wired to the status registers It also occurs to me That because reg one here is sticky and Reg nought is not reg one is taking care of remembering the result So I think that we don't want output one here to be registered I mean nothing looks too bad about this code. I wonder if it's possible for the status register To sample the result I think only in sticky mode we could implement our own latch But that's basically just doing what reg does Yeah, that's not gonna work The reason why is output one here being registered will retain its value and keep asserting it so After we read the value from the status register Then the value gets reset back to zero But because output one is still asserting the old value it will immediately get the acknowledge bit set again So in fact we can't do it like that so we're going to have to Be a little bit different We're going to need to add a another output terminal do we See, I'm I'm wondering if we if we need to add Output enable lines for output zero and output one So that this now becomes data right output enable and each of these gets its own then Output zero goes through a latch And I think we have some you've got a bunch of flip flops here. I Think we want to D Nate pit wide D flip flop with enable bit So that when the enable bit is set It will capture the value coming in on D and emit it and Q so the status register is now pointing at Q Enable becomes the output enable line and clock is a clock Okay Generate the vera log Yes We then need to update some stuff. Of course, that's removed the regs from my outputs, but I wanted to remove anyway Data read oh II is Decoded an RD So output zero can we do this in combinatorial logic? Output wait a minute the outputs are always going to be the data lines Like always So we don't actually need these The only thing we care about is data are here. So if index is zero we want to enable Output naught enable otherwise we enable Output one so if this is a leading edge Set one of the So if this is a leading edge and we're doing a right Enable one of the OE lines otherwise clear them in Fact can we do it like this? Don't think we can These do need to be a Registered no, they don't sign Output what output enable Becomes If we are writing and index is false comes one Otherwise zero Okay, that is actually much simpler code. I Don't know if it'll work, but We also want to save our symbol go down to the schematic and Do some work? so Break that line Output zero needs to be sticky Well, not sticky, but it needs to remember the value that we programmed into it So that means it's got to go through the flip-flop Output enable goes to the Flip-flops enable line the Data line is connected to the data in oh, yeah, and we also want The clock to be a clock Right, what do we do here? Well This one is our sticky one so we connect up the input We however do not want a clock there. We want a and gate and This is only going to be So that this will only get clocked When output one output enable is set Does that build? routing of asynchronous signal Microsoft Hues a clock to UDP component What? These error messages really 582 Bet that's this one No, this one This one We don't need a clock here or an AND gate because we're going to use the output one as a clock Well, we do however need to synchronize it with the system clock Which we use one of these for so that we get a pulse out here and this will force it to be in the right clock domain for this thing and Let's Do that. Hey, how are we doing for resource usages usage? Yeah, this has dropped a lot. We went from 50 down to 36 However, the sync thing here uses up a status register Which is why this has gone up to three Okay That's programmed. Is that programmed? Programmed now Let's see if this works Okay, I added some more tracing just to log the Acknowledge bits whenever they are non-zero should we so we should be able to see the Act bits actually show up And they do not so I think that the My status registers are not working. So that would be a job for the bus interface, I think Okay, let's do some debugging the proper way to debug this is with a logic analyzer, but That would require even more video capture stuff. So let's try using the LED first because there's an LED It's on port 1.6 It's very simple if it's if the port is energized the LED goes on So let's add a Let's add a digital output Pin will it LED strong drive is what we want Pins map this to port 4.1 We've got wait a minute. That's the Port one point four wait put one point six. I'm going mad put one point six here we go and We are going to Create a toggle flip-flop which are going to wire up to this copy the clock and connect this to our register one Output enable that means every time the output enable goes high it will toggle the state of the LED Then should let us see whether you know the output enable is actually working and Tell us whether our problem is in the bus interface here or Whether the status register is not working the way I expected Let's look at the Yep, we're in the right We are in the right mode Let's try and switch to another mode by acknowledging read and Nothing happens Fantastic. We are stuck in mode for let's try acknowledging data Yep, that's not doing anything at all Typing in the serial terminal Still switches us to readable and I bet this has gone to state five Yeah But if we Try it if we acknowledge the read with RA data We see nothing happen Okay, I think our acknowledge bits are just not making it through for some reason So why is the question? So we know that decoding works I mean, you know the index works because otherwise we wouldn't be able to read bytes And we actually saw all this working before and admittedly that was before I rewrote everything So I bet it's this stuff This is the thing that's doing the There's testing for a pos edge on the right signal So let's add I'll put terminal Let's add another output term which we're gonna call debug except not in capitals bug Oh, yeah generate verilog Yes There's our debug and we're going to sign To CPU write pos edge In our schematic We are going to connect up debug to a flip-flop So the LED should change state every time debug Goes high Which should happen on every pos edge so program Okay, that is not it that is in fact a power LED the user LED is here And is actually labeled port 1.6 so we Want to output To port 41 a1 what happens Nothing Okay, our bus interface is faulty Well the LED works I have also wired it up to The decoded line so that every time the Something accesses ports 40 or 41 then then nothing happens interesting Interesting why did writing a zero Do nothing Now it is doing something That is interesting that suggests that this is sometimes not decoding properly Either that or the flip-flops not working Let's just Program so that we can do run Well, it's didn't flip then Yeah Okay, I think something is wrong with the bus interface it's not Capturing values correctly But why After a lot of tinkering I think I have something working so let's give it a proper test So if I run my program which writes zero to the act bits. I can see light toggle on and off Which indicates that the output enable is working. So let's try and do that right again So what we need to do is write our bite to Actually before we do anything. Let's just make sure that we're in the right Date that should be a four. It's a six. What does six mean? Six means that the read state is done. It thinks it's read a bite Into the buffer. Okay, that's fine. That's four plus two six So, let's just go ahead with the right Oops so right 65 into the output buffer and we want to set the data ac bit and we can see that it has The the ac bits logging in the serial terminal means it's actually fetched the My app bit assignments are all overlapping Because WS writable is four and Ws done is six but four plus two is six So RS done and WS writable Produce six, which is WS done. I'm going to have to fix that Okay. Well, that was really stupid I'd use zero one and two and four five and six So I'd started the writable bits at four rather than starting them at bit At the bit representing four so the real value should be zero four eight And I've also changed the code and done the reprogramming to match Okay, let's try our right again So we write our byte to the output port then we signify that we are That we want to actually write it by using ac bit four And yes, you can see on the terminal a Transition from writable to writing Then it printed the a and then Transition from writing to done which is correct. So if I read the state We're now at state eight, which is WS done that is completely correct So we now write the ac bit to tell it that we've seen the done which is eight and It transitions back to writable waiting for the next character fantastic. Okay, so now let's type it a letter on the keyboard Of the terminal that is so it's gone from RS idle to RS readable So we can read the data buffer Which is 107 that's the lowercase k I can prove that like so We then need to acknowledge that we've read it by You sending ac bit one. Let's use the right character Yep, and it's transitioned from readable to done and then we acknowledge that we have seen the the Done by sending ac bit two and it transitions back to idle which is correct. I think this might work Fantastic, okay So I think I will call it for that session I will remove the tracing the next step is to actually write some back-end code to Do something more useful than So back-end code writes some code for the board the brother machine To do something more useful than me having to poke it with dbc basic I'm going to do a very simple terminal emulator Then we will see what happens Actually, I completely forgot to explain what I did to fix it Which is I simplified things even more by removing the clock dependency So it's now all completely a synchronous logic. In fact, I can probably take the clock out now and In order to Treats in order to handle the leading edge of right bus operations correctly. I've added these edge detectors What these are attached to the output enable lines and they take care of generating a single pulse Whenever the output enable line goes high, so we end up sampling the data bus here and Here Only when the bus transaction actually starts so none of that is happening inside the the very log stuff and it's It's added a couple of macro cells one for each edge detector but we've dramatically Simplified the number of p terms So I will just do one more test offline to make sure that I didn't break anything and moving the tracing and Then next time we'll come back with some z80 machine code