|
Short answer: I would generally say WRITE_FIRST is the correct choice for your FPGA which is the closest representation of the nand2tetris memory.
More specifically, you have to study the timing diagrams of your FPGA's block RAM. The memory implementation of nand2tetris uses a purely combinatorial addressing/memory cell selection circuit. It means that as soon as the address changes, the memory would immediately provide the data of the newly addressed cell, regardless of a clock cycle. Only the writing of new data to a cell is sequential and will occur with a new clock cycle. A typical block RAM of a FPGA will usually differ from this behaviour by at least registering the address. E.g. the address has to be written into the address register of the block RAM and the data read from memory will only be available for the next cycle.
That is especially relevant because of some oddities in the n2t instruction set which allows reading/writing to the same cell AND changing the address for the next memory instruction at the same time:
AM=M+1
Coming back to your question:
Consecutive M=M+1 commands will all refer to the same address and you want the new value written to the memory to be available immediately for the next instruction as M. This is what the WRITE_FIRST mode of your FPGA seems to provide.
More critical would be something like this:
AM=M+1
M=M+1
Nand2tetris takes advantage of the combinatorial memory, because the data at the new A is provided "in between" the cycles. So effectively n2t can read AND write a value in 1 cycle.
I am pretty sure that your block RAM cannot do that within 1 cycle:
- read from old A
- combinatorial update ALU
- write to old A
- read from new A
Some block RAMs can be configured as dual port. With such configurations you could manage to do 2 memory accesses in parallel. However, that leaves you with the issue that the VRAM portion has to be read in parallel by the video controller, typically blocking one port (though not relevant in practice since AM=M... commands typically don't occur with VRAM addresses). In any case, that's why it is so important to study the timing diagrams of your specific FPGA.
To summarise: to deal with parallel read/write operations and address changes, you need either a fully combinatorial memory decoding circuit 100% like nand2tetris (unlikely that your Block RAM can do that), or insert wait states to allow data to be written/address register of the block RAM to be updated, or (most complicated) add a write-back cache circuit.
|