RISC-V Memory Map
Memory Map of OUR RISC-V Processor
Assuming default memory configuration, IROM_DEPTH_BITS
= DMEM_DEPTH_BITS
= 9.
Address | Attributes | Name | DESCRIPTION |
---|---|---|---|
0x00400000 to 0x004001FC | RO (Read Only) | Instruction memory (IROM) | 128 words (0x200 bytes) - total number of instructions should not exceed this (127 excluding the last line 'halt B halt'). Word addressable - only multiples of 4 are valid addresses. This might cause warnings about 2 unused bits, but that's ok. |
0x10010000 to 0x100101FC | RW (Read-Write - See notes below) | Data memory (DMEM) | 128 words (0x200 bytes) - Total number of constants+variables should not exceed this. Word addressable - only multiples of 4 are valid addresses. |
0xFFFF0000 | RO | UART_RX_VALID | Data can be read from UART_RX (is valid) only when the LSBit of this register is set. |
0xFFFF0004 | RO | UART_RX | UART Receive (input, from keyboard). UART Settings : Baud Rate 115200. 8-bit. No Parity. 1 Stop bit. Only LSByte is valid. RealTerm is a good console application. |
0xFFFF0008 | RO | UART_TX_READY | Data can be written to UART_TX only when the LSBit of this register is set |
0xFFFF000C | WO (Write Only) | UART_TX | UART Transmit (output, to display). Only LSByte is writeable. Same settings as RX |
0xFFFF0020 | WO | OLED_COL | The OLED pixel column index, between 0 and 95. |
0xFFFF0024 | WO | OLED_ROW | The OLED pixel row index, between 0 and 63. |
0xFFFF0028 | WO | OLED_DATA | Please see the peripherals page for details on choosing OLED data format via OLED_CTRL register. |
0xFFFF002C | WO | OLED_CTRL | Controls OLED data format and modes of operation. |
0xFFFF0040 | RO | ACCEL_DATA | Please see the peripherals page for details on accelerometer data format. |
0xFFFF0044 | RO | ACCEL_DREADY | A new reading is available if the LSBit of this register is set. Not necessary to check this if ACCEL_DATA is read at a low frequency (a few times a second). |
0xFFFF0060 | WO | LED | LED[7:0]. Only the least significant 8 bits written to this location are used. LED[8] is used to show the divided clock. LED[15:9] shows PC[8:2]. PC[1:0] will alw ays be 0 and hence not shown. |
0xFFFF0064 | RO | DIP | DIP switches. Only the least significant 16 bits read from this location are valid, corresponding to DIP switches [15:0]. |
0xFFFF0068 | RO | PB | PushButton switches. [2:0] → BTNL, BTNC, BTNR. Only the least significant 3 bits read from this location are valid. BTND is used as RESET and BTNU is used as PAUSE. |
0xFFFF0080 | WO | SEVENSEG | 7-Segment LED display. The data written to this location will appear as an 8-digit hexadecimal number on the display. For the Basys 3 board, the two half-words will keep displaying in alternation. |
0xFFFF00A0 | RO | CYCLECOUNT | Cycles elapsed since the system came out of reset. |
Table 1: Memory map summary
A Note on Data Memory.
This kind of a data memory is slightly unrealistic and possible only in FPGAs.
In embedded systems, the data memory has two parts - constants stored in a ROM/Flash (non-volatile) and variables stored in RAM.
Constants are available for reading without a prior writing (and can't normally be written).
Variables that are initialized are explicitly set to their initial value via writes (sw
instructions). Variables should't be read (lw
) without a prior write (sw
) somewhere.
In desktop systems, the data memory is typically all RAM, but has constants stored in read-only area that is initalised explicitly via writes (sw
) and are not modified further.
As with embedded systems, variables that are initialized are explicitly set to their initial value via writes (sw
instructions). Variables should't be read (lw
) without a prior write (sw
) somewhere.
In contrast, the FPGA-based systems often have a more flexible memory architecture*, allowing for RAM to be used like ROM, i.e., variables are auto-initialised - can be read without prior writes, but can also be modified.
*At least the way it is used in our case, which necessitates the memory to be small and implemented using block or distributed RAMs available within the FPGA fabric and initialised using GSR.
Sizes of various segments, base addresses, and peripheral address offsets.
The RARS default memory configuration is as follows.
IROM_BASE
= 0x00400000. This should be the same as the.txt
address based on the Memory Configuration set in the assembler/linker,Wrapper.v
and the PC default value as well as reset value inProgramCounter.v
DMEM_BASE
= 0x10010000. This should be the same as the.data
address based on the Memory Configuration set in the assembler/linker,Wrapper.v
, C program.MMIO_BASE
= 0xFFFFF0000. This should be the same as the.mmio
address based on the Memory Configuration set in the assembler/linker,Wrapper.v
, C program.
It is possible to change the configuration to others supported by RARS, such as compact with .txt
at 0. MMIO base can be changed freely in any configuration, though if you need to use RARS simulated peripherals, it to be the default value.
Instruction and data memory sizes can be bigger than 128 words. Be mindful of the potentially increased synthesis time though, especially if not using synch read (block RAM).
DMEM_DEPTH_BITS
= 9. DMEM_SIZE
= 2**DMEM_DEPTH_BITS
= 0x200 = 512 bytes = 128 words by default. Changing this will need changes to Wrapper.v
. Set STACK_INIT
in C / asm program (via .align
in asm, via DMEM_SIZE
) in C.
IROM_DEPTH_BITS
= 9. Changing this will need changes to Wrapper.v
.
Endianness
The instruction and data memory are WORD addressable (NOT byte-addressable) for our labs. => Endianness doesn't matter for our hardware. Endianness matters only when each byte in the memory has an address, but we read/write one word (4 bytes) in one go.
For example, if we store two words 0xABCD1234 and 0xEF567890 in the memory starting at the address 0x10010000, the two words will be stored at word addresses 0x10010000 and 0x10010004 respectively. In a system with a little-endian processor like RISC-V, the byte address 0x10010000 will have the content 0x34, byte address 0x10010001 will have the content 0x12, byte address 0x10010003 will have the content 0xAB, byte address 0x10010004 will have the content 0x90, byte address 0x10010007 will have the content 0xEF.
In CG3207 labs, we use a system that cannot deal with byte addresses such as 0x10010001 and 0x10010002*. We can only send word addresses (addresses which are multiples of 4), i.e., like 0x10010000 and 0x10010004, and get the corresponding 32-bit contents. Hence, for our hardware, endianness doesn't matter*.
*Unless you explicitly enable it by adding support for lb
/lbu
/lh
/lhu
/sb
/sh
- which is optional, and for later assignments.