Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

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

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.

So, I define it as

alt_16 value=0; 

And I read the value using:

value =IORD_ALTERA_AVALON_PIO_DATA(base); 

The problem is it always give me positive value every time it is read from this line even though I am sure it has both positive and negative value from VHDL code.

printf("\n value= %.2f \n", (float) value);  

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.

signal a     : sfixed(7 downto -6);

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.

Thank you in advance.

7 Replies

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

    As the NIOS II is a microprocessor, the structure does not support any other than 8, 16, 32 Bits width.

    Nevertheless... I'd suggest to rescale the 14Bit VHDL value to a 16Bit VHDL value prior reading it by the NIOSII by multiplying with "4" :-)

    Depending on the data representation this might be by a simple concatenate &"00" (for signed vector) or typing a "*4" to implement the multiplication. This also depends on the VHDL package you are using (which functions are defined and thus synthesizable)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You are aligning the data on the LSB. Don't do that - you want to align it on the sign bit.

    For a 32-bit signed integer, bit-31 is the sign bit. For a 14-bit signed number, bit-13 is the sign bit: out <= in & "00"

    Alternatively, you can propagate the sign bit to all of the high bits: out <= (12 downto 0 => in(12 downto 0), others => in(13)) - or something like that.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I thought of a better way - you shouldn't (can't) multiply because that preserves the sign, which is wrong. Shifting is OK, but it's too specific.

    Use the built-in type conversions - convert the 14-bit to an integer (which should preserve the sign), then convert that integer to a std_logic_vector with the proper size for the Avalon port:

    port <= to_std_logic_vector(to_integer(data),port'size);

    You get to fix the syntax errors.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Why not just sign extend?

    output <= resize(a, a'high+2, a'low);

    --- Quote End ---

    When using integer conversion one doesn't need to know the size difference when writing the code - it's more portable.

    Eventually one will forget why 'high+2 was used.

    Odds are the synthesis output is the same for both.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    When using integer conversion one doesn't need to know the size difference when writing the code - it's more portable.

    Eventually one will forget why 'high+2 was used.

    Odds are the synthesis output is the same for both.

    --- Quote End ---

    But the OP is using the sfixed type, and this function exists exactly for this purpose. Using the to_integer function from sfixed directly will remove the fractional part, so you need to use appropriate type conversions.

    Your code also used the non-standard std_logic_arith library to convert the value.