Recursive function to generate mux output

Discussion in 'VHDL' started by Edward Watts, Jan 24, 2006.

  1. Edward Watts

    Edward Watts Guest

    Hi all,

    I posted a short while ago about using generate statements to select
    out sections of a parallel signal or to combine sections into a
    parallel signal (serial-ish to parallel and parallel to serial-ish
    converters)
    http://groups.google.com/group/comp.lang.vhdl/browse_thread/thread/67501029fa8041c6

    The input serial to parallel works fine, and is synthesised and
    general.
    The output parallel to serial syntactically is fine, but won't
    synthesis:
    I'm using Xilinx 7.1i Foundation, and the code is the following

    output_g : for i in 0 to NumberOfOutputOperands-1
    generate
    outputSlice_g : for j in 0 to NumberOfOutputBitGroups-1
    generate
    outputSliceLast_g : if (j = NumberOfOutputBitGroups-1) and (i =
    NumberOutputOperands-1)
    generate
    process(clk)
    if rising_edge(clk) then
    if RSTIn = '1' then
    ...reset code.
    else
    result_internal <= result(i)( (j+1)*OutputWidth - 1 downto
    j*OutputWidth );
    -- other IO stuff.
    end if;
    end if;
    end process;
    end generate;
    -- similar generate for all other output slices.
    end generate;
    end generate;

    And the problem with this code is that a synthesis error occurs:
    multi-source in Unit ... on signal result_internal<...>

    VHDL requires that the process statement be inside the generate
    statement, and not the other way around. Is there an option to use
    perhaps a block statement to replicate the behaviour.

    I've now tried to create a mux tree structure with a function, which
    crashed the synthesis tool.
    Here's the function, based off a reduction operator:

    There were two errors raised, one at line 0 of this file of "Overflow
    in constant operation", and the other is pointed out in the source
    code.

    function mux_build ( arg: std_logic_vector, a : std_logic_vector )
    return std_logic_vector is
    variable Result, Upper, Lower : std_logic_vector( SizeOfOutputBus-1
    downto 0 );
    variable Half : integer;
    variable internal : std_logic_vector( arg'length-1 downto 0 );
    begin
    internal := arg;
    if ( internal'length = SizeOfOutputBus ) then
    Result := internal;
    else
    Half := 2**(internal'length-1);
    Upper := mux_build( internal( internal'left downto Half ), a );
    --gives "Use of null array slice on signal <internal> is not supported"
    Lower := mux_build( internal( Half-1 downto internal'right), a );
    if ( a( internal'length-SizeOfOutputBus-1) = '1' ) then
    Result := Upper;
    else
    Result := Lower;
    end if;
    end if;
    return Result;
    end function;

    Can someone help me with the nitty gritty of the language? I haven't
    had too much experience with functions and synthesis.

    Thanks,
    ed.
     
    Edward Watts, Jan 24, 2006
    #1
    1. Advertising

  2. "Edward Watts" <> writes:

    > I've now tried to create a mux tree structure with a function, which
    > crashed the synthesis tool.
    > Here's the function, based off a reduction operator:
    >
    > There were two errors raised, one at line 0 of this file of "Overflow
    > in constant operation", and the other is pointed out in the source
    > code.
    >
    > function mux_build ( arg: std_logic_vector, a : std_logic_vector )
    > return std_logic_vector is
    > variable Result, Upper, Lower : std_logic_vector( SizeOfOutputBus-1
    > downto 0 );
    > variable Half : integer;
    > variable internal : std_logic_vector( arg'length-1 downto 0 );
    > begin
    > internal := arg;
    > if ( internal'length = SizeOfOutputBus ) then
    > Result := internal;
    > else
    > Half := 2**(internal'length-1);
    > Upper := mux_build( internal( internal'left downto Half ), a );
    > --gives "Use of null array slice on signal <internal> is not supported"
    > Lower := mux_build( internal( Half-1 downto internal'right), a );
    > if ( a( internal'length-SizeOfOutputBus-1) = '1' ) then
    > Result := Upper;
    > else
    > Result := Lower;
    > end if;
    > end if;
    > return Result;
    > end function;
    >
    > Can someone help me with the nitty gritty of the language? I haven't
    > had too much experience with functions and synthesis.


    You have left out what widths you are testing with, but my best guess,
    is that the function barfs when you get down to 1 bit wide vectors (0
    downto 0).

    Say your input isn't a multiple of SizeOfOutputBus, then the
    internal'length = SizeOfOutputBus test will never succeed, and you end
    up trying to split a 1-bit bus in one of the halfs.

    Regards,


    Kai
    --
    Kai Harrekilde-Petersen <khp(at)harrekilde(dot)dk>
     
    Kai Harrekilde-Petersen, Jan 24, 2006
    #2
    1. Advertising

  3. Edward Watts wrote:

    > And the problem with this code is that a synthesis error occurs:
    > multi-source in Unit ... on signal result_internal<...>


    Generate loops tend to have problems at the edges.
    Sometimes you need a process or two outside the loop.

    I find vhdl simulation a very quick way to
    debug problems like this.

    I find that a single process design
    style is a good way to *eliminate*
    problems like this.


    -- Mike Treseler
     
    Mike Treseler, Jan 24, 2006
    #3
  4. Edward Watts

    Edward Watts Guest

    Replying to both posts.

    Mike Treseler helped out with:

    > I find that a single process design
    > style is a good way to *eliminate*
    > problems like this.


    The issue is we don't want to retype out all the different multiples of
    OutputBusWidth each time we change the size of the internal
    representation (possibly up to 1024 bits). I'm not sure of a VHDL
    pattern that deals with this problem, but i'm working on another
    generate option. If I get it working, I'll post both the input and
    output solutions for critique or dust-collecting :)

    Kai Harrekilde-Petersen chipped in with:
    > Say your input isn't a multiple of SizeOfOutputBus, then the
    > internal'length = SizeOfOutputBus test will never succeed, and you end
    > up trying to split a 1-bit bus in one of the halfs.

    So a guard condition on the 1-bit wide bus should help...
    However the function assign will barf on the usage, since it should
    always return a value of
     
    Edward Watts, Jan 26, 2006
    #4
  5. Edward Watts

    Edward Watts Guest

    Replying to both posts.

    Mike Treseler helped out with:

    > I find that a single process design
    > style is a good way to *eliminate*
    > problems like this.


    The issue is we don't want to retype out all the different multiples of
    OutputBusWidth each time we change the size of the internal
    representation (possibly up to 1024 bits). I'm not sure of a VHDL
    pattern that deals with this problem, but i'm working on another
    generate option. If I get it working, I'll post both the input and
    output solutions for critique or dust-collecting :)

    Kai Harrekilde-Petersen chipped in with:
    > Say your input isn't a multiple of SizeOfOutputBus, then the
    > internal'length = SizeOfOutputBus test will never succeed, and you end
    > up trying to split a 1-bit bus in one of the halfs.


    So a guard condition on the 1-bit wide bus should help the synthesis
    tool.
    The input to the function is always some multiple of SizeOfOutputBus,
    but not necessarily 2^n * SizeOfOutputBus.
    However the function assign will barf on the usage, if it returns a
    1-bit wide answer, since it should always return a value of
    SizeOfOutputBus wide. Is there a method of constraining the input sizes
    using some sort of assertion or precondition (I know it's not Eiffel)
    whereby I can indicate to the compiler what it can assume?

    cheers,
    ed.

    PS sorry if this is a double post. I may have tapped the post button
    accidentally
     
    Edward Watts, Jan 26, 2006
    #5
  6. Edward Watts wrote:

    > Mike Treseler helped out with:
    >
    >>I find that a single process design
    >>style is a good way to *eliminate*
    >>problems like this.

    >
    > The issue is we don't want to retype out all the different multiples of
    > OutputBusWidth each time we change the size of the internal
    > representation (possibly up to 1024 bits).


    Understood. My point was that I would
    apply the generic dimensions to a some complex data type
    to cover the same design in a single process.
    I would find this easier to sim and debug.

    -- Mike Treseler
     
    Mike Treseler, Jan 27, 2006
    #6
  7. Edward Watts

    Edward Watts Guest

    Here's the solution to all my problems.
    I was attempting to convert a std_logic_vector signal to an integer to
    use as an index into the output signal. Xilinx told me that I couldn't
    use to_integer (error was "to_integer cannot have such operands in this
    context."). However using conv_integer worked fine.

    So here it is:
    OutputBitGroupCounter is std_logic_vector(OutputBitGroupCounterBits-1
    downto 0)
    resultIn is std_logic_vector(N_Bits-1 downto 0);
    result_internal is std_logic_vector(SizeOfOutputBus-1 downto 0);
    out_internal is array(OutputBitGroupCounter_MAX downto 0) of
    std_logic_vector(SizeOfOutputBus-1 downto 0);
    outputCounting is a flag that is set when outputs are being read

    -- use a generate signal to clock the N bit wide internal signal into a
    2D array
    outputSelect_g : for i in OutputBitGroupCounter_MAX downto 0 generate
    process(CLK)
    begin
    --clock inputs into each part of the array slice.
    if rising_edge(CLK) then
    if RST = '1' then
    out_internal(i) <= (others => '0');
    elsif expFinished = '1' then
    out_internal(i) <= resultIn( (i+1)*SizeOfOutputBus-1 downto
    i*SizeOfOutputBus);
    end if;
    end if;
    end process;
    end generate;

    -- followed with the almost trivial:
    process(CLK)
    begin
    if rising_edge(CLK) then
    if RST = '1' then
    result_internal <= (others => '0');
    elsif outputCounting = '1' then
    result_internal <= out_internal( conv_integer(
    outputBitGroupCounter ) );
    end if;
    end if;
    end process;

    ed.
     
    Edward Watts, Jan 30, 2006
    #7
    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. valentin tihomirov

    operation on mux output

    valentin tihomirov, Sep 22, 2004, in forum: VHDL
    Replies:
    5
    Views:
    1,205
    valentin tihomirov
    Sep 23, 2004
  2. conradojr
    Replies:
    5
    Views:
    634
  3. n00m
    Replies:
    12
    Views:
    1,119
  4. RADNOR

    MUX with generate statement

    RADNOR, Jul 20, 2011, in forum: VHDL
    Replies:
    3
    Views:
    3,012
    RADNOR
    Jul 20, 2011
  5. Guest
    Replies:
    2
    Views:
    266
    Guest
    Mar 30, 2005
Loading...

Share This Page