I've done the Coursera course, Nand2Tetris, that inspired this website [1] and found it deeply intellectually satisfying and engaging.
If anyone is interested in learning about the logical primitives that build up to a computer, and how they're implemented using logic gates, I would deeply recommend the course!
Whenever someone asks me how a computer works, this is what I tell them to read. No need to qualify the recommendation on their background, the book is accessible to anyone because it starts from first principles and builds layers on top.
Seconded. And a quick note that this course is based on the book "The Elements of Computing Systems: Building a Modern Computer from First Principles (The MIT Press)"
This is an incredible course to learn about low level stuff like
computer architecture, micro OP codes, machine language, assembly code, virtual machine...
I implemented the course[1] in Logism[2] but unfortunately the simulation is too slow to run Teris!
Course materials (projects) seem to contain only slides, with bullet points, not real explanations. Am I missing something? Should I buy the book to actually have the course?
You don’t really need the book for the first half of the course, but I found it very helpful for the second half. More so than the vids, which got boring due to repetition.
Building circuits is neat, but I think this has some problems as a game:
1. It seems to only let you save one solution for each level, even though there are two optimization goals. It should let you save one for fewest components and one for fewest NAND gates.
2. It's not really clear how NAND gate counts work in later levels where you're using potentially non-optimal components you've built? Like does it count each one as the number of gates that you used, or the number of gates that is optimal, or what? Someone else told me it was the latter, but it seems like XOR counts as 6 even though there's apparently a way to do it with fewer?
3. Why do some levels give me the message "This is optimal!" while others say "This is the simplest solution!"? What's going on here? What do these messages mean specifically? It's not clear.
All this adds up making attempts at optimization a bit frustrating and as such I just don't really want to play it very far. If you're not worried about optimization it seems fine, but if you are the interface really kind of works against you.
1. The blue on purple color scheme is a little hard on the eyes. Changing the blue lines and circles to #0f0 green helped a lot. (Green also has strong "on" semantics)
2. My SO and I both had trouble finding the trash can. We both tried to drag components back to the workbench or off of the mat to delete them. A larger trash can icon or just making it red might help.
3. I ran into some z-layering issues (at least on Firefox). Opening a component info bubble from the workbench displays under the mat. Also the "results" popup displays underneath any components that might be on the far side.
Overall great game though! I had a lot of fun with it. Thank you!
Yeah if you see my comment below I think really it should always be explicit both about whether you used the fewest components and (separately) about whether you used the fewest NAND gates. Currently it seems like you sometimes only get told about one or the other...
Love the game. One suggestion I had is that it would be helpful to indicate the number of nand gates in each component. When I'm trying to optimize I'm also trying to remember which is a "cheaper" component - having a number of nand gates associated with each component would help.
Hi author, cool game, you got me hooked! One thing I could suggest for now (I'm still in the Latch level) is that you could go a bit below and start from the transistor itself, like build the nand gate from the transistors..
> it seems like XOR counts as 6 even though there's apparently a way to do it with fewer?
This is a great game and tbh I think you're just butthurt because you couldn't figure out any of the optimal solutions. Xor is the first one and it sounds like you didn't solve it. (fwiw I haven't figured it out yet either)
1. It does only save one solution for each level but if you can do it in fewer nands, why do you need to keep the fewest components? Most puzzle games like this work this way
2. In later levels it uses your best solution from previous levels. The basic (non-optimal) xor solution has 3 compents with 6 nand. The first time I did half-adder, it told me my solution was 2 components/8 nand (a 2-nand AND plus a 6-nand XOR). After trying for optimal xor again (and failing), solving half-adder shows "2 components used. Mission XOR is not completed, so the total number of gates could not be counted." So it uses YOUR best solutions.
3. I mean it's pretty obvious. optimal == fewest nand, simplest == fewest components. If you optimize for nands, your solution is going to be less simple/more complicated.
I think it's a really great game. You should give it another try
I've completed all but the very last level (input/output, it just seemed too disconnected from the rest and more tedious than informative, so I gave up) and managed optimal solutions for all of the basic logic gates (but not for some of the more complex later components -- would have loved to try, but the canvas gets unwieldy fast as it has too little vertical space, plus its too much effort to break down components into their nand gates for optimisation).
With that said (so you know that I'm not "butthurt" nor do I need to give it another try): I completely agree with all of the feedback Sniffnoy gave and I don't know why you're getting butthurt over someone having feedback like that. Why would you insult someone just because they had comments on it? Are you having a bad day?
It is a great game, nonetheless, though, otherwise I wouldn't have played it as far as I did. I think with some small tweaks and fixes, it could be greater still, however.
I think Sniffoy made some valid points but I don't think they support his premise that "Building circuits is neat, but [...] this has some problems as a game". Sure there are things that could be improved but I don't think they take away from the game. I mean you said you did all of the levels with optimizations and enjoyed it. You didn't let the subpar language stop you from enjoying it. But Sniffoy did. And I guess that rubbed me wrong - he's blaming the game because he got hung up on a couple words.
> This is a great game and tbh I think you're just butthurt because you couldn't figure out any of the optimal solutions.
There's no need to be rude. Insults like this don't add to your argument.
> 1. It does only save one solution for each level but if you can do it in fewer nands, why do you need to keep the fewest components? Most puzzle games like this work this way
Because they're separate optimization goals. I want to hit all of them and have each of them saved. Compare Zachtronics games, as magnostherobot mentions. Also, the ones with fewest components will typically be conceptually clearer.
> 2. In later levels it uses your best solution from previous levels. The basic (non-optimal) xor solution has 3 compents with 6 nand. The first time I did half-adder, it told me my solution was 2 components/8 nand (a 2-nand AND plus a 6-nand XOR). After trying for optimal xor again (and failing), solving half-adder shows "2 components used. Mission XOR is not completed, so the total number of gates could not be counted." So it uses YOUR best solutions.
Thanks for determining this. But it would be better if, you know, the game said this anywhere. None of this is explained.
> 3. I mean it's pretty obvious. optimal == fewest nand, simplest == fewest components. If you optimize for nands, your solution is going to be less simple/more complicated.
I have to disagree that this is "obvious". I'm sure one could figure it out after playing enough, but one shouldn't have to; the messages could easily be made more explicit. And like note that even this isn't exactly a correct description, because if you come up with a solution that minimizes both, it only says "This is optimal!" rather than saying "This is simplest and optimal!". You see the problem?
And honestly I'm just not sure you're correct. Like doing NOR the obvious way, I got a "this is simplest!" message, but did not get a message saying to do it in fewer NAND gates. So what does that mean? Is it optimal or not? If yes it ought to have told me; if no it ought to have given me the message saying it can be done in fewer.
So yes I do think the game is really being badly unclear about this.
Yeah I mean I guess you're right - the verbiage could be improved. I just don't think it's worth getting hung up on. It's still a fun little game. I've heard that everything in a processor can be built up out of nand gates and always wondered how that worked so it's been neat to work through it.
It's kind of a learning-first game though so I guess if your goal is to beat the game and get every achievement, yeah you'll be disappointed.
You can create equivalents of AND, OR and NOT with only NAND, which is why it's possible for everything in a processor to be NAND gates only.
https://en.wikipedia.org/wiki/NAND_logic
As far as Zachtronics games go, you've been able to save multiple solutions since IIRC Infinifactory, and those games all have two or three optimisation goals.
I think Silicon Zeroes only remembers one solution per puzzle, however in most of its levels its goals are quite closely related.
OCTOPTICOM also only saves one solution per level, but only has one optimisation goal, I believe.
I don't believe your assertion is true; at the least, it is not true in my experience.
Okay Zachtronics games look awesome. I'll definitely have to try them out.
On the other hand, my experience with games "like this" are mostly free mobile games or other little browser games. For a paid game I would totally expect to be able to save multiple solutions.
Not that this will ever matter for someone who isn't a circuit designer, but the "optimal" solution for the latch is actually really bad.
If you use a "select" block (which should really be called "mux") and tie the output to the input, you create a race condition. If the data input is 1, and you change set from 1 to 0, the output can actually glitch to 0 for a very short period of time, which is a big no-no. (If you draw the equivalent circuit out with just nand gates and assume they all have some delay between input and output, you'll see why).
A safer solution would be to cross couple two nand gates into an SR latch [0], use another two nand gates to control the Set and Reset signals, and an inverter to create NOT(data).
Of course in reality, a latch is usually custom built out of transistors rather than logic gates, but there are some cases where I've used logic-gate-latches to make things easier.
Since the latch is only used as a component of the flip-flip and edge sensitive logic does not care about glitches except on the clock line or any asynchronous set/resets (which are not used in this design) I find that rather unimportant.
Especially because the d-flipflops found in standard cell libraries are frequently implemented as what amounts to two muxes and some inverters.
For a design that uses latches as stand-alone components the glitch considerations become a lot more important.
In practical designs, flip flop outputs are regularly used as clock inputs and asynchronous set/reset inputs. If you used this latch as the output latch in a flip flop, it would glitch on the falling edge of the flip flop clock.
I didn't go through the entire game, so its entirely possible that it would not affect this particular "design". But as its far more educational than practical, I think its still worth mentioning.
> Especially because the d-flipflops found in standard cell libraries are frequently implemented as what amounts to two muxes and some inverters.
I'm curious where you've seen that implementation because I've never seen anything like that. Most of what I've seen uses two tri-state inverter latches.
Not the one you're replying to, but look up "transmission gate latch". As for an actual processor that uses them, see the RCA CDP1802, for which a die photo and reverse engineered gate-level schematic are available.
There was this ancient Flash game called "Engineer of the People" that was all about designing IC circuits (NPN and PNP junctions) in the Soviet Union for some secretive reason. I never beat the game and got to the reveal. IIRC it was by Zachtronics, the same guy that did Shenzhen I/O and infiniminer (the inspiration for Minecraft).
Human Resource Machine and 7 Billion Humans are also pretty good computer programming puzzle games that are pretty funny and fun to play. HRM is basically solving problems using single threaded assembly. 7BH is solving problems using more multi threaded primitives (CSP-like). Both have a couple optimizations points for every problem, and you can copy/paste code to a notepad to save too I believe, though only one solution is saved in game.
Last time I tried a Zachtronics game I thought it was awesome and that it was far too much like my actual job so I refunded it. Would have played so much of it if I was still in school.
The main issues I've found in his games (at least for Shenzen I/O and TIS-100) is that the difficulty ramps up a lot in the later levels, and there are artificial limitations that are make the game way harder and less fun. For example, the lack of a "swap dat acc" instruction, having just 2 registers at most, among others. You can work around that but the game's idea shouldn't require you to exploit weaknesses of its simulation engine.
I feel like that's the point of the game, is it not? I always thought of Shenzhen I/O as a hacking game, not an engineering game. The best solutions are elegant, but in a kind of fucked up and convoluted way. This, to me, is the appeal, but I can see why it turns some people off.
Have to agree with this. I kept thinking "Instead of playing this, I'd be way better of buying an Arduino and building something real instead. I'd learn a real skill and it would be less unnecessarily difficult on top of that."
Of the various Zachtronics games I've tried, Opus Magnum has been the only one where I haven't felt that the interface and the limitations get in the way of letting me execute the solution.
I remember that game like it was yesterday --- and then checked to see that it was created over a decade ago! I was hoping someone would make a more realistic sequel with something like CMOS, but haven't seen any since then.
Oh man, I was hooked the moment I played SpaceChem. I think that game and Kerbal Space Program are responsible for reigniting my interest in math and computers.
Edit: this continues on with the counter level, where you can use the register but it does not behave like the typical set of edge-triggered flip-flops (or transparent latches) that one would normally use. My best attempt at coming up with an explanation is that it's like two-phase edge-triggered logic.
Yeah. The flip flop, and its corresponding register version would be a DFF with enable pin. That is not actually too abnormal. The traditional implementation is taking a normal DFF and adding the enable feature either by gating the clock or by adding a mux in the input path, that uses the enable signal to select between the input or the existing output.
Everything started making sense after I thought of "store" as "enable", and I made it to the end pretty quickly after that --- except for the "bonus" multiplier level, which is definitely possible but seems like it would take about 10x as much space as the canvas allows.
I got excited when I saw the title, then checked the URL and it is a software simulation / game of building a computer. I'm not denying this can be interesting, but I've been thinking for a while to get my hands dirty with hardware as a side project. (I'm a software eng by profession). I haven't really done a lot of research on this yet, but does anyone have any recommended guides/books/tutorials on how to get started designing and building my own computer? (extra points it it's a mobile/embedded computer)
Super educational, but if you want to get into more embedded hardware hacking, I would say that building a homemade computer like he does is probably not a super exciting place to start. I'd recommend picking up some Teensy 4.0 microcontrollers and build some small hardware projects with the microcontroller before diving into lower-level circuitry.
Check out Ben Eater on YT. He has a series where he builds an 8 bit CPU from components. And another where he builds a 6502 based computer from scratch. He sells kits to follow along, and explains everything along the way
I would recommended just using the Nand2Tetris book Elements of Computing Systems and implement the computer on an FPGA. I went through the course using the original project’s simulation tools, and I am now circling back and implementing the Hack CPU on a Xilinx FPGA using VHDL.
It has a USB host port for a keyboard and VGA out for the display. The jury is still out as to whether I can build the entire CPU using nand gates, including the ROM and RAM memory. Doing so will use a lot of the FPGA's resources from calculations I've seen. If that's not possible for the memory, then I plan on using the block RAM that's included on the Xilinx board, but for everything else I plan on following the book's design as close as possible. So far, I am in chapters 1-3 simply porting my solutions in the course's HDL to VHDL, which is relatively straightforward so far. I'm taking my time to make sure I'm doing things "professionally", as I'd like to learn the Xilinx toolchain in my professional work at some point. My experience with FPGAs has been implementing them with LabVIEW, which actually makes learning VHDL somewhat mechanical although a bit frustrating. (If I had an FPGA big enough that's targetable via LabVIEW, I could probably build and test the computer in a day or two aside from the VGA and keyboard.) The combinatorial gates are done now, and I've implemented a DFF and am building things from there. So now I'm learning about clocking and such with VHDL. The most troublesome part I anticipate is what to do about the ROM and RAM memory and the display and keyboard. I'd also like to update the CPU where I can interactively download new code to the CPU from a PC using the assembler and software stack I'm building, which is in F#.
I have several books I am using as reference:
- VHDL By Example by Blaine C. Readler (great first intro to VHDL)
- Digital Design Using Digilent FPGA Boards: VHDL/Vivado Edition by Haskell and Hanna
- Effective Coding with VHDL: Principles and Best Practices by Ricardo Jasinski (I'm using this to sort through the various ways to do things in VHDL and have best practices in my code.)
- VHDL for Logic Synthesis by Andrew Rushton
- FPGA Prototyping by VHDL Examples: Xilinx MicroBlaze MCS SoC by Pong Chu
Also James Sharman's channel[1]. He has built an 8-bit, pipelined, computer from scratch. He works at the level of TTL chips. Sharman is good at explaining what he's doing, but does not go down to the very detailed level of bit-by-bit explanation of Ben Eater.
The first question you'll need to answer is if you want to build a computer from discrete gates, or if you'd rather glue large existing IP blocks together.
In the former approach, you won't get anything in a mobile form factor, as your computer would simply be too big. But you might learn more than in the latter approach.
Neat! My only complaint is I feel like it would be more intuitive to be able to drag connections from output to input. I understand why it's the other way around (each input can only have one source, while outputs can go to multiple chips) but it still feels backwards - like reading right to left.
Silicon Zeroes[0] is also a pretty good next step if you enjoy these games. Doesn't quite get down to the NAND level, but gets into a lot of fun performance optimizations instead.
Awesome! I've always thought it would be interesting to port Nand2Tetris to the web to make it more easily accessible. Glad someone finally ported the virtual computer building part!
I was able to get as far as building the half-adder, but then didn't have the means of figuring out the full adder as that seemed massively more complex.
I find using an FPGA for this an ideal middle point. Building a functional computer from discrete components is fun but the result may not be worth the effort, to be honest. At the other extreme, modeling it in software may leave a weird feeling of not having achieved anything. With an FPGA, on the other hand, you can create something of a usable computer, even one you could run Linux on.
So I'm a bit confused with how this is measuring the number of NANDs; for example, with the first adder problem, I solved it with exactly two gates, neither of which were NAND, and yet while it's recognized as the lowest number of gates, it insists that it can be done with fewer NANDs (than zero, apparently). Is it counting the NANDs that may or may not be used to implement those two gates? And if so, is that based on how I solved the previous problems? Or is it based on the lowest possible number of NANDs that would be required to solve those problems / produce those gates?
If it is indeed counting the NANDs used to make the gates I actually used, it'd be useful to have a clear indication of exactly how many NANDs each gate uses so I can chase after a game of NAND Golf.
It would be nice if that information were available in later stages, without having to take notes.
I'd like to see the ability to "unbundle" the composite components. Maybe an intermediate pin in (say) the XOR or half-adder has exactly the signal you need to save a component in a later stage.
Some of my favourite courses of undergrad were Digital Electronics 1 and 2. How you can build everything up from nand gates is so satisfying, I’ve forgotten much of it now but this is bookmarked to come back to for posterity
It probably sounds petty, but I found it disturbing that inputs are at the bottom ... I was constantly having to readjust my thinking, and have become sufficiently frustrated to give up.
This is fun! But, the first few told me "this is the optimal solution", then I hit the xor gate, and I can get either "this uses the fewest nand gates but it can be done with fewer components" or "this uses the fewest components, but it can be done with fewer nand gates".. Does this imply that there is no optimal solution, or just that I've not yet found it?
You haven't yet found the optimal solution. I had the same problem and it wasn't until a later problem that I realised XOR could be implemented with fewer nands.
Reminds me of Ben Eater's Youtube videos where he builds everything using basic gates on a breadboard. He made a video-card using ICs on a breadboard that fascinated me: https://www.youtube.com/watch?v=l7rce6IQDWs
this is fun. When I got to the multi-bit-adder I think the half adder was removed from the toolbox though and replaced with the full adder - would be nice to keep it there.
Author here - It uses TypeScript and the Angular framework. Not because I prefer Angular in particular but because I had to learn it anyway for a work-related project. I think TypeScript is great.
It looks like it is more canvas than svg, yes? Was there a particular canvas library that you used? I ask because I'm working on a side project that feels like it mostly pulls me in an svg direction, so I'm been prototyping with dagrejs and cytoscape.js, but it also has elements of creating (or dragging, like yours) new elements into a graph and connecting them, so I'm regularly torn when deciding on the basic architecture of it.
I'm not using canvas. SVG is used for the connections, the rest is HTML. I'm not using any particular library for the diagrams, since I couldn't find anything suiting my purpose unfortunately.
I would definitely like to improve the look of the wires.
it would be cool (ambitious) if at some point there is also a programming language/compiler down the line. perhaps it can would also be able to run tetris or even another nandgame.
I find that it actually gets easier as you get further along, because you start using higher and higher level components. The hardest (to optimise, not to implement) for me were the components just after the basic gates (counters, latches, etc).
I'm no expert in this field but I think the challenging part in IC design is the light-based lithography process that makes integrating large numbers of transistors possible...so I guess the 3d printing part is not the limiting factor.
Should start from physics building up and up until you have subatomic particles, rising through many layers of abstraction until you are doping P and N type semiconductors .... starting with such a high level concept as “nand gates” is far too easy. /sarcasm.parody
If anyone is interested in learning about the logical primitives that build up to a computer, and how they're implemented using logic gates, I would deeply recommend the course!
-----------
[1] https://www.nand2tetris.org/