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

Data transfer between fpga (14 bits) vhdl block to NIos II system (16 bits)

Altera_Forum
Honored Contributor II
1,747 Views

Hi, 

 

I am writing C code to program Altera Nios II system in Cyclone IV E. The Nios II system is used to control some custom FPGA blocks written in VHDL in Quartus II. 

 

 

In the vhdl block "a", "data" is defined as follow where it has a total of 14 bits, msb as the signed bit, the following 7 bits are integer and the last 6 bits are fractional. 

 

 

data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 7, -6)); 

 

"scale" is any number to represent the peak value, "in" is a sinusoidal waveform. "data" is the input to the Nios II. 

 

In the C code, initially, I read the data from vhdl block using the C code below: 

 

int16_t data=0; data = IORD_ALTERA_AVALON_PIO_DATA(data_base);  

 

In the C code, since Altera compiler only supports "8", "16" or "32" bits of data length, after I read "data", I have to check if "data" is negative, if it is, I need to pad the msb with bits '1' as shown in the following code:  

 

if (data & 0x2000) data |= 0xC000; 

 

After this, the Nios system do some calculation (multiply with "a" for instance) to give a new value of "data", say name it as "data_new". 

 

data_new=((float)data/ 64.0f)*(a); 

 

After the calculation, I want to assign "data_new" back to another custom block in vhdl say "block b". So I need to format the "data_new" back to 14 bits instead of 16 bits using the following code: 

 

if (data_new & 0x2000) data_new &= 0x3fff; 

 

Finally, I write the "data_new" back to another custom block in vhdl say "block b". 

 

IOWR_ALTERA_AVALON_PIO_DATA(data_new_base, (int16_t)data_new); 

 

I am sure something is wrong with the way I did above, cause I am expecting to get a constant output voltage and current but I kept getting output voltage and current that keep changing every second. I don't have this issue if I feed the data_new directly from one vhdl block to another vhdl block.  

 

Could you give me some hints? have been trying for a week still could not figure out . I am trying to form the question as clear as I could, please let me know if additional information should be provided, much appreciated, thank you.
0 Kudos
6 Replies
Altera_Forum
Honored Contributor II
589 Views

Why can't you adjust your VHDL code to output and accept 16 bit data. That seems like the simplest approach. Also, since all you are doing is scaling, why wouldn't you do this operation also in VHDL. You are creating a huge bottleneck in your data flow by using the NIOS to scale your data. Floating point operation in software are incredibly slow... Ideally, the NIOS should not be doing data processing, it should just be doing management.

0 Kudos
Altera_Forum
Honored Contributor II
589 Views

 

--- Quote Start ---  

Why can't you adjust your VHDL code to output and accept 16 bit data. That seems like the simplest approach. Also, since all you are doing is scaling, why wouldn't you do this operation also in VHDL. You are creating a huge bottleneck in your data flow by using the NIOS to scale your data. Floating point operation in software are incredibly slow... Ideally, the NIOS should not be doing data processing, it should just be doing management. 

--- Quote End ---  

 

 

Thanks Krasner for the reply... 

To answer your first question, yes you are right, I did change in the vhdl code so that the input to the NIos is always 16 bits. 

data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 9, -6)); 

Second question, actually there are some processing tasks being done in Nios, I just put *a as an example, sorry for the confusion... 

 

I am still having issue where the value sent from NIos to the fpga is not correct, I tried with iowr, iowr16direct and also using macros without iowr, but still the value sent to the fpga is not correct... I lost direction on which aspect to troubleshoot....sorry, I don't know what else information I should provide here? I updated in the following, I hope you could spend some time have a look, just to give a hint on what I can do, many thanks
0 Kudos
Altera_Forum
Honored Contributor II
589 Views

Ok, I thought I should make it simpler: 

 

From vhdl, the data is the input to Nios. 

 

 

data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 9, -6));  

"scale" is any number to represent the peak value, "in" is a sinusoidal waveform. "data" is the input to the Nios II. 

 

In the C code, initially, I read the data from vhdl block using the C code below: 

 

 

alt_16 data=0; data = IORD_ALTERA_AVALON_PIO_DATA(data_base); 

 

 

After this, the Nios system do some calculation (multiply with "a" for instance, where a is not a constant depending on calculation on some other inputs) to give a new value of "data", say name it as "data_new". 

 

 

 

data_new=(data)*(a); 

 

After the calculation, I want to assign "data_new" back to another custom block in vhdl say "block b".  

 

Finally, I write the "data_new" back to another custom block in vhdl say "block b". 

 

 

 

 

IOWR_ALTERA_AVALON_PIO_DATA(data_new_base, data_new); 

 

I am not getting the correct value of "data_new" fed to the fpga, what could be the causes? timing issue? clock? What aspects can I look into?
0 Kudos
Altera_Forum
Honored Contributor II
589 Views

Let me see if I understand your flow: 

 

VHDL Block A --> signed 16 bit input to NIOS --> Calculation in NIOS --> signed 16 bit output from NIOS --> VHDL Block B 

 

In this flow, the "Calculation in NIOS" is your bottleneck, especially since it seems to be floating point. Why not do: 

 

VHDL Block A --> VHDL Calculation Block --> VHDL Block B 

 

Say, you don't want to do this... Looking at your C code you use floating point to calculate data_new. Then you do a logic operation on it (& 0x2000). This might be the source of error. You should convert from float to hex before your do bit manipulations. Also, you may not even have to use floating point...
0 Kudos
Altera_Forum
Honored Contributor II
589 Views

 

--- Quote Start ---  

Let me see if I understand your flow: 

 

VHDL Block A --> signed 16 bit input to NIOS --> Calculation in NIOS --> signed 16 bit output from NIOS --> VHDL Block B 

 

In this flow, the "Calculation in NIOS" is your bottleneck, especially since it seems to be floating point. Why not do: 

 

VHDL Block A --> VHDL Calculation Block --> VHDL Block B 

 

Say, you don't want to do this... Looking at your C code you use floating point to calculate data_new. Then you do a logic operation on it (& 0x2000). This might be the source of error. You should convert from float to hex before your do bit manipulations. Also, you may not even have to use floating point... 

--- Quote End ---  

 

 

Thanks Krasner for your reply, much appreciated... 

 

VHDL Block A --> signed 16 bit input to NIOS --> Calculation in NIOS --> signed 16 bit output from NIOS --> VHDL Block B 

 

Yes, you are right, this flow is what I intend to do  

 

Regarding your second question, the calculation has to be done in NIios, I think I posted the same time as you, could you please see # 4, after taking your advice in# 3, I didn't use any floating point to calculate data_new.  

 

For your information, just a trial, I also try by directly reading data from vhdl block a, then without doing any calculation, then write directly to vhdl block b, still it is not producing a sine wave to vhdl block b...if I feed directly from vhdl block a to vhdl block b, I can see a sine wave sent to vhdl block b
0 Kudos
Altera_Forum
Honored Contributor II
589 Views

If you can, attach your project so that I can see what you are doing.

0 Kudos
Reply