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