Forum Discussion

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

Help with Bit Extraction

I have a basic question about the following:

MIN_GAIN : unsigned(13 downto 0) := b"10000000000000"; -- 0x2000

gain_in : in std_logic_vector(13 downto 0);

val : unsigned(13 downto 0); -- 14 bits

gain : std_logic_vector(15 downto 0); -- 16 bits

IN MY CODE I HAVE:

1.) val <= unsigned(gain_in)-MIN_GAIN;

2.) gain(13 downto 0) <= std_logic_vector((b"000"&x"00"& val(13 downto 11)) + 1); -- concatenation

How do you get rid of the second assignment? It seems reasonable that one should be able to

extract the bits in the first assignment statement. However I get an error when I do the following:

val <= (unsigned(gain_in-MIN_GAIN)(13 downto 11);

The code is subtracting a value MIN_GAIN and then shifting right by 11. One should be able to

do that shift in the first statement so that the second statement is not needed. The goal is to get

rid of that second statement and do the entire operation with one statement.

Anyone know what I'm doing wrong?

Thanks.

7 Replies

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

    --- Quote Start ---

    I have a basic question about the following:

    MIN_GAIN : unsigned(13 downto 0) := b"10000000000000"; -- 0x2000

    gain_in : in std_logic_vector(13 downto 0);

    val : unsigned(13 downto 0); -- 14 bits

    gain : std_logic_vector(15 downto 0); -- 16 bits

    IN MY CODE I HAVE:

    1.) val <= unsigned(gain_in)-MIN_GAIN;

    2.) gain(13 downto 0) <= std_logic_vector((b"000"&x"00"& val(13 downto 11)) + 1); -- concatenation

    How do you get rid of the second assignment? It seems reasonable that one should be able to

    extract the bits in the first assignment statement. However I get an error when I do the following:

    val <= (unsigned(gain_in-MIN_GAIN)(2 downto 0);

    The code is subtracting a value MIN_GAIN and then shifting right by 11. One should be able to

    do that shift in the first statement so that the second statement is not needed. The goal is to get

    rid of that second statement and do the entire operation with one statement.

    Anyone know what I'm doing wrong?

    Thanks.

    --- Quote End ---

    your topic and discussion is not helpful.

    It seems you want this

    result <= unsigned(gain_in) - MIN_GAIN; -- ok

    final_result <= result(13 downto 11);

    but you are adding 1 as well.

    Note that 2 bits + 1 needs 3 bits yet your final output is 14 bits???
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    your topic and discussion is not helpful.

    It seems you want this

    result <= unsigned(gain_in) - MIN_GAIN; -- ok

    final_result <= result(13 downto 11);

    but you are adding 1 as well.

    Note that 2 bits + 1 needs 3 bits yet your final output is 14 bits???

    --- Quote End ---

    Yes. I may have put the wrong bit numbers. I'll check that

    After the subtraction the result is shifted 11 bits. So bits

    13, 12, and 11 get moved into bit positions 2 ,1 and 0.

    This is then concatenated

    with 0's to get a final 14 bit vector. Thus, I have:

    final_result <= b"000" & x"00" & val(13 downto 11) + 1;

    I have two statements that accomplish this but would like to have only

    one statement because it's clocked and the second statement is

    one clock later.

    It seems to me that I should be able to do this entire operation in one statement as:

    gain = (b"000" & x"00" & (unsigned(gain_in) - MIN_GAIN)) + 1;

    So my question is how can I keep bits 13, 12, and 11 from the statement

    (unsigned(gain_in) - MIN_GAIN) ?

    Doing something like (unsigned(gain_in)-MIN_GAIN)(13 downto 11) doesn't work.

    Right now this temporary variable "val" has to be used which I'm trying to get rid of

    because it's off by 1 clock.

    Is there something one would prefix or postifx to ??? (unsigned(gain_in)-MIN_GAIN) ???

    to get just those bits 13, 12 and 11? I have had no luck finding it.

    So, the single equation looks like: bits 13, 12, and 11 only

    final_result <= (b"000" & x"00" & (unsigned(gain_in) - MIN_GAIN) ) + 1;

    This statement as it stands doesn't tell me what bits the subtraction will keep!

    Thank you for you reply.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You have two stages:

    subtraction followed by addition of 1 to those 3 bits

    first: it doesn't make much sense as you lose a lot of bits (11 bits set permanently to zero)

    second: if you want subtraction and addition in one clock then you might just put one of them outside the clocked process

    since either way it implies one clock period for both operations.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You have two stages:

    subtraction followed by addition of 1 to those 3 bits

    first: it doesn't make much sense as you lose a lot of bits (11 bits set permanently to zero)

    second: if you want subtraction and addition in one clock then you might just put one of them outside the clocked process

    since either way it implies one clock period for both operations.

    --- Quote End ---

    You mean:

    Put this outside in a concurrent statement:

    val = (unsigned(gain_in) - MIN_GAIN;

    Then, in the clocked process put:

    gain = b"000" & x"00" & val(13 downto 11);

    I did this a little while ago and it appears to work.

    The question is: Will the output of val be ready by the time the

    clock pulse comes? The clock is 40 MHz in a Virtex 4. That gives 25 ns

    to get through the subtractor logic to the gain register.

    Cadence simulations shows it's working OK.

    But isn't there a way to say you want only some particular

    bits in an expression like the above and do it in the clocked

    process? (A-B) is an expression giving a result of so many bits.

    What's wrong with (A-B)(13 downto 11) meaning that only bits

    13 to 11 will be used after the subtraction. Why does it have to

    be assigned to some signal?

    Thanks,

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

    --- Quote Start ---

    You mean:

    Put this outside in a concurrent statement:

    val = (unsigned(gain_in) - MIN_GAIN;

    Then, in the clocked process put:

    gain = b"000" & x"00" & val(13 downto 11);

    --- Quote End ---

    yes that is what I meant. It should be ok on 40MHz speed (usually).

    However, I don't get what you are aiming at. It will help if you tell us what you are trying to achieve in terms of concept (not code).

    Normally gain word is multiplied by signal and result is then truncated say by 11 bits.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    yes that is what I meant. It should be ok on 40MHz speed (usually).

    However, I don't get what you are aiming at. It will help if you tell us what you are trying to achieve in terms of concept (not code).

    Normally gain word is multiplied by signal and result is then truncated say by 11 bits.

    --- Quote End ---

    I really don't know.. I'm just given the equation. You have a 14 bit input and subtract that 14-bit input

    from 8192. Then you divide (right shift) by 2^11. Thus, one is essentially subtracting and only keeping

    bits 13, 12, 11.

    You know, in 'C you can write a statement and then use it as a pointer. You don't have to have

    the variable name. You can use an expression. So, it seemed reasonable to me that one could

    do the same thing in VHDL. I guess not.

    ((unsigned(gain_in) - MIN_GAIN) This expression is 14 bits. So why can't one just extract what bits

    one wants instead assigning it to a signal name? That way one can avoid using the concurrent

    statement altogether.

    As I mentioned before. Something like (unsigned(gain_in)-MIN_GAIN)(13 downto 11).

    The synthesizer should interpret this as perform the subtraction and from the result take bits

    13, 12 and 11. Unfortunately,, ISE doesn't do that. It gives and ERROR. So does Cadence.

    But in 'C' one can do something similar.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    yes that is what I meant. It should be ok on 40MHz speed (usually).

    However, I don't get what you are aiming at. It will help if you tell us what you are trying to achieve in terms of concept (not code).

    Normally gain word is multiplied by signal and result is then truncated say by 11 bits.

    --- Quote End ---

    Thanks again for your suggestion.