Quantcast
Channel: Altera Forums
Viewing all articles
Browse latest Browse all 19390

How to transfer doubles from the nios 2 to FPGA using the avalon interface?

$
0
0
Hi everyone,

First a little backstory on this problem I'm encoutering.
I have a Altera DE2 board on wich I want to implement my current project.
In this project I need to transfer multiple 64 bit values (doubles) from the nios to the FPGA wich runs VHDL.
I have read the documentation on how to create a avalon component and succeeded (I guess) in creating/implementing one.
Now I want to transfer two 64 bit values to this component, do some calculating with it and send them back to the C code.
To illustrate the goal I reach, here is a simple image:

In multiple attempts to achieve this goal I did not manage to get one single value on the VHDL side.
The code and findings below are logical to me, but sadly not working as a whole.
Currently I'm having big trouble understanding the whole concept of 64 bit avalon component against the nios (since the nios2 is a 32 bit processor).
Could anybody tell me the following things:
  1. How to write a 64 bit value (in this case a double) on the nios2 using IOWR. (I have seen it here, but not sure if it is correct: http://www.alteraforum.com/forum/showthread.php?t=21529).
  2. How to receive this 64 bit value in VHDL code (write request from master (nios)). In the documentation they speak of using the byteenable signal. But I can't figure out how to work with this.
  3. How to send a 32 bit value back to the nios2 (read request)


If done some work on all the four questions and like to get an expert opinion on the work that is done (mostly of things are correct).
1. / 2. Following the link supplied on the first question I read that you can write a 64 bit value by doing two times a IQWR but on different address, like so:
Code:

IOWR(COMPONENT_BASE,0x0,value_one_part_one);
IOWR(COMPONENT_BASE,0x4,value_one_part_two);
//where part_one and part_two are two 32 value that form a 64 value together.

//A second value would go like this
IOWR(COMPONENT_BASE,0x8,value_two_part_one);
IOWR(COMPONENT_BASE,0x12,value_two_part_two);

I was wondering if it is possible to write a whole double in one time using only one IOWR.
Cause else I would be forced to convert the double in two 32 bit arrays, wich costs calculation time.

I also did some reading on how to address a 64 bit component.
My findings are listed in this table below
Offset on the nios memory part (8 bits) Offset on the 64 bit avalon component
0x00 1 00000000 (0 ... 31)
2
3
4
0x04 5 00000000 (32 ... 63)
6
7
8
0x08 9 00000001 (0 ... 31)
ect. ect. ect.
If this is correct then that would mean that I can use the byteenable and address signals to receive one 64 bit component like this:
Code:

if write = '1' then
    if byteenable(0) = '1' then
        data(7 downto 0) := writedata(7 downto 0);
    end if;
    if byteenable(1) = '1' then
        data(15 downto 8) := writedata(15 downto 8);
    end if;
    if byteenable(2) = '1' then
        data(23 downto 16) := writedata(23 downto 16);
    end if;
    if avs_s0_byteenable(3) = '1' then
        data(31 downto 24) := writedata(31 downto 24);
    end if;
    if avs_s0_byteenable(4) = '1' then
        data(39 downto 32) := writedata(39 downto 32);
    end if;
    if avs_s0_byteenable(5) = '1' then
        data(47 downto 40) := writedata(47 downto 40);
    end if;
    if avs_s0_byteenable(6) = '1' then
        data(55 downto 48) := writedata(55 downto 48);
    end if;
    if byteenable(7) = '1' then
        data(63 downto 56) := writedata(63 downto 56);
    end if;
end if;


if write = '1' then
    case address is
        when "00000000" => -- ADDR 0
            value_one := data;
        when "00000001" => -- ADDR 8
            value_two := data;
        when others =>
            value_one := (others => '0');
            value_two := (others => '0');
    end case;
end if;

Is this the correct way to recieve the two 64 bit values from the nios, or is there a correct/better way to do this?

3. For the last part I do have a clue on how to do this.
You need to put up a VHDL code sort a like the write request code, but then for a read request.
I guess the C code for reading a 32 bit value from the FPGA would be a simple as this:
Code:

int value_one = IORD(COMPONENT_BASE,0x0);
int value_two = IORD(COMPONENT_BASE,0x4);

For the VHDL it would be:
Code:

if read = '1' then
    case address is
        when "00000000" =>
            readdata <= value_one;
        when "00000001" =>
            readdata <= value_two;
        when others =>
            readdata <= (others => '0');
    end case;
end if;

Again is this the correct way to do this or is there maybe a better one?
Currently I can't find a solution to the whole problem, so if anyone could explain these three main parts to me, than that would be a big help.
I guess this is a beginners problem since the avalon mm interface is fairly new to me.
Thanks in advance.
Attached Images

Viewing all articles
Browse latest Browse all 19390

Trending Articles