Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17255 Discussions

Modular SGDMA Streaming

Altera_Forum
Honored Contributor II
1,931 Views

Hi, 

 

I'm trying to stream data from an ADC to my DDR RAM. I’ve hit a roadblock with using the modular SGDMA core to do streaming to memory mapped transfers to DDR RAM. An interrupt that is supposed to go off when the transfer is complete never goes off. This isn’t because the data never stops being written but is actually because the data never begins to be written. I’ve noticed this because I print out some of the memory addresses during the wait for the interrupt -> the values that get written out don’t correspond to the values being fed into the SGDMA. I’ve noticed issues which point to either a software or hardware problem. 

 

 

 

 

 

The software issue is that the IOWR and IORD commands don’t seem to be working correctly. 

 

 

IOWR_32DIRECT(MEM_IF_DDR2_EMIF_0_BASE, testNumber, testNumber); 

 

 

IORD (MEM_IF_DDR2_EMIF_0_BASE, testNumber); 

 

 

/////////////////////////////////////////////////////////////^Doesn’t work 

memcpy(MEM_IF_DDR2_EMIF_0_BASE + testNumber*sizeof(int), &testNumber, sizeof(testNumber)); ->writing 

 

 

memcpy(&value, (MEM_IF_DDR2_EMIF_0_BASE+testNumber*sizeof(int)), sizeof(int)); ->reading 

 

////////////////////////////////////////////////////////////^Works 

 

 

I’m not sure if this is because in my tests I am writing to RAM, I will look into that, but this is an issue since the data transfer descriptor is initialized using the IOWR_32DIRECT function. I don’t think this is the issue though because I’m able to call these same functions successfully when I do memory-mapped to memory-mapped data transfers. I've attached the c file that I'm using to test the streaming data transfer (main.c), the line that doesn't work is# 74: if (sgdma_interrupt_fired == 1) -> I've changed this to a while check and noticed that the interrupt never gets asserted. 

 

 

The next area that I think might be an issue is the way I collect data from the incrementing register (the one I’m streaming data from). I simply connected the bus streaming data bus to the streaming sink of the write master in the Qsys project. I have an image of that project with the connection circled (Qsys.png). Is that the correct way to connect streaming data to a Qsys project? Is there anything that’s obviously wrong with the way I’ve set up the connections? Any advice on how to approach figuring out why the interrupt I need doesn’t go off?
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
1,096 Views

Your image is so small it's difficult to see. Can you add a signaltap instance on the stream interface to check that anything is actually going through it? 

 

As for your problem with the macros, it's probably because the 32DIRECT versions use a byte offset, while IORD/IOWR use a word offset. Therefore you either need to multiply testNumber by sizeof(int) in your line with IOWR_32DIRECT, or only use IOWR and IORD. This should probably work: 

IOWR(MEM_IF_DDR2_EMIF_0_BASE, testNumber, testNumber); IORD (MEM_IF_DDR2_EMIF_0_BASE, testNumber); 

 

Using direct addressing, either with pointers or memcpy work also, but you need to be careful if your CPU has a data cache. Then you need to flush or invalidate it before or after the operation.
0 Kudos
Altera_Forum
Honored Contributor II
1,096 Views

Hi Daixiwen, 

 

I've attached a screenshot of the signals being tapped from the write master's data sink, it looks like the streaming data is going through correctly. The CSR IRQ also goes off which indicates when the write is complete. However, there is a problem on the software side, the exception does not get handled.  

 

The way I have the system set up right now is I "fake" an avalon streaming interface to stream data from an ADC to a FIFO. That fifo is connected to the data sink of the SGDMA using the avalon streaming interface. I used a PIO to allow the NIOS II software to set the valid bit of the top level module's "fake" streaming avalon bus (this signal is tapped and shown in the attached image as "adc_ready_pio_export"). The interrupt signal is also shown as "csr_irq". 

 

The interrupt remains at 1 after the standard descriptor register is written to. It seems like the nios 2 processor registers an unhandled exception right after interrupt signal goes up. The following are the instructions that get called prior to the interrupt going off (the PIO that controls the write is set to high) and the assembly instructions of the exception handler. 

 

90 IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 1); 

00000320: movi r3,1 

00000324: movhi r2,16388 

00000328: addi r2,r2,2128 

0000032c: stwio r3,0(r2) 

96 if(value == 0){ 

00000330: ldw r2,-4(fp) 

 

 

 

alt_exception_unknown: 

40000094: break 0 

40000098: ldw r5,68(sp) 

4000009c: ldw ea,72(sp) 

400000a0: ldw ra,0(sp) 

400000a4: wrctl estatus,r5 

400000a8: ldw at,8(sp) 

400000ac: ldw r2,12(sp) 

400000b0: ldw r3,16(sp) 

400000b4: ldw r4,20(sp) 

400000b8: ldw r5,24(sp) 

400000bc: ldw r6,28(sp) 

400000c0: ldw r7,32(sp) 

400000c4: ldw r8,36(sp) 

400000c8: ldw r9,40(sp) 

400000cc: ldw r10,44(sp) 

400000d0: ldw r11,48(sp) 

400000d4: ldw r12,52(sp) 

400000d8: ldw r13,56(sp) 

400000dc: ldw r14,60(sp) 

400000e0: ldw r15,64(sp) 

400000e4: addi sp,sp,76 

400000e8: eret  

 

I also printed out the register values at the time the exception occurs: 

 

zero 0  

at 3735928559  

r2 3690725375  

r3 488  

r4 1  

r5 0  

r6 2155905152  

r7 4278124287  

r8 67528  

r9 70204  

r10 5  

r11 3  

r12 67532  

r13 1073740280  

r14 67528  

r15 196218880  

r16 69016  

r17 67552  

r18 3735928559  

r19 3735928559  

r20 3735928559  

r21 3735928559  

r22 3735928559  

r23 3735928559  

et 3735928559  

bt 4294967295  

gp 0x0001a844  

sp 0x3ffffeb8  

fp 0x3fffff18  

ea 0x0bb21004  

sstatus 4294967295  

ra 0x000001ec  

pc 0x40000094  

status 0  

estatus 0  

bstatus 4294967295  

ienable 5  

ipending 1  

cpuid 0  

ctl6 4294967295  

exception 20  

pteaddr 4294967295  

tlbacc 4294967295  

tlbmisc 4294967295  

eccinj 4294967295  

badaddr 0  

config 4294967295  

mpubase 4294967295  

mpuacc 4294967295  

 

The register that seemed to be the most important was the exception register which held a value of 20. A subset of the exception register corresponds to the cause of the exception. That subset corresponded to cause# 5 which is an "Illegal Instruction Exception". I'm not sure why I'm getting this exception since the instructions being run prior to the interrupt seem valid. Any idea what's causing this problem?
0 Kudos
Altera_Forum
Honored Contributor II
1,096 Views

I have another update, it seems like I can only write 488 words of data before this exception occurs. This indicates to me that there might be a buffer that's filling up (I don't know why I would be getting an illegal instruction error though). The other strange thing is that the depth of all of my buffers is 1024, I would expect a buffer error to occur at around that number of words being transferred not 488.

0 Kudos
Reply