Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12589 Discussions

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

Altera_Forum
Honored Contributor II
1,321 Views

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: 

http://www.alteraforum.com/forum/attachment.php?attachmentid=9929&stc=1  

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: 

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 

00000000 (0 ... 31) 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x04 

00000000 (32 ... 63) 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x08 

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: 

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: 

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

 

For the VHDL it would be: 

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.
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
548 Views

The nios is only ever going to generate 32bit Avalon cycles - so your 64bit transfer will always be two Avalon bus cycles. 

Personally I wouldn't use IOW() - the semantics are all wrong and it is very error prone. 

You want to generate a C structure that matches your register definition (probably with some fields marked 'volatile') and 'arrange' for a pointer to do uncached accesses (possibly by getting the linker script to generate an absolute symbol). 

 

You might find it easier to dual-port an internal memory block (tightly coupled to the cpu) and use that for data transfer. 

The 'actions' could be initiated by an Avalon write, but you might find that a multi-cycle custom instruction is more appropriate.
0 Kudos
Altera_Forum
Honored Contributor II
548 Views

 

--- Quote Start ---  

The nios is only ever going to generate 32bit Avalon cycles - so your 64bit transfer will always be two Avalon bus cycles. 

Personally I wouldn't use IOW() - the semantics are all wrong and it is very error prone. 

You want to generate a C structure that matches your register definition (probably with some fields marked 'volatile') and 'arrange' for a pointer to do uncached accesses (possibly by getting the linker script to generate an absolute symbol). 

 

You might find it easier to dual-port an internal memory block (tightly coupled to the cpu) and use that for data transfer. 

The 'actions' could be initiated by an Avalon write, but you might find that a multi-cycle custom instruction is more appropriate. 

--- Quote End ---  

 

 

Hi dsl, I came across your reply on this thread when I was searching for solution I have with writing a value to an pio from Nios as I posted here (http://www.alteraforum.com/forum/showthread.php?t=48744

 

You mentioned "Personally I wouldn't use IOW() - the semantics are all wrong and it is very error prone.". So , what do you mean by "the semantics are all wrong" and could you please suggest on what to use to replace IOWR? Thank you
0 Kudos
Altera_Forum
Honored Contributor II
548 Views

I think he would meant using IOWR_32DIRECT instead.

0 Kudos
Reply