 Let's do some more work on my nice new brother WP1 word processor. I have a port of CPM to this machine and it boots my original plan for this thing was to use it as a Terminal for a Raspberry Pi. I could connect the Raspberry Pi up to the UART Blowing to the processor here. Sadly, this turns out not to be viable This is a very cheap Psoc 5 development board It's got a mini FPGA allowing you to wire up arbitrary logic to any of the ioports this wonderful cable and That should hopefully be all the hardware Modifications I need the next chunk of work isn't going to be happening on the workbench because I need to go and pull up The Cyprus development kit see you on the desktop so what you're looking at here is The Cyprus or rather now in Phineon since in Phineon bought Cyprus Psoc integrator development system. This is a frustrating combination of being brilliant and Being maddeningly stupid, but I will just create a new project The board we're using is the CYHC kit 049 So that's fine. We want an empty project and we're going to call this Pdaptor and put it in Psoc And you want the project name inside the workspace to be Pdaptor Okay, and that has created a new empty project We should be able to immediately build it and I will explain what this is doing later This is can actually Constructing the vera log which it's then compiling into the bit stream to program the FPGA. There we go. It's done so program and It has programmed the board. I have the board hooked up via a entertainingly ludicrous collection of USB extension cables To the desktop PC you're looking at now. I've got both the Debugger port plugged in which is what this programmed it with and a serial terminal connected to the board itself Okay, so First step you want to get the serial terminal working. So what we do is We go look through the set of components That the thing supports and we find a UART Which we drop down here onto the schematic. This is where we'll be designing the FPGA logic Note I keep saying FPGA. It's not technically an FPGA. It is something else beginning with a C whose acronym I can never remember because it sounds far too like Java mid P systems So I'm just going to call it an FPGA It's functionally very similar except smaller and a bit weirder anyway this Represents a UART Compiled into our system. We can double-click it and get Various bits of configuration. It doesn't have any inputs or outputs because the way this is set up by default It's controlled entirely by software, which is what we want. So we're going to rename that to UART Because we're only going to have one of them and you notice that even though it's set to a hundred and fifteen point two killerboard the there's a warning here that the actual board rate is Not right. This is because the clock rate at which the thing runs doesn't allow the The UART to generate the appropriate board rate accurately enough. So we need to fix that So we go over here. That's the wrong one to clocks This shows all the clocks used on the system We have the standard ones here in yellow and one extra clock down here that was created by the UART so Yeah, the the clock used by the UART here you can see it wants 1.382 megahertz, but it only got 1.412 Because it's limited to a set of dividers Based on the system clock. So let's change the system clock. Do that. We double click here This now shows us the Clock tree. This is how all the various clocks are generated The this particular board The clock is generated from this thing here called an imo Presumably that stands for something something oscillator It's not particularly accurate. You can see here plus or minus 2% On the more expensive board Because it's got usb on it. It needs an accurate 48 megahertz clock for the usb But this one doesn't so this is what we get And by default it runs at 24 megahertz. So let's fire up windows calculator This is our clock rate now. We're going to keep doubling it Until we get a number in about the range we want So it's 29 megahertz 58.9 that's too high. This thing only goes up to 48 It's the other board that goes up to 80. So let's try 29.491 Okay Now we can see here that These clocks now match much more accurately So if you go back to the schematic I want 115.2. It gets 115.1. That is good enough Okay So now let us just build it This is going to generate the code for the urt which Uh, it looks like it's already done it, which you can actually see here in the ide Uh, we're not going to touch any of this but we need to build it to generate the source code to do the next bit Which is to actually like call things so Because we've added a uart component we need to initialize it Like so and then here we can put in our code So we want this is why I wanted the ide to know about the uart device Uartput string Hello world Okay So build again done Program And here is the output through the serial terminal Excellent That shows that our system actually works now Uh, there's a thing here called the resource meter that shows What's what resources are actually in use? And you can see that we've used one out of two serial blocks These are dedicated components for doing serial stuff We can build a uart from actual logic. In fact, there's got this one here. This is a simple Transmit only uart intended for debugging Uh, if we were to build this Uh, it will then generate this in verilog Compile it to the bitstream Then compile all the source code again Which takes a while there we go And here in the resource meter we can see that We are still only using one serial block but We That's interesting I would expected it to use some logic blocks Okay, uh, I reckon that what it's probably done is notice that i'm not referring to this anywhere and has optimized it out Never mind Anyway, this is the main resource we're looking for here this shows the uh the usage of the fbj block and There's it's pretty small. We can't put too much in it So let us start actually talking to the outside world So let's shift this out of the way now our device is Plugged in to the brother word processor by various ports like copied down So we want to Add some components to the schematic to represent the input and output ports We have The address input which is going to be eight bit wide We've got data input and output, which is eight pin eight bits wide And we have the control lines of which there are three So We call this address pins number of pins eight Uh display as a bus means that it emits a eight bit wide wire rather than eight one bit wide wires And this is the data pins now this is Going to be an input and an output Because we need to be able to read pins and write Yeah, we need to be able to read and write data So we have to be able to sense what's on the bus as well as assert our own values to the bus There does have this bidirectional mode here But this is subtly different from enabling input and output. So we're going to do this instead Uh, if you have them both enabled at once you want to turn on output enable here This generates a Uh a second input These are this thing here represents the inputs To the pin component which will be output from the board This is the output from the component which is input to the board This will enable whether we are Outputting or not and again, we want that to be a bit wide display as bus and control pins These are an input and there are three of them Um, in fact, I'm not going to do that I'm going to put three of these in so that we can name them different things So our three control lines are read write and io enable right We now want to assign these actual pins on the chip And I did note down what they're all connected to The uart has been automatically assigned to the correct pins Uh pin zero and one of port four Uh Let me get want to lock those to prevent them from being reassigned Uh now Read pin is on 1.6 Right pin is on 1.5 And io is on 1.7 And it's automatically locked those The data pins Which is these are eight bits wide these are on port two All of them and the address pins are on port Port zero We even have a Recent number of spare pins Some of them are reserved for things like debugging and programming But there's enough space here to add more functionality to this thing when we're done with it assuming it works, of course Okay So let us build this Four errors, um Okay, we need to wire stuff up So Let's just wire these up to hardcode these to zero Don't think that's going to work. Let's just try that Because this I think is going to be yeah, this is a one bit wide zero. So we actually want the Constant generator digital constant And yes, oh x f f is correct so The reason why I want to build it is data pin zero Cannot be configured for output enable or input output synchronization I'm connected to ursebs urcts terminal This is going to be because there is special logic attached to the to port two Okay, let's try just swapping these So the address pins are now on port two and the data pins are on port zero Let's see if that makes it happier cannot be configured for output enable or input output synchronization That's interesting It is connected. Oh, yes, and we also want to Set the modes here The way the The way the bus is set up on the brother computer Is that the lines or float high they're connected to five volts via a large resistor So that given no other control on the line They will end up at five volts Then in order to apply a signal a transistor in one of the components such as a memory chip will connect the line to ground So you end up with current flowing from five volts through the resistor And then through the transistor to ground So we want to mimic this The reason why is it means you can have multiple devices attached to the same uh The same bus line Provided only one of them is trying to drive the The line Then no current is consumed because then The line is connected to five volts via the resistor and then not anything else But any device can ground the line by simply turning on its transistor And Yeah, I think we can leave that as is Let me just do the same thing for this one. This is the really important one Because this is input and output These are Inputs so the drive mode shouldn't matter and build as you may be able to tell This is no longer The scripted part of this video Okay, it Really doesn't like me using port zero port one is in use by the iopins port three is Difficult to use because it's got the software Uh, it's got the j tag lines on it Um I have seen this before there's a workaround. I can't remember what it is. So I'm just going to go away and look that up I made it work What was needed was to change the constant value being fed to the output enable line from zero to a one Apparently if you set it to a zero, then the optimizer gets invoked and it removes various critical bits of the Data pin logic and then you get that meaningless error message This is one of the problems with this tool when it works. It's magic when it doesn't it's incomprehensible It's full of weird rough edges like If in verilog you try to use a tristate pin you get Completely meaningless gibberish turns out this verilog dialect doesn't support tristate which is why we're using a Separate input and output lines with output enable because you know you just can't do that Anyway, it now builds and runs and the text messages change here So let's see if we can do something a bit more interesting with this So We need to configure this to actually point we need to Configure the cpu to be able to read what's coming out. So we're going to do that with a Status register. This is a value that can be read by the cpu So display as bus. This is going to be address status Okay, now it needs a clock and for that we are going to use the System clock Yep hf clock high frequency clock And then we just need to wire this up here So now the cpu can read this register And it will sample the contents of the data bus and what the data bus we wanted the address bus like so And let's put another one in the status and this is going to be One bit wide And again, it needs a clock Which is again going to be hf clock. Okay now We want the Uh the Data sheet for the processor. Did I remember to download that? Yes Here it is What you're looking at here is the the bus timing graph for a i o operation This half has got the read cycle and this half has got the right cycles. So We're going to do reads for the time being. It's just to Make sure everything is hooked up in the right place the way a read works Is the cpu will assert i o e and r d and On the bus assertion means driving low When it goes low that is a signal for the hardware to sample the address of the address bus and Place the data on the data bus A certain time later Uh and leave it there until i o e and r d are unasserted So these So a read operation happens when i u e and r d are both low So Internally this thing operates with active high So the first thing we want to do is Invert i o e and r d And then we want an and And wire that up Okay We're ignoring wr for now. We're also ignoring the data for now So the cpu can now read control status and that will tell it It'll give a one bit value that will tell it whether a read operation Whether a read i o operation Is in action So what we do is we go to our source code And we're going to do forever. We want to Oh, yeah We want to build it this is Building it will then generate the source code for the two status registers to which will Make it much easier to access them because the id will know about symbols. Okay So what we're going to do is wait for control status To become non-zero that means a read i o operation is an access Then we're going to Read the address bus Then we are going to Uh Do we have s printf We seem not to have s printf. Okay. We want to try and print the address to the console. So let's Okay This is a Classic quick and dirty technique for printing a hex digit There are better ways to do it, but this is pretty fast and it's not like we are Low on flash space So print the high nibble print the low nibble so print x8 address there you are put char printed space now we're going to wait until the Uh, the control line is zero, which means that the i o operation has finished and if this works We should have a bus snooper which is capable of logging All the i o read operations that the computer is doing Uh, it'll just dump the address. We're just we're not actually doing this to like use it in real life I just want to verify that everything is wired up correctly So, uh, yeah, yeah the resource meter you can see that our logic here is used up Two macro cells and one unique peter and whatever they are Status cells are these things you can have up to four of those control cells will get to in a bit Now I don't actually know whether this will work The issue is the timing It takes time for the cpu to do things This is of course running at 39 29 megahertz which is a lot faster than the hd64 and 80s For I think megahertz And each operation takes multiple clock ticks But we still have to get through the entire serial write operation in one two three and a bit hd64 and 80 clock cycles So I don't know if this will actually if it's actually fast enough to do that I'm hoping it will because this Should be fast. It should just dump the values into the output buffer and then they'll get emitted Asynchronously maybe But let's program this And of course nothing is happening because it's just seen gibberish because the computer's turned off So I will go and turn it on Well, I don't know if you heard that but it made a very bad noise when I turn the computer on This suggests that Uh, our wiring is incorrect And we are doing something horrible to the i o Lines thus causing the computer to Keep crashing While it's running Which is annoying. Oh, I reckon it's this the data pins I think this is probably trying to assert a one onto the bus But as set to open drain drives low asserting a one onto the bus should do nothing Um Tell you what let's just Disable that And build Because I wonder if i'm actually wrong about open drain drives low At least this is the only output pin. So these should be safe Program, okay, and let's give that another go Nope that is in fact not working I have figured out the problem what i'm looking at here is the documentation for the CYHC kit 049 board itself And it turns out that there is a capacitor on Pin 1.7 So this is the one that I chose for the i o enable line. That means that whenever this is plugged in Really weird things happen to the system bus That's really annoying. There's actually two more um What I have done in the past is to simply remove the capacitors from the board I think what I'll do in this case is to just use some more pins. We do have lots after all That means I don't have to modify the board itself Here it is actually labeled on the PCB So I'm going to have to do some rewiring and then I will come back again The three control lines are now wired up to port 3.4 0.5 0.6. My first choice was 3.0 0.1 and 0.2 Unfortunately, it turned out that these are in use by the the programmer so Yeah, anyway, you notice that we are actually getting lots of spammy output Because it's working. This is recording what all the i o read accesses are The computer is actually running and I was able to reprogram it and it continued to run which is great This shows that This approach does actually seem to be working Okay, so let's turn the data pins back on again even though they're not connected to anything And that they should be on 2 Correct my notes. Yep, that is correct program So it rebuilds and Eventually it rebuilds very slowly. It's a single threaded compiler And we still have stuff coming out. It's all the same stuff. Excellent So what are we actually using? We're using About three quarters of our GPIO pins one serial block A miniscule amount of FPGA resources And nothing else. Oh, yeah, you notice down here This chip's got analog stuff in it. It's not as flexible as the digital But it's got some configurable pins some op amp some adc stuff like that None of it's actually enabled. So we could actually like use this to do things like I don't know Measure the voltage of the brother word processors bus maybe I mean I don't think we've got any use for the analog stuff, but it's Really nice to have Okay, let's actually start work on the real thing So we nuke all of this because we're not going to do it in discrete logic and Come on delete delete delete We're going to write this in verilog because it's actually easier to do in verilog So to do that we select the project right click add Add Add symbol component I can never remember where things are Add components item. Here we go Symbol wizard Right This is going to create a new thing that we can put onto the schematic And it's going to be backed up by some verilog code that we're going to actually want to write. So What's this going to be? This is going to be our decoder Uh, well our bus interface more accurately. So we are going to have Uh data input Data output Address input IoE input Read input Write input These are connecting to the external bus Uh, we also want a output enable Which will be connected up to the data pins We are going to want to have a system clock because lots of things need a system clock And then we're going to want the things that we're actually going to wire this up to So, uh I'm going to put those in later. I think So this has defined our Uh Component it needs a This is just a drawing tool So we need a bit of Manual configuration, that's a bus That's a bus. Let's put that the right way round That's a bus And this is a clock Uh I have seen, um arrows drawn to indicate it's a clock, but I'm not going to bother with that Uh Go to properties. Can we change the block name? No, we can't that's I'm not actually sure that has done what I wanted it to But anyway, let's go to Generate fairy log This is going to be Yeah, that's all wrong. That's annoying. Okay, let's Here we go. We want to add it here And we want to set the name here Create new There we go. Now it's called bus interface and it's shown up next to our design. Okay, that was annoying Data read Address read IO enable Read Write clock Data write Outputs enable these are digital outputs Yep Set these to be Buses like so Okay Generate fairy log bus interface dot v Right So this is the chunk of fairy log that is representing that component So the ci sim here is the Symbol definition This is the fairy log Here is our schematic. So we go over to here to Not that one Search for the bus interface component, which is here And we plonk that down Onto our schematic and Let's just do some Rearrangement just line things up a little neatly and Wiring so address IOE read write We want our clock Nearly everything Fairy log related wants a clock Find out why later Unfortunately that's not showing up as a bus Why is that not a bus? That's a bus I didn't save it. That's why Yep, okay. Now it's a bus Uh, right Output from the data bus Goes to data read Output from the bus interface Goes to data out And the output enable Line Followed it Okay, that should be all the wiring that is needed. So we should be able to build that We're going to be adding some more stuff apart from anything else Yeah Uh, the outputs aren't there is no fairy log to define what these are therefore it's unhappy So let us Write some code So this looks like a programming language, but it really isn't very log Is a way to define a set of equations that get turned into logic So For example, we want to say that OE is always going to be zero output enable disabled And Likewise data write is going to be a A eight bit wide zero constant now this will probably not build Because setting OE to zero is going to cause the Uh Seems that loading the analog editor makes me think makes it think that we're using analog. Here we go We get the same error again because OE here is a zero So let's just set that to one for now. We can't program this or it will crash the board and It builds okay, so Let us define A oh, yeah, and our actual source code is all wrong. So what we're going to do Well, we can define a few uh Simple equations so that we know that the cpu is reading when Read is False And io enable is false so likewise See the cpu is writing when we have write and io enable So we want to enable the output line only Only when the cpu is wanting to read data so this Whenever the cpu tries to read any ioport It will enable the output and a certain zero that will certainly crash the board Because we don't want to Uh We don't we only want to respond to the address range that we care about So let's do this with um So let me think Actually, this is to start with let's just do this So if the address lines are set to o x 40 Then now we should have We should have an error Oh, yeah, too much Uh too much c This is the syntax for hex constants eight bits wide hexadecimal four zeros the data I picked four zero because the internal peripherals for this thing Uh appear at zero to three f i've noticed in fact, we should be able to see here That there are a number of other peripherals. You can see it's mostly reading from fd But it's also looking at places like nine b eight six six zero, etc But it doesn't appear to be trying to read from four zero So i'm going to take a wild guess that That address is not used So this should If it builds work So we have slightly more complicated logic Who's we've used a tiny amount of the flash Not a lot of ram most of the ram is actually Occupied by the stack and the heap and we're not using a heap Oh, no, it's not. Sorry. The heap is being reduced to 128 k But I thought it was more because I thought this thing a 32 k around but it doesn't Anyway, that's lots But we should be able to program this Actually, let's change this to a memorable Number so Program and wait for it to build And it's programmed and now we head over to the board Okay, here I am at the workbench with the thing running. It's booted up into bbc basic It turns out that programming the board doesn't crash the computer But if the board is plugged into the usb Then the floppy disk drive doesn't work Which is weird. I think that what we've got is like ground loop stuff causing noise Which is interfering with the ability to read the floppy disk So I've unplugged it from the usb. The board here is now driving the The psoc board So we should be able to just do print Get hex 40 and see what comes out 72 Uh, let's do that again, but in hexadef small 40 48 um That is not the number that's supposed to come out So for one is still returning port for one is still returning ff, which is what I would expect 48 Okay Yeah, let's go back to the let's plug this in actually And the computer still runs Let's go back to the desktop and do some experimentation So I think I know what's going wrong Let me How do you work this stupid thing programmer? Here we go hex 48 It's not that I actually thought this would be This would come out as 5a Because I think that I don't know whether the value on the bus is supposed to be inverted or not I think not from looking at the Looking at these Problem solved I was using the wrong drive mode for the data lines So it was asserting bad data onto the bus Setting it to uh Our resistive pull-up Meant that I now get correct data. So I am performing a get I have this little program here And through the snow you can see it is actually Returning 5a, which is the right value Of course, I still went through and traced all the data lines before looking at that Because you know, it's more work that way. Anyway back to the desktop