Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Announcements
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.
12453 Discussions

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

Altera_Forum
Honored Contributor II
1,469 Views

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

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
Honored Contributor II
177 Views

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
Honored Contributor II
177 Views
Altera_Forum
Honored Contributor II
177 Views

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
Honored Contributor II
177 Views

Why not just sign extend? 

 

output <= resize(a, a'high+2, a'low);
Altera_Forum
Honored Contributor II
177 Views

 

--- 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
Honored Contributor II
177 Views

 

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