[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [f-cpu] about the ongoing work for the "stable" release

On Wed, Jan 02, 2002 at 04:14:34AM +0100, Yann Guidon wrote:
> can anybody have a look at "fanout_linear.vhdl" ?
> who can figure why it doesn't work with vanilla ?

It says:

	# -- Failure: t: signal has multiple drivers with no resolution function.

This is not true, of course - but vanilla doesn't grok it.  This happens
when certain combinations of range attributes are used (in particular,
'high and 'low seem to cause problems).  If you use explicit ranges,
e.g. `WIDTH-1 downto 0', everything is fine again.

I'll attach a fixed version that works for me. But the recursive version
will have to wait (BTW: did you mean a recursive entity, or a recursive
version of the binary_tree_index function?)

 Michael "Tired" Riepe <Michael.Riepe@stud.uni-hannover.de>
 "All I wanna do is have a little fun before I die"
-- f-cpu/vhdl/common/fanout_linear.vhdl - fanout tree (2**n) for the F-CPU
-- Copyright (C) 2001 Yann GUIDON (whygee@f-cpu.org)
-- created sam dec  1 00:39:05 GMT 2001
-- version jeu dec  6 16:28:31 GMT 2001 : stripped from fanout_tree.vhdl
-- changed Thu Jan  3 02:49:09 CET 2002 (Michael Riepe):
-- added workaround for broken 'low and 'high attributes in Vanilla VHDL
-- This program is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- GNU General Public License for more details.
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-- This component implements a balanced fanout tree, for use when a signal
-- must be sent to more than 2**n inputs, where n > 2.
-- This version is a binary tree for synthesis. It tries to trick the
-- "dumb" optimizers into thinking that the whole tree contains different
-- signals and values, so that the nets won't be tied dumbly together
-- (which would void the use of this component). Using inverters,
-- which are somewhat faster than buffers that are probably not inferred,
-- we can break the net into sub-levels. This means that one inverter
-- level must be added if log2_width is odd.
-- Depending on the software, this will be more or less efficient. Try each
-- implementation to be sure.
-- This code is not yet suitable for Vanilla VHDL and is taken apart.
-- With Simili or other tools, compile this architecture AFTER work.fanout
-- in order to replace the default "simple" architecture.

-- some standard librairies
    USE ieee.std_logic_1164.ALL;
    USE ieee.numeric_std.all;
-- text i/o
    use IEEE.std_logic_textio.all;
    use std.textio.all;

-- where the component interface is declared :
    use work.fanout;

-- more sophisticated version :
Architecture linear of fanout is
  constant verbose : natural := 0;

  constant WIDTH : natural := 2 ** log2_width;

  signal t : Std_ulogic_vector(WIDTH-1 downto 0);

  function binary_tree_index (
    index : integer)
  return integer is
    variable i, j : integer;
    variable lout : line;
  begin  -- binary_tree_index

    -- 1 ) count the number of LSB that are set to 1
    -- (the loop could be avoided but requires a XOR which
    --  is not defined for integers :-( )
    i := index;
    j := 4;

    while (i mod 2) = 1 loop
      i := i / 2;
      j := j * 2;
    end loop;

    -- 2) the incredible magic formula !
    -- don't ask me where it comes, it was built from observation.
    i := (j - 1) / 2;

    if verbose > 0 then
      write(lout, string'(" * index : "));
      write(lout, index);
      write(lout, string'(" * result : "));
      write(lout, i);
    end if;

    return ((index / j)*j) + i;
  end binary_tree_index;
  -- avoid the ugly `if ... generate / if not ... generate'
  function invert_if (A : in std_ulogic; F : boolean) return std_ulogic is
	variable Y : std_ulogic;
	if F then
	  Y := not A;
	  Y := A;
	end if;
	return Y;
  end invert_if;

  assert (log2_width > 2) and (log2_width < 10)
    report "wrong size range for the binary tree"
    severity FAILURE;

  assert (leaf'low) = 0
    report "array index should start with 0"
    severity FAILURE;

  -- compensation for the odd/even cases.
  t(WIDTH-1) <= invert_if(root, log2_width mod 2 = 0);

  -- build nodes
  saturate: for i in WIDTH-2 downto 0 generate
	t(i) <= not t(binary_tree_index(i));  -- map the binary tree to a linear vector.
  end generate saturate;

  -- add leaves
  i_loop: for i in leaf'range generate
    leaf(i) <= not t((i/2) *2);     -- connect to the even numbered temporary nodes.
  end generate i_loop;