# How to read signed values from FPGA in VHDL to Nios II system

Status
Not open for further replies.

#### wannaknow

##### Junior Member level 2
HI, I have a very simple question but I have no idea what went wrong. Basically I have a 24-bit signed signal from VHDL block fed into Altera Nios II system. I use C code for NIos II system. This is my code:Code:
Code:
 value =IORD_ALTERA_AVALON_PIO_DATA(base);
to read the 24-bit signed signal. I define it as Code:
Code:
alt_32 value=0;
The problem is it always give me positive value every time read from this line even though I am sure it is negative value from VHDL code. Code:
Code:
printf("\n value= %d \n", value);
Any idea what went wrong??? sorry for the simple question... Thank you in advance

Last edited by a moderator:

#### TrickyDicky

Re: How to read a 24-bit signed signal from VHDL block fed in Nios II system - always

Are you sign extended the 24 bit number into the 32 bit reg correctly?

#### wannaknow

##### Junior Member level 2
Hi,

I am reading a 14-bit signed value from a 14-bit vhdl port into a 16 bit signed variable in Nios II. There is no way for me to define it as 14 bits since the standard are alt_8, alt_16 and alt_32.

I define it as

Code:
[COLOR=#333333][FONT=myriad-pro]alt_16 value=0; [/FONT][/COLOR]

Code:
[COLOR=#333333][FONT=myriad-pro]value =IORD_ALTERA_AVALON_PIO_DATA(base); [/FONT][/COLOR]

The problem is it always give me positive value every time read from this line even though I am sure the value can be positive or negative value from VHDL code.

Code:
[COLOR=#333333][FONT=myriad-pro]printf("\n value= %.2f \n", (float) value);  [/FONT][/COLOR]

In the vhdl code, the 14 bits data is defined as follows: the msb represents the signed bit, the following 6 bits represent the magnitude, and the following 6 bits.

Code:
[COLOR=#333333][FONT=myriad-pro]signal a     : sfixed(7 downto -6);[/FONT][/COLOR]

I want to know,
1. How could I check if the value is positive or negative cause I have no idea how to read each of the binary bit in Nios C code?
2. Is it using 2's complement?

How could I do that in C code? I am using C code to program Nios II.

##### Super Moderator
Staff member
You should change the hardware to give the Nios a 16-bt signed value by doing the sign extension external to the Nios.

wannaknow

### wannaknow

Points: 2

#### wannaknow

##### Junior Member level 2
You should change the hardware to give the Nios a 16-bt signed value by doing the sign extension external to the Nios.

But, the 14-bit data can be positive, zero or negative.
The 14-bit-data is defined as follow: with msb as the sign bit, the following 6 bits are the magnitude for integer and the last 6 bits are the magnitude for fractional part.

I need to compute the real value of this binary representation into a decimal value of BOTH integer and fraction, for example, the value is 15282 (0011 1011 1011 0010), but it is not the real value, how to make sure I will get the value as -30.750015?

#### FvM

##### Super Moderator
Staff member
I tried to find a 14 bit number representation that matches the said value of -30.75 but didn't succeed. Apparently it's neither signed 8.6 fixed point nor a sign magnitude format with 6 fractional bits. How do you know that 11 1011 1011 0010 is representing -30.75?

Fractional or fixed point formats can be defined in VHDL but there's no respective number format in C. You can use 16 bit signed with a scale factor of 1/64. To print the number, you'll usuall convert it to float.

#### wannaknow

##### Junior Member level 2
Data transfer between fpga block (14 bits) in vhdl and Nios II system (16 bits)

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.

Code:
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:

Code:
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:

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".

Code:
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:

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

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

Code:
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.

Last edited by a moderator:

#### wannaknow

##### Junior Member level 2
You should change the hardware to give the Nios a 16-bt signed value by doing the sign extension external to the Nios.

Hi, thank you for your reply, I just read this reply... I did give this a try, I still am getting the same output as in #7 where the output voltage and current keep changing , since I could not edit my original post, I have updated the content in #7. Does it have anything to do with timing or sampling issue then?

#### wannaknow

##### Junior Member level 2
I tried to find a 14 bit number representation that matches the said value of -30.75 but didn't succeed. Apparently it's neither signed 8.6 fixed point nor a sign magnitude format with 6 fractional bits. How do you know that 11 1011 1011 0010 is representing -30.75?

Fractional or fixed point formats can be defined in VHDL but there's no respective number format in C. You can use 16 bit signed with a scale factor of 1/64. To print the number, you'll usuall convert it to float.

Like you said, I use 16 bit signed with a scale factor of 1/64 to get the 6 fractional points...I managed to get this value converted correctly to floating point, but still I am having issue in #7, I thought they are not relevant that is why I created a new thread

#### FvM

##### Super Moderator
Staff member
The required sign extension to 16-bit can be performed by the resize() function. But you are doing it wrong because you are resizing to a vector with 14 bit length.

For the other points, you should provide a complete code example instead of two-line snippets which are lacking of most essential information.

#### wannaknow

##### Junior Member level 2
thanks, if I understand correctly, you mean this line (data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 7, -6))
here, I still resize it to 14 bit because I did extend the sign extension in C code, meaning the input to the C code is still 14 bits.

I also tried with another approach where I use (data <= to_slv(resize(scale*to_sfixed(in, 0, -11), 9, -6)) and to get the data of 16 bits directly fed to Nios. I got the same issue.

The required sign extension to 16-bit can be performed by the resize() function. But you are doing it wrong because you are resizing to a vector with 14 bit length.

For the other points, you should provide a complete code example instead of two-line snippets which are lacking of most essential information.

- - - Updated - - -

Ok, I thought I should make it simpler:

From vhdl, the data is the input to Nios.

Code:
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:

Code:
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".

Code:
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".

Code:
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?

Status
Not open for further replies.