Skip to content

Memory Access

Nicolas Peschke edited this page May 23, 2020 · 7 revisions

Memory Access on the RedPitaya

Memory Architecture

The RedPitaya uses shared memory for communication between the FPGA and the ARM processor. The memory is aligned to 4 bytes and has a width of 32 bits. This means that if you tell the processor to read address 0x40000000 it will read four bytes starting with address 0x40000000. Hence, it will read the addresses 0x40000000, 0x40000001, 0x40000002 and 0x40000003. Direct access to the unaligned addresses 0x4000000(1..3) is disallowed because no matter what address is given to the processor, it will always read four addresses starting with the one given. This would open up the possibility for a process to write and read from memory that is owned by another process which leads to huge security and stability risks.

Register Map

The RedPitaya developers created the following register map that is largely followed by pyrpl. The original RedPitaya map can be viewed here (https://redpitaya.readthedocs.io/en/latest/developerGuide/fpga.html#register-map).

Start End Module Name Usage in pyrpl
CS[0] 0x40000000 0x400FFFFF Housekeeping Housekeeping
CS[1] 0x40100000 0x401FFFFF Oscilloscope Oscilloscope
CS[2] 0x40200000 0x402FFFFF Arbitrary signal generator (ASG) Arbitrary signal generator (ASG)
CS[3] 0x40300000 0x403FFFFF PID controller Dsp module (interconnects modules)
CS[4] 0x40400000 0x404FFFFF Analog mixed signals (AMS) Analog mixed signals (AMS)
CS[5] 0x40500000 0x405FFFFF Daisy chain FREE
CS[6] 0x40600000 0x406FFFFF FREE Was free, now used for FADS by me
CS[7] 0x40700000 0x407FFFFF Power test FREE

Memory access (FPGA side)

pyrpl is using its own simplified system bus architecture. Usually when using the Zynq FPGA series, the AXI bus is used to exchange data between different the processing system (the ARM processor, PS) and the programmable logic (the FPGA, PL). However, the AXI protocol is quite complex so the pyrpl developers opted to create their own system bus structure. To use the system bus, both a read and write interface have to be implemented and the module needs to be connected to the bus in the top level module. There, the base address (0x40?00000, ? replaced by 0..7 for the respective module) is also given to the module instance.

Top module level

pyrpl creates the eight big registers (0x40?00000, ? = 0..7) for the individual modules in a system bus chunk in the top module. This is also the location where the AXI bus is wired to the pyrpl system bus. To make use of the free registers, the lines have to be removed that set everything in the desired memory range to zero. Below, the range 0x40600000 - 0x406FFFFF is enabled to be used later for the FADS module.

// unused system bus slave ports

assign sys_rdata[5*32+:32] = 32'h0; 
assign sys_err  [5       ] =  1'b0;
assign sys_ack  [5       ] =  1'b1;

//assign sys_rdata[6*32+:32] = 32'h0;
//assign sys_err  [6       ] =  1'b0;
//assign sys_ack  [6       ] =  1'b1;

assign sys_rdata[7*32+:32] = 32'h0; 
assign sys_err  [7       ] =  1'b0;
assign sys_ack  [7       ] =  1'b1;

The special kind of indexing here is called indexed part select (more info https://stackoverflow.com/questions/17778418/what-is-and). Basically the sys_rdata wire is 8 times 32 bit wide and using this notation, the 32 bit words can be easily addressed.

To connect a module to the system bus in the top module, it must expose the following connections.

// Reset
.adc_rstn_i     (   adc_rstn                    ),

// System bus
.sys_addr        (  sys_addr                   ),  // address
.sys_wdata       (  sys_wdata                  ),  // write data
.sys_sel         (  sys_sel                    ),  // write byte select
.sys_wen         (  sys_wen[6]                 ),  // write enable
.sys_ren         (  sys_ren[6]                 ),  // read enable
.sys_rdata       (  sys_rdata[ 6*32+31: 6*32]  ),  // read data
.sys_err         (  sys_err[6]                 ),  // error indicator
.sys_ack         (  sys_ack[6]                 )   // acknowledge signal

To select the base address (0x40?00000, ? = 0..7) the respective number has to be used as index for sys_wen, sys_ren, sys_err, sys_ack and sys_cs. sys_rdata gets special treatment. The connected part of the 8 * 32 bit wide vector is the sixth 32 bit word.

Module level

Together with the sys_wen, sys_ren, sys_rdata, sys_err, sys_ack and sys_cs wires, the 8 individual base addresses are selected.

Clone this wiki locally