Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 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

    Thank you everybody for the tips but I am now more lost than before :)! OK let's start somewhere. Please correct me where I am wrong.

    1) Starting with normad's PIO suggestion, I inserted three 16-bit PIO ports (2 in and 1 out) in SOPC Builder. I called them line_1_in, line_2_in and result_out respectively. Each one has a Base and End address assigned by SOPC, e.g. 0x08200000-0x0820000f for the line_1_in. Then I declared these ports in the top level .v file. as:

    input LINE_1_DATA;

    input LINE_2_DATA;

    output RESULT_BACK;

    and added these lines also to the internal modules:

    .in_port_to_the_line_1_in (LINE_1_DATA),

    .in_port_to_the_line_2_in (LINE_2_DATA),

    .out_port_from_the_result_back_out (RESULT_BACK),

    My new queries:

    - What clock do I assign to these PIOs? Now they are at 50 MHz like all other components.

    - To go back to the C-code now, how do I tell NIOSII to send data to these PIOs? I am assuming that I need to make use of pointers to read the memory address, but then I don't know how to move to the next step. I am not too sure how to get get rid of the for-loop either. Any suggestions please?

    volatile int * line_1_ptr = (int *) 0x08200000; // Port_in_1 address

    volatile int * line_2_ptr = (int *) 0x08200010;// Port_in_2 address

    volatile int * result_back_ptr = (int *) 0x08200020;// Port_out_result

    *line_1_ptr = line1; // But line1 is an array

    *line_2_ptr = line2; // line2 is an array

    store_val = * result_back_ptr;

    2) How do I write a process with a clock input as suggested by nophutwern?

    3) This is my first attempt at writing a verilog module. I don't even know how to compile it :), but I just wanted to know if this the type of code that will do the calculation as the data comes in :

    module my_sum_prod (

    // Inputs

    clk,

    line_1_in,

    line_2_in,

    // Output

    result_out

    );

    //Port Declarations

    // Inputs

    input clk;

    input [15:0] line_1_in;

    input [15:0] line_2_in;

    // Output

    output [15:0] result_out

    //Internal registers

    reg [15:0] original_line_1;

    reg [15:0] original_line_2;

    reg [15:0] temp_sum;

    reg [15:0] final_result_out;

    temp_sum <= 16'd0;

    final_result_out < 16'd0;

    always @(posedge clk)

    begin

    temp_sum <= original_line_1 * original_line_2;

    final_result_out <= final_result_out + temp_sum;

    end

    assign result_out = final_result_out ;

    endmodule

    4) When I manage to do a proper verilog module, where and how I do call it in my main .c file such that it accepts the data from the NIOS processor through the PIOs and return a value again?

    Thank you again. I'm just entering this whole FPGA world and I need step-by-step help.

    NB: To nophutwern: I will try the FIFO as soon as I get this methodology working. It's part of my learning process.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    For loops are synthesizable but may give different results that what you expect. In this case it would create 8 multipliers and 8 adders that would all work in parallel to do the operation in one clock cycle. If you want to have only one multiplier and do the operation in 8 cycles instead, then yes you need to get rid of the loop and do a clocked process.

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

    Hi vivasam,

    1) for loops in verilog aren't synthesizable, they are only working in simulation. You have to write a process with a clock input. On every clock cycle it will be processed one time - so you can do the mathematical operations. Maybe you need a second process to count the cycles and abort the loop.

    2) the verilog module have to be saved in the quartus-project folder or a subfolder. You can use the quartusII software to create the verilog module, and modelsim to simulate it.

    3) DMA is not the right way to communicate between nios and hardware. You can use FIFOs or DUALPORT-RAMs to communicate. FIFOs are easier to use. You can implement this functions bei using the MEGAWIZARD in quartusII software, both are standard modules. When you got different clocks for your nios and the verilog-module you should use clock-crossing FIFOs. As normad said you can also use the PIO (a module for sopc-builder), but be careful with the clocking.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i havent used a for loop in verilog before but this link shows you how to

    http://www.asic-world.com/verilog/verilog_one_day2.html

    you have to save your verilog module in the same project that you created your processor. after that you can right click on that file in the files tab and select 'create symbol for this file'

    after that you can use that symbol in the bdf editor just as any other module.(double click on the bdf editor and your module should be in the project folder)

    as for sending data from your processor to your verilog module is tricky.

    what you can do is add a 16bit PIO device to your processor and send data through it integer by integer. Because it is very impractical to send the whole array at once.

    if i understood your program right what you can do is create two 16bit PIO devices and send line1 and line2 separately two at a time. and write your verilog to process data as it comes in. This way you dont need a for loop in your verilog