Forum Discussion

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

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

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 Nios II system. I use C code for NIos II system. This is my code:

 value =IORD_ALTERA_AVALON_PIO_DATA(base); 
to read the 24-bit signed signal. I define it as
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.
printf("\n value= %d \n", value);                                                                                   
Any idea what went wrong??? sorry for the simple question... Thank you in advance

6 Replies

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

    If I understand you correctly, you are reading a 24 bit signed value from a 24 bit port into a 32 bit signed variable then you have extend the most significant bit into bits 24 through 31.

    1 represented with 24 bits is 0x000001, which when read as a 32 bit number is 0x00000001 which is the same.

    -1 represented with 24 bits is 0xffffff, which when read as a 32 bit number if 0x00ffffff which is a positive value of 16777215.

    When the msb is extended into bits 24 thru 31 you get 0xffffffff which is -1.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    If I understand you correctly, you are reading a 24 bit signed value from a 24 bit port into a 32 bit signed variable then you have extend the most significant bit into bits 24 through 31.

    1 represented with 24 bits is 0x000001, which when read as a 32 bit number is 0x00000001 which is the same.

    -1 represented with 24 bits is 0xffffff, which when read as a 32 bit number if 0x00ffffff which is a positive value of 16777215.

    When the msb is extended into bits 24 thru 31 you get 0xffffffff which is -1.

    --- Quote End ---

    Hi kflynn,

    Thanks so much for your reply.

    Yes, you understand it correctly. But, there is no way for me to define it as 24 bits since the standard are alt_8, alt_16 and alt_32. Thanks for telling me that I should extend the msb from 24 bits through 31 bits . "When the msb is extended into bits 24 thru 31 you get 0xffffffff which is -1."

    Could you suggest to me what can be done in order to extend the msb from 24 bits through 31 bits in C code? I program the Nios in C code. Any link or resources would be much appreciated, really thanks for your precious time.

    Thanks in advance.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Multiple ways,

    alt_32 n;

    // read the 24 bit signed signal

    n = read_port;

    // if the sign bit is set extend it to bit 31

    if (n & 0x08000000)

    n |= 0xf0000000;

    Is the pio module your custom vhdl code or is it a qsys library module?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The easiest way to sign extend a number is:

    
     wire  numAs24 = -24'd1245
    wire  numAs32 = {{(8){numAs24}},numAs24};
    

    Granted the above is in Verilog, but it should be easy to turn it into the equivalent VHDL. Basically all it does is copy bit 23 into all of the upper bits.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Multiple ways,

    alt_32 n;

    // read the 24 bit signed signal

    n = read_port;

    // if the sign bit is set extend it to bit 31

    if (n & 0x08000000)

    n |= 0xf0000000;

    Is the pio module your custom vhdl code or is it a qsys library module?

    --- Quote End ---

    Thanks kflynn for your reply... To answer your question, it is the standard qsys pio module.

    If I understand correctly, guess it is typo from you? it should be as follow:

    if (n & 0x00800000)
       n |= 0xff000000;

    Please correct me if I am wrong, thank you!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Yes that was a typo and yours is the correct version.

    Is the qsys generated hdl file your top level or do you instantiate it in another source file. If you instantiate it in another file you can use the idea from TCWORLD to sign extend the reading in the hardware automatically. Then your reads of the 24 bit signal will always be extended to 32 bits.

    If the qsys output is named MyNios then a top level file would work like this

    constant cA2dDataBusMSB :natural := 23;

    constant cNiosBusMSB : natural := 31;

    sAdcData(cA2dDataBusMSB : 0 <= adc_pins(cA2dDataBusMSB downto 0);

    -- Bridge the difference between the NIOS bus width and the ADC bus width.

    BridgeBus:

    for busbit in 1 to (cNiosBusMSB-cA2dDataBusMSB ) generate -- Generate 8 bits

    sAdcData(busbit+cA2dDataBusMSB ) <= not adc_pins(cA2dDataBusMSB); -- replicate bit 23 onto bits 24 through 31.

    end generate;

    Hope this helps