Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

Move data from NIOS to hardware and then back to NIOS

I am trying to do a little calculation in hardware but I'm stuck on how to get started. I'm a complete newbie, but after reading a lot of manuals and demos, I figured out that I could have a soft processor NIOS that could accept C code. So using a basic computer configuration of the the DE2 (it comes with the University Program), I then created a NIOS BSP project. After trying many times, I managed to get everything compiled and the code below to run on the target hardware.

void main(void)

{

int line1[] = {1, 2, 3, 4, 5, 6, 7};

int line2[] = {1, 2, 3, 4, 5, 6, 7};

//--- Do this in verilog!

int i;

int store_val = 0;

for(i=0; i<7; i++)

{

store_val = store_val + (line1*line2);

}

//--- verilog_end

}

Now the next step is that I want to do the calculation in the for-loop section in hardware using verilog rather than C. I have three main queries:

1) How to write that for-loop function in verilog?

2) Where do I save the verilog module?

3) When I have the verilog equivalent, how do I move the values contained in the two C arrays to the verilog module to do the calculation and then send back 'store_val' to the BSP project? I read about DMA in other posts but I don't know how to do that process.

This is confusing me. Any help is greatly appreciated. Thank you very much

14 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You might have an easier time using this instead: http://www.alterawiki.com/wiki/modular_sgdma

    --- Quote End ---

    Yeah the UP core has a ST port into the core and another ST port coming out of it. Before I slot the ST component in between the read and write masters and assuming that my original data is generated by the CPU and stored in the SDRAM, and the result after going through the UP core will also go in the SDRAM, do I need:

    - modular dispatcher (MM to MM), Read master and Write master like in the example file

    or

    - modular dispatcher (MM to ST) & Read master, and modular dispatcher (ST to MM) & Write master

    My feeling is that it is the first option but I just want a confirmation because it is my first time using a DMA type component.

    If suppose instead I had used the standard SG-DMA component available in SOPC, would I then need two SG-DMA components, i.e. MM to ST at transmission and ST to MM at receiver?

    OK, in the meantime I tried to adapt the example given in the website to my DE2-115 board but the msgdma keeps spinning and my NIOS program gets stuck at loop 'while (sgdma_interrupt_fired == 0) {}'. How do I find the cause of the error? Could this error due to the fact that I have not fully copied the SOPC example design file because I have not used the Avalon-MM Pipeline Bridge and the 'DDR SDRAM Contorller with ALTMEMPHY'? I just have a CPU, SDRAM controller and the Modular SGDMA components (all running at same clock rate) at the moment. I did not add those components because I don't understand their purpose but if needed, I will do it.

    Now assuming I get that example file working after adding all these extra components and clocks, what changes will I need to bring to the parameter setttings of my Read Master and Write Master components if the data to be transferred is now a 3 x 12 array of u8 integers, i.e. 36 bytes, defined as below in my C code.

    alt_u8 my_2d_array[3][12] ; //Fill in the values

    source_buffer = &(my_2d_array[0][0]);

    The Data Width setting goes to 8. How about Length Width and FIFO Depth, and the other settings? What are the major changes in the example 'main.c' file to I need to do?

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That's correct, to do this with the SGDMA on the ACDS you would need to control a pair of SGDMAs for doing MM-->ST and ST-->MM. With the mSGDMA if you wedged your block between the read and write masters then your control would be just triggering a normal DMA transfer (assuming for every input there is one output from your block).

    The pipeline bridge isn't necessary, it's just included to add some additional pipelining to the design. If you are running the included software from the mSGDMA design make sure you change the settings near the top of the main.c file to represent your own system memory address base and span. I did a minor update to that software to fix a bug which would cause the source and destination buffers to overlap so make sure you have the latest main.c file.

    You probably don't need to modify many of the settings. The length width parameter just dictates the maximum number of bytes you can transfer in a single transfer. For example if you chose 20 bits that means you can transfer slightly less than 1MB of data in a single descriptor. The only reason why it's a parameter and not hardcoded to be 32-bits is that when a timing critical path shows up in one of the masters it can typically be solved by just reducing that length register width to something more sensible (being able to transfer ~4GB in one shot doesn't make sense in SOPC Builder which only has a 4GB space per master anyway).

    Since you are dealing with MM to ST the symbol size is 8-bits. So if your component has an 8-bit input/output you can still setup the mSGDMA for a wider data path. This will help increase your memory throughput since multiple symbols can be fetched every clock cycle. I would use the C code as a guideline, most of it has nothing to do with the mSGDMA so it may end up leading to confusion. If you want to see a simplier application check out this design example which is configured for MM --> ST which performs frame buffering to an LCD. The only difference is you would use MM --> MM and setup the descriptors slightly differently.

    http://www.alterawiki.com/wiki/modular_sgdma
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    If you are running the included software from the mSGDMA design make sure you change the settings near the top of the main.c file to represent your own system memory address base and span.

    --- Quote End ---

    OK, I found my mistake. I had the CPU Reset and Exception vectors on the SDRAM. I have now changed the DATA_SOURCE_BASE address to start further into the memory, and I can see the source and destination memory being the same after I run the program in debug mode.

    Just a quick question: Is the statement ' test_counter = 0;' not supposed to be before the start of the 'do' loop? Because '(test_counter < NUMBER_OF_TESTS)' in the 'while condition' will always be true otherwise.

    The next step for me is to try to populate the source buffer with the 36 data values contained in my_2d_array, but I am struggling to do this. I've set MAXIMUM_BUFFER_SIZE 36 and NUMBER_OF_BUFFERS 2 but I am not too confident with the pointer notation to get first 36 addresses after DATA_SOURCE_BASE to contain those values. Can anybody please help me with this?

    --- Quote Start ---

    If you want to see a simplier application check out this design example which is configured for MM --> ST which performs frame buffering to an LCD. The only difference is you would use MM --> MM and setup the descriptors slightly differently.

    http://www.alterawiki.com/wiki/modular_sgdma

    --- Quote End ---

    Where is this design example? I can't find it on that website.

    --- Quote Start ---

    With the mSGDMA if you wedged your block between the read and write masters then your control would be just triggering a normal DMA transfer (assuming for every input there is one output from your block).

    --- Quote End ---

    Now that you mention to assume every input = output, I am realizing it is not the case with that UP IP block. This block takes in one 8-bit value at a time and uses altshift_taps shift register to get the data in the right format to do its processing. Anyway, this is not a problem for now as I just want to get those 36 values in my array moved around using Avalon ST and I will have to write my own core later.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Good catch, I never noticed that bug since I have always used the code in an infinite loop mode. I'll update the design some time this week to correct that.

    I would probably make your own code to test your own hardware since most of the mSGDMA code is setup to setup random test buffers and all kinds of non-practical stuff. Your code should end up being a faction of the length if you code it for your own application. You could run an uncached malloc (see Nios II software handbook for more details) to allocate a pointer to some location in the heap and then dereference that point to populate the buffer.

    Sorry I linked the wrong page, I meant this one: http://www.alterawiki.com/wiki/modular_sgdma_video_frame_buffer

    If the read and write lengths are not the same then you'll need to use a pair of DMAs since a DMA typically performs the same number of reads as writes. It would be possible to hack the dispatcher HDL to support different read and write lengths but I wouldn't recommend attempting that just yet.