1

I followed the nand2tetris course (https://www.nand2tetris.org/course) with the main intent to learn how to build a soft processor on a real FPGA.

While the course was simple enough, now that I am starting with the FPGA implementation I feel a bit lost.

I bought an Intel de10 nano FPGA(http://de10-nano.terasic.com/), and, having some Verilog knowledge from Uni, I was able to download "Quartus Prime Lite" and bootstrap with simple things like led blinking, etc...

However, when it comes to implement the processor there are several things that are not clear to me:

  • How do I implement data memory? I saw there is a DDR3 module attached to the HPS of the FPGA. Is this something I need to directly use? Could I simply use a big 16bit register vector in HDL?
  • How do I implement the ROM from where the program is read? And how can I store the binary I assembled to then bootstrap the fetch-decode-execute loop?
  • How do I implement the screen and the keyboard? Indeed, there is also an HDMI controller on the board: do I have to implement all the logic myself?

Those are the main questions I am struggling with at the moment. Could you point me out to any resource useful for a complete novice?

Thanks,

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847

2 Answers2

5

For something as simple as a CPU from nand2tetris you'll be just ok with block RAMs, there's plenty of it on DE10Nano, likely enough for all your needs. Plus some more distributed memory.

In case if you still want an access to DDR, DE10Nano is an SoC, with a hard DDR controller managed by the processor subsystem. It's very easy to interface with it over an Avalon bus (don't bother with AXI unless you really need maximum possible performance).

For the ROM, just use LUTs. A simple static case in Verilog will be translated into an efficient LUT-based ROM.

For accessing HDMI on DE10Nano, you can take a look at this example: https://github.com/combinatorylogic/soc/blob/a1d282d793548030cba940496bed90ff3a29c0ba/backends/c2/hw/de10nano/vga1080p.v (you can also take a look at the DDR access in the same project). Before you can use HDMI you'll need to set up the ADV7513 chip over i2c, see a copy of a library from Terasic under the same project.

For a monochrome 800x600 video you'll be ok with a block RAM. For higher resolutions, as in the example above, you'll have to use DDR.

SK-logic
  • 9,605
  • 1
  • 23
  • 35
  • Thanks for the reply! Few clarification questions: "block RAM" means using a simple reg[] based block in verilog? And what do you exactly mean by LUT? – Giuseppe Rossini Mar 21 '21 at 17:04
  • You need to follow few simple rules to ensure that an addressable register array is synthesised as a block ram. E.g., see page 20 of https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/qts/qts_qii51007.pdf – SK-logic Mar 22 '21 at 09:41
  • Alternatively you can instantiate a vendor-specific block ram module yourself. – SK-logic Mar 22 '21 at 09:41
  • @GiuseppeRossini for a LUT-based ROM, see this example: https://github.com/combinatorylogic/soc/blob/a1d282d793548030cba940496bed90ff3a29c0ba/backends/c2/hw/de10nano/i2c/I2C_HDMI_Config.v#L133 – SK-logic Mar 22 '21 at 09:44
  • Also, you can always use a block RAM as ROM, since you can load it with initial data values. Depending on what resource is more available - LUTs or BRAMs, you can decide what to use for a ROM implementation. – SK-logic Mar 22 '21 at 09:45
5

I finished implementing the nand2tetris hardware on a small fpga (ice40HX8K) and here are my suggestions:

A. Memory Original nand2tetris uses two memory parts:

  1. ROM for instruction code
  2. RAM for data memory

Both can be implemented using BRAM-cells of fpga. They have the nice property, that BRAM can be preloaded with data at startup. This is useful to preload the ROM with your instruction code. If you have plenty of BRAM you are fine. My board (ice40HX8K-EVB from Olimex) had only 8K x 16bit of BRAM. So I did the following:

  1. I used 512 x 16 bit of BRAM as ROM preloaded with a bootloader (written in Hack-Assembler)
  2. rest of BRAM is used as RAM (7680 x 16 bit)
  3. My board has an external SRAM chip (256 k x 16 bit). I used this as Instruction memory. On startup the bootloader fills the SRAM with Application-code and than "switches" the SRAM to be the instruction memory.

Your board has a separates DRAM-chip. You could use this as Memory too, but be warned: using DRAM is much more tricky than using SRAM.

B. input/output nand2tetris has a screen and a keyboard attached to it.

An easy to implement alternative could be the following: Implement a small UART so you can connect your PC over a terminal (e.g. screen /devttyACM0). Now you can talk to your Hack-CPU (running in fpga) at runtime. I used the UART also to upload Hack-Application at boot time.

Take a look at my repo: https://gitlab.com/x653/nand2tetris-fpga