[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [f-cpu] DCT in VHDL



On Thu, Apr 10, 2003 at 03:41:26PM +0200, devik wrote:
[...]
> I tried to compute 6 point DCT matrix - it seems
> nice, you need only constants 1/2, 1/(2 sqrt(2)),
> 1/sqrt(3) and 1/sqrt(6).
> So I did exhaustive search to find good coeficient
> scale. I found that if you use scale 14037 then
> these constants are 1b6a, 1fa8, 1362 and 1662.
> If you look at them closely you find that they
> need only 15 adds to implement multiply for all
> of these constants (I was searching for these constants
> whose have a few bits set and have large overlap in them).

Good design :)

> Thus I was able to synthetize whole 1D 6 point pipelined
> DCT into 342 Spartan slices and tracer estimates 60MHz for it.
> 
> What I need next is second pass to form 2D transform.
> It will need 21 bit inputs instead of 8 bits thus it
> will be much more complex :-\
> 
> Just I'm interested if someone has some ideas about design
> (attached). It is my first VHDL I wrote ;).

But the coding style looks familiar ;)

[...]
> architecture Behavioral of test is
> 	type matrix is array (natural range <>)
> 	        of std_logic_vector(20 downto 0);
> 
> 	function xsrl (A : in std_logic_vector) return std_logic_vector is
> 		constant w : natural := A'length;
> 	begin
> 		return '0' & A(w downto 1);
> 	end xsrl;

You made a tiny mistake here.  Note that A has an unspecified range,
which means that it is taken from the actual argument.  It could be
(n-1 downto 0), (n downto 1) oder even (1 to n).  In your design, it's
(20 downto 0) -- that is, `w' is 21.  Unfortunately, that means that
A(w downto 1) is not a valid expression.  In fact, it isn't in most
cases, and it rarely does what you expect it to.  A trick to avoid that
kind of error is to copy the argument to a vector of the same length,
but with a well-defined range:

	function xsrl (A : in std_logic_vector) return std_logic_vector is
		constant w : natural := A'length;
		variable aa : std_logic_vector(w-1 downto 0);
	begin
		aa := A;	-- automagically converts index range
		return '0' & aa(w-1 downto 1);
	end xsrl;

You'll find that idiom a lot in my code (I used to use aliases, but as
we both know, the Xilinx synthesizer doesn't grok them).  Even more
often, you'll see that I convert the index range of the result, too:

	function xsrl (A : in std_logic_vector) return std_logic_vector is
		constant w : natural := A'length;
		variable aa : std_logic_vector(w-1 downto 0);
		variable yy : std_logic_vector(w-1 downto 0);
	begin
		aa := A;	-- automagically converts index range
		yy(w-1) := '0';
		yy(w-2 downto 0) := aa(w-1 downto 1);
		return yy;
	end xsrl;

That way the results of my functions have a consistent index range
(descending and 0-based, unless otherwise noted).  I find that very
convenient, and it also helps me to avoid stupid indexing mistakes.

You could also specify the index range in the formal parameter list, but
that has an important drawback:  The range will be fixed.  For generic
functions (which are always preferable), an unspecified (and therefore
variable) range is needed.

[...]
> 	-- actual DCT point (0..5)
> 	signal cnt : std_logic_vector(2 downto 0);
[...]

It's probably better to use "one-hot" encoding here:

	-- declarations
	constant STATES : positive := 6;	-- may also be a GENERIC
	signal cnt : std_logic_vector(STATES-1 downto 0);

	-- initialization/reset
	-- Note: synthesizers don't like vector assignments that contain
	-- both explicit indices and "others".
	cnt <= (others => '0');
	cnt(0) <= '1';

	-- update (a simple left rotate)
	variable tmp : std_logic_vector(STATES-1 downto 0);
	-- and then:
	tmp(STATES-1 downto 1) := cc(STATES-2 downto 0);
	tmp(0) := cc(STATES-1);
	cnt <= tmp;

This code scales much better (just change the value of STATES), the shift
register can be updated more easily than a binary counter (you'll also
save an add/increment circuit), and its output will be faster to decode
in most cases.

-- 
 Michael "Tired" Riepe <Michael.Riepe@stud.uni-hannover.de>
 "All I wanna do is have a little fun before I die"
*************************************************************
To unsubscribe, send an e-mail to majordomo@seul.org with
unsubscribe f-cpu       in the body. http://f-cpu.seul.org/