Hi, interesting project. How do you manage the "recursion" (or feedback wires, or loops)? If i understood well, you push the change from some gate to the output connected to the next gate. But if the next is connected to the input of the first one, there is a loop of calls that will never end up. So how did you manage it? Thanks
Hi, I’ve built an entire CPU complete with 130 odd instructions, 256 bytes of RAM, a keyboard device and a scrolling 14 segment display using my own logic sim simulating only 4 components, being wire, an oscillator, a tri-state buffer and a NAND gate. The way I handled recursion is more about recognising when the simulation has reached a stable state. Basically each pass through the simulator will update every component state, if any change occurred then it’s still not stable and you perform another pass, until it no longer yields a change of state. In order to achieve this I also treat the first pass of the high state in the oscillator as a special ‘rising edge’ state, certain time sensitive units such as flip flops will use that rising edge as a trigger, so will only flip say on the first pass, but will not perpetually flip while the passes are being simulated to a steady state. In my system the entire component set becomes steady after between 1 and 4 passes, and only occasionally up to 6 or 7 passes. It’s a bit of a hack, but it works and basically I have a turing complete CPU complete with conditional branching, logical operators, addition, subtraction and even barrel shifters and rotators. I’ve even simulated 7 and 14 segment display decoders and built a scrolling display, and a fully working alpha numeric keyboard. Built entirely out of those 4 components wired together. All in pure python it’s hardly efficient but even with 256 bytes of RAM, a 16 character scrolling display, a keyboard and a 130 instruction 8 bit CPU it will execute about 4-10 instructions per second. Give it a go!
@@osogrande4999 WOW Oso, you are a MASTER! So you do not use components that updates the status of the connected ones. Instead, for every clock cycle, there is a "simulator" that iterates over all components looking for updates eventually, up to no updates state is reached. Than, it can pass to the next clock cycle, right? I didn't understand if the code is available on GitHub or not, for studying and testing it. Thanks for sharing!
@@jdaniele Hi Daniele, I'm afraid it isn't on GitHub since I still have to clean up the code quite a lot. I looked for a way to private message you on UA-cam but I don't think it's possible. I wouldn't mind sending you the code as it is if you can find a way for me to contact you privately. The project grew organically so the code is somewhat convoluted, and on top of that I built in the ability to construct components that can be 'emulated' instead of simulated so it's even more confusing unless you know that beforehand (this is great for getting some performance when you want to see it in action though). For every clock cycle (in fact every half cycle since the every time the clock changes the entire component set must be updated), all the logic components are computed over a series of iterations (based on their function and inputs). I very simply keep a flag which tracks if anything changes during that iteration. Once no changes have occurred, then then that half-cycle is complete. It also means I can detect any logical design errors in components by ensuring a steady state occurs within a reasonable number of iterations - I generously allow up to 100 iterations but in my system it doesn't take that many at all. To ensure timing-sensitive parts like latches and flip-flops work properly I have a 'risingedgepulse' component which is connected directly to the oscillator. This edge pulse will only be 1 when both the oscillator is 1 AND it is on the first iteration - that way it acts like a period of time where in a real system a rising edge detector would do the job of limiting the signal time (I know nothing about real hardware but I do understand some basics). For the complex parts of the system like the instruction decoder, and other complex 'chips', I created a logic combinator class which basically takes a truth table and generates all the logic gates. That way I design my instruction set with ease, and I can add new instructions with just a couple of lines describing the instruction name, and the sequence of micro operations that it performs - it's really pretty cool. I learned a lot from the entire thing, it's very much my own design of CPU, but heavily leverages the knowlege I picked up in Ben Eater's videos where he builds an 8 bit CPU on bread-boards. If you haven't seen them I highly recommend you have a look. Best of luck - if you can get a private message to me I'll be happy to send you my (messy) code!
I forgot to mention, the entire system with 128 bytes of 8 bit RAM, generates a huge list of around 44,000 logic components. These are comprised of : 1 oscillator (the clock) 2 rising edge pulse (one for the clock and one for the inverted clock) 78 tri-state buffers (these connect various registers etc to the bus) 8 bus wires and literally all the rest are NAND gates which take 2 inputs. Which is very cool when you think about it!
@Oso Grande Hello Oso, you did a gigantic work! Yes, I love Ben, he is a digital logic Guru! You can easily reach me by mail writing to my name.surname @ gmail.com. Thanks a lot! :)
It's been over a year now, but do you still have this code? I would love to play around with it
Thanks for a very interesting presentation! - Like the guys before me; have you shared the code anywhere?
Interesting, thanks for sharing
Hi, interesting project. How do you manage the "recursion" (or feedback wires, or loops)?
If i understood well, you push the change from some gate to the output connected to the next gate. But if the next is connected to the input of the first one, there is a loop of calls that will never end up. So how did you manage it? Thanks
Hi, I’ve built an entire CPU complete with 130 odd instructions, 256 bytes of RAM, a keyboard device and a scrolling 14 segment display using my own logic sim simulating only 4 components, being wire, an oscillator, a tri-state buffer and a NAND gate. The way I handled recursion is more about recognising when the simulation has reached a stable state.
Basically each pass through the simulator will update every component state, if any change occurred then it’s still not stable and you perform another pass, until it no longer yields a change of state.
In order to achieve this I also treat the first pass of the high state in the oscillator as a special ‘rising edge’ state, certain time sensitive units such as flip flops will use that rising edge as a trigger, so will only flip say on the first pass, but will not perpetually flip while the passes are being simulated to a steady state.
In my system the entire component set becomes steady after between 1 and 4 passes, and only occasionally up to 6 or 7 passes.
It’s a bit of a hack, but it works and basically I have a turing complete CPU complete with conditional branching, logical operators, addition, subtraction and even barrel shifters and rotators. I’ve even simulated 7 and 14 segment display decoders and built a scrolling display, and a fully working alpha numeric keyboard. Built entirely out of those 4 components wired together. All in pure python it’s hardly efficient but even with 256 bytes of RAM, a 16 character scrolling display, a keyboard and a 130 instruction 8 bit CPU it will execute about 4-10 instructions per second. Give it a go!
@@osogrande4999 WOW Oso, you are a MASTER! So you do not use components that updates the status of the connected ones. Instead, for every clock cycle, there is a "simulator" that iterates over all components looking for updates eventually, up to no updates state is reached. Than, it can pass to the next clock cycle, right?
I didn't understand if the code is available on GitHub or not, for studying and testing it. Thanks for sharing!
@@jdaniele Hi Daniele, I'm afraid it isn't on GitHub since I still have to clean up the code quite a lot. I looked for a way to private message you on UA-cam but I don't think it's possible. I wouldn't mind sending you the code as it is if you can find a way for me to contact you privately.
The project grew organically so the code is somewhat convoluted, and on top of that I built in the ability to construct components that can be 'emulated' instead of simulated so it's even more confusing unless you know that beforehand (this is great for getting some performance when you want to see it in action though).
For every clock cycle (in fact every half cycle since the every time the clock changes the entire component set must be updated), all the logic components are computed over a series of iterations (based on their function and inputs). I very simply keep a flag which tracks if anything changes during that iteration. Once no changes have occurred, then then that half-cycle is complete. It also means I can detect any logical design errors in components by ensuring a steady state occurs within a reasonable number of iterations - I generously allow up to 100 iterations but in my system it doesn't take that many at all.
To ensure timing-sensitive parts like latches and flip-flops work properly I have a 'risingedgepulse' component which is connected directly to the oscillator. This edge pulse will only be 1 when both the oscillator is 1 AND it is on the first iteration - that way it acts like a period of time where in a real system a rising edge detector would do the job of limiting the signal time (I know nothing about real hardware but I do understand some basics).
For the complex parts of the system like the instruction decoder, and other complex 'chips', I created a logic combinator class which basically takes a truth table and generates all the logic gates. That way I design my instruction set with ease, and I can add new instructions with just a couple of lines describing the instruction name, and the sequence of micro operations that it performs - it's really pretty cool.
I learned a lot from the entire thing, it's very much my own design of CPU, but heavily leverages the knowlege I picked up in Ben Eater's videos where he builds an 8 bit CPU on bread-boards. If you haven't seen them I highly recommend you have a look.
Best of luck - if you can get a private message to me I'll be happy to send you my (messy) code!
I forgot to mention, the entire system with 128 bytes of 8 bit RAM, generates a huge list of around 44,000 logic components.
These are comprised of :
1 oscillator (the clock)
2 rising edge pulse (one for the clock and one for the inverted clock)
78 tri-state buffers (these connect various registers etc to the bus)
8 bus wires
and literally all the rest are NAND gates which take 2 inputs.
Which is very cool when you think about it!
@Oso Grande Hello Oso, you did a gigantic work! Yes, I love Ben, he is a digital logic Guru!
You can easily reach me by mail writing to my name.surname @ gmail.com. Thanks a lot! :)
it is very interesting. can u share code please ?
I want your GitHub account name please
Not toggle flop it's JK flip flop