Loop inside case?

Discussion in 'VHDL' started by Travis, Sep 13, 2006.

  1. Travis

    Travis Guest

    Pardon me if this is a trivial question but my VHDL experience is
    limited and rusty (sorry, I'm verilog). I'm modifying a pre-existing
    unit that manages access to a giant register bank. This is handled
    with a huge case statement and I need to modify the case statement to
    support a new subset of addresses. These addresses correspond to a big
    contiguous block of data and so I was hoping I could use a loop to
    simplify the coding. Essentially what I'm looking for is the ability
    to do the equivalent of the following:

    case addr is
    ...
    for i in 0 to count-1 loop
    when (new_base_addr + i) =>
    dataout <= new_reg(i);
    end loop
    ...
    end case

    I've tried a standard for loop and a for-generate loop but neither will
    synthesize (using the Xilinx Synthesis Tool). If anybody can show me
    how to do this without manually entering every individual case that
    would be awesome. Thanks.
    - Travis
     
    Travis, Sep 13, 2006
    #1
    1. Advertising

  2. Travis wrote:

    > case addr is
    > ...
    > for i in 0 to count-1 loop
    > when (new_base_addr + i) =>
    > dataout <= new_reg(i);
    > end loop
    > ...
    > end case


    You cannot interleave a case statement and a loop statement as you try
    to do. Also, the choices of a case statement must be static, so you
    cannot use a variable or signal in a choice expression (so you cannot
    use new_base_addr, unless it is a constant).

    Why not use an IF statement, possibly IF .. ELSIF .. ELSIF ..

       for i in 0 to count-1 loop
          if addr = new_base_addr + i then
             dataout <= new_reg(i);
    end if;
       end loop;

    --
    Paul.
     
    Paul Uiterlinden, Sep 13, 2006
    #2
    1. Advertising

  3. Travis

    Travis Guest

    Paul Uiterlinden wrote:
    > Travis wrote:
    >
    > > case addr is
    > > ...
    > > for i in 0 to count-1 loop
    > > when (new_base_addr + i) =>
    > > dataout <= new_reg(i);
    > > end loop
    > > ...
    > > end case

    >
    > You cannot interleave a case statement and a loop statement as you try
    > to do. Also, the choices of a case statement must be static, so you
    > cannot use a variable or signal in a choice expression (so you cannot
    > use new_base_addr, unless it is a constant).
    >
    > Why not use an IF statement, possibly IF .. ELSIF .. ELSIF ..
    >
    > for i in 0 to count-1 loop
    > if addr = new_base_addr + i then
    > dataout <= new_reg(i);
    > end if;
    > end loop;
    >
    > --
    > Paul.


    So there's no way to use a loop to generate the choices, even static
    choices, in a case statement? That's unfortunate. As mentioned, I'm
    modifying a pre-existing unit and simply updated the range of choices
    in the case statement, so switching to an IF statement isn't really an
    option without major refactoring. Is my only other option then to hand
    code each choice (when new_base_addr + 1 ... when new_base_addr + 2 ...
    etc..)? Thanks.
    - Travis
     
    Travis, Sep 13, 2006
    #3
  4. Travis

    Andy Ray Guest

    Travis wrote:
    > Paul Uiterlinden wrote:
    >> Travis wrote:
    >>
    >>> case addr is
    >>> ...
    >>> for i in 0 to count-1 loop
    >>> when (new_base_addr + i) =>
    >>> dataout <= new_reg(i);
    >>> end loop
    >>> ...
    >>> end case

    >> You cannot interleave a case statement and a loop statement as you try
    >> to do. Also, the choices of a case statement must be static, so you
    >> cannot use a variable or signal in a choice expression (so you cannot
    >> use new_base_addr, unless it is a constant).
    >>
    >> Why not use an IF statement, possibly IF .. ELSIF .. ELSIF ..
    >>
    >> for i in 0 to count-1 loop
    >> if addr = new_base_addr + i then
    >> dataout <= new_reg(i);
    >> end if;
    >> end loop;
    >>
    >> --
    >> Paul.

    >
    > So there's no way to use a loop to generate the choices, even static
    > choices, in a case statement? That's unfortunate. As mentioned, I'm
    > modifying a pre-existing unit and simply updated the range of choices
    > in the case statement, so switching to an IF statement isn't really an
    > option without major refactoring. Is my only other option then to hand
    > code each choice (when new_base_addr + 1 ... when new_base_addr + 2 ...
    > etc..)? Thanks.
    > - Travis
    >


    Hi,

    You can do

    when 32 to 63 =>
    dataout <= new_reg( addr );

    or something similar. It will depend exactly how addr is specified as
    this only works with specific types (ie ints not std_logic_vectors).

    You may yet have some refactoring to do...

    Cheers,

    Andy
     
    Andy Ray, Sep 13, 2006
    #4
  5. Travis wrote:


    > So there's no way to use a loop to generate the choices, even static
    > choices, in a case statement? That's unfortunate. As mentioned,
    > I'm modifying a pre-existing unit and simply updated the range of
    > choices in the case statement, so switching to an IF statement isn't
    > really an
    > option without major refactoring. Is my only other option then to
    > hand code each choice (when new_base_addr + 1 ... when new_base_addr
    > + 2 ...
    > etc..)? Thanks.


    I'm not sure if this would work (no compiler at hand at the moment):

    for i in 0 to count-1 loop
    case addr is
    when new_base_addr + i =>
    dataout <= new_reg(i);
    when ...
    end case;
    end loop;

    After all, i is a constant. But VHDL is a bit peculiar with regards to
    choices in the case statement. See e.g.
    http://www.vhdl.org/comp.lang.vhdl/FAQ1.html#static.

    --
    Paul.
     
    Paul Uiterlinden, Sep 13, 2006
    #5
  6. Travis

    KJ Guest

    "Travis" <> wrote in message
    news:...
    > Pardon me if this is a trivial question but my VHDL experience is
    > limited and rusty (sorry, I'm verilog). I'm modifying a pre-existing
    > unit that manages access to a giant register bank. This is handled
    > with a huge case statement and I need to modify the case statement to
    > support a new subset of addresses. These addresses correspond to a big
    > contiguous block of data and so I was hoping I could use a loop to
    > simplify the coding. Essentially what I'm looking for is the ability
    > to do the equivalent of the following:
    >
    > case addr is
    > ...
    > for i in 0 to count-1 loop
    > when (new_base_addr + i) =>
    > dataout <= new_reg(i);
    > end loop
    > ...
    > end case
    >
    > I've tried a standard for loop and a for-generate loop but neither will
    > synthesize (using the Xilinx Synthesis Tool). If anybody can show me
    > how to do this without manually entering every individual case that
    > would be awesome. Thanks.
    > - Travis

    How about something like this

    if (Address is in the new range) then
    Do your new stuff here
    else
    case -- The existing case statement
    end case;
    end if;

    KJ
     
    KJ, Sep 13, 2006
    #6
  7. Travis

    Travis Guest

    KJ wrote:
    > "Travis" <> wrote in message
    > news:...
    > > Pardon me if this is a trivial question but my VHDL experience is
    > > limited and rusty (sorry, I'm verilog). I'm modifying a pre-existing
    > > unit that manages access to a giant register bank. This is handled
    > > with a huge case statement and I need to modify the case statement to
    > > support a new subset of addresses. These addresses correspond to a big
    > > contiguous block of data and so I was hoping I could use a loop to
    > > simplify the coding. Essentially what I'm looking for is the ability
    > > to do the equivalent of the following:
    > >
    > > case addr is
    > > ...
    > > for i in 0 to count-1 loop
    > > when (new_base_addr + i) =>
    > > dataout <= new_reg(i);
    > > end loop
    > > ...
    > > end case
    > >
    > > I've tried a standard for loop and a for-generate loop but neither will
    > > synthesize (using the Xilinx Synthesis Tool). If anybody can show me
    > > how to do this without manually entering every individual case that
    > > would be awesome. Thanks.
    > > - Travis

    > How about something like this
    >
    > if (Address is in the new range) then
    > Do your new stuff here
    > else
    > case -- The existing case statement
    > end case;
    > end if;
    >
    > KJ


    Thanks to all for your suggestions. I think KJ's suggestion is
    probably the only method that wouldn't require major rework but I had
    already gone the route of putting together a perl script to generate
    the code for me. I'm pretty happy with the result so I thought I'd
    share it incase somebody else might find it useful. Thanks again.

    ------------------------------------------------

    #!/usr/local/bin/perl -w
    # Script:
    # textgen.pl
    # Description:
    # Generates repeating strings with auto-increment integer or hex
    values.
    # Since double-quotes cannot be inside the input string, use '\q' to
    insert a
    # placeholder for a double-quote (").
    # Arguments:
    # 1 - The number of repetitions
    # 2 - String with %#d (integer), %#x (hex) or %#b (binary)
    placeholders.
    # This uses the C-style printf formatting native to Perl.
    # 3+ - The third and all remaining arguments are indicators of how
    to
    # update the values in the string. They take the format of
    X±Y, where
    # X is the initial value, ± is increment or decrement and Y
    is the
    # amount to increment or decrement.
    # Sample:
    # textgen.pl 3 "#%d, 0x%02x\n, \q%05b\q" 10-3 15+16 1+4
    # > Output:
    # #10, 0x0F, "00001"
    # #7, 0x1F, "00101"
    # #4, 0x2F, "01001"
    ###############################################################################

    use strict;

    if($#ARGV < 1) {
    die "Too few arguments";
    }

    my $i;
    my $reps = $ARGV[0];
    my $text = $ARGV[1];

    # Convert input text linebreaks to real linebreaks
    $text =~ s/\\n/\n/g;
    # Convert \q to double-quote
    $text =~ s/\\q/\\\"/g;

    # Extract the value/increment pairs into arrays
    my @values = splice(@ARGV, 2, $#ARGV);
    my @inc = @values;

    # Convert value/increment pairs to just values
    for($i = 0; $i <= $#values; $i++) {
    $values[$i] =~ /(\d+)[\+|-]\d+/;
    $values[$i] = $1;
    }
    # Convert value/increment pairs to just increments
    for($i = 0; $i <= $#inc; $i++) {
    $inc[$i] =~ /\d+([\+|-]\d+)/;
    $inc[$i] = $1;
    # Remove '+' signs
    $inc[$i] =~ s/\+//g;
    }
    # Extract the placeholders
    my @places = ($text =~ /(%\d*[d|x|b])/g);

    # Verify placeholders and arguments compatibility
    if($#places != $#values) {
    die "Invalid argument list";
    }

    # Print output
    for(; $reps > 0; $reps--) {
    # Create the value list
    my $val;
    my $valuelist = '';
    foreach $val (@values) {
    $valuelist .= ", $val";
    }

    # Create printf function from input string and current values
    my $evalstr = "printf(\"$text\"$valuelist)";
    # Evaluate (print out) printf string
    eval $evalstr;

    # Update the values
    for($i = 0; $i <= $#values; $i++) {
    $values[$i] += $inc[$i];
    }
    }
     
    Travis, Sep 14, 2006
    #7
  8. Travis

    Andy Guest

    Since loops are unrolled in synthesis (and therefore must be staticly
    bound), the index is "treated as static" in synthesis. This treatment
    only exists in the backend, and has no effect on legal vhdl staticness.

    Case statement targets must be locally static, meaning that at analysis
    time, before elaboration, the compiler must be able to know the value
    of each target. Among other things, even generic values and deferred
    constants (i.e. whose values are only defined in a package body) cannot
    be used as case statement targets, since the compiler must be able to
    verify, at analysis time, that all possible choices are covered exactly
    once.

    Andy


    Paul Uiterlinden wrote:
    > Travis wrote:
    >
    >
    > > So there's no way to use a loop to generate the choices, even static
    > > choices, in a case statement? That's unfortunate. As mentioned,
    > > I'm modifying a pre-existing unit and simply updated the range of
    > > choices in the case statement, so switching to an IF statement isn't
    > > really an
    > > option without major refactoring. Is my only other option then to
    > > hand code each choice (when new_base_addr + 1 ... when new_base_addr
    > > + 2 ...
    > > etc..)? Thanks.

    >
    > I'm not sure if this would work (no compiler at hand at the moment):
    >
    > for i in 0 to count-1 loop
    > case addr is
    > when new_base_addr + i =>
    > dataout <= new_reg(i);
    > when ...
    > end case;
    > end loop;
    >
    > After all, i is a constant. But VHDL is a bit peculiar with regards to
    > choices in the case statement. See e.g.
    > http://www.vhdl.org/comp.lang.vhdl/FAQ1.html#static.
    >
    > --
    > Paul.
     
    Andy, Sep 15, 2006
    #8
  9. Andy wrote:

    > Since loops are unrolled in synthesis (and therefore must be
    > staticly bound), the index is "treated as static" in synthesis. This
    > treatment only exists in the backend, and has no effect on legal
    > vhdl staticness.
    >
    > Case statement targets must be locally static, meaning that at
    > analysis time, before elaboration, the compiler must be able to know
    > the value of each target. Among other things, even generic values
    > and deferred constants (i.e. whose values are only defined in a
    > package body) cannot be used as case statement targets, since the
    > compiler must be able to verify, at analysis time, that all possible
    > choices are covered exactly once.


    Thanks for the clarification. Of course I knew all this, but it had
    sunken too deep for direct access. ;-)

    --
    Paul.
     
    Paul Uiterlinden, Sep 16, 2006
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alexander Korsunsky

    break inside of case- statement inside of loop

    Alexander Korsunsky, Feb 25, 2007, in forum: C Programming
    Replies:
    25
    Views:
    1,084
    Richard Heathfield
    Feb 27, 2007
  2. Roedy Green
    Replies:
    3
    Views:
    443
    Mike Schilling
    Sep 13, 2008
  3. Aggelos

    Loop Inside loop for writing text lines

    Aggelos, Nov 11, 2003, in forum: ASP General
    Replies:
    2
    Views:
    203
    Aggelos
    Nov 12, 2003
  4. aa
    Replies:
    14
    Views:
    334
  5. Isaac Won
    Replies:
    9
    Views:
    403
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page