vector align on fixed boundaries

O

Olaf

Guest
Hello,

I have the following code:

entity ...
generic (
SMPL_WIDTH : integer range 2 to 32 := 32;
TS_WIDTH : integer range 2 to 32 := 32;
SMPL_DEPTH : integer range 2 to 1048576 := 16384;
...
port (
smpl_clk : in std_ulogic;
reset : in std_ulogic;
sample : in std_ulogic_vector(SMPL_WIDTH-1 downto 0);
...
end entity;

architecture behavioral ...

type smpl_memory_t is array (SMPL_DEPTH-1 downto 0) of
std_ulogic_vector (sample'range);
type ts_memory_t is array (SMPL_DEPTH-1 downto 0) of
std_ulogic_vector (TS_WIDTH-1 downto 0);

signal smpl_memory : smpl_memory_t;
signal ts_memory : ts_memory_t;

signal we : std_ulogic;
signal en : std_ulogic;
signal addr : std_ulogic_vector(log2(SMPL_DEPTH)-1 downto 0);
signal smpl_di : std_ulogic_vector(smpl_memory'range);
signal smpl_do : std_ulogic_vector(smpl_memory'range);
signal ts_di : std_ulogic_vector(ts_memory'range);
signal ts_do : std_ulogic_vector(ts_memory'range);
signal ts_smpl_data : std_ulogic_vector(63 downto 0);

begin

smpl_di <= sample;
ts_di <= ts_count;
ts_smpl_data(63 downto 32) <=
(ts_smpl_data(ts_do'range) => ts_do, others => '0');
ts_smpl_data(31 downto 0) <=
(ts_smpl_data(smpl_do'range) => smpl_do, others => '0');

ts_ram: process ...
smpl_ram: process ...

The goal is to align the vectors ts_do and smpl_do to a 32bit boundary;
the upper 32-bit word should hold the ts_do and the lower the smpl_do
regardless of the length of each vector. Unused bits should be tied to
'0'. Therefore the 64-bit data word is independ of the length of ts_do
and smpl_do.

Anyway, this won't compile in that manner. What is the correct syntax
for this?

Thanks
Olaf
 
Olaf schrieb:
Hello,

I have the following code:

entity ...
generic (
SMPL_WIDTH : integer range 2 to 32 := 32;
TS_WIDTH : integer range 2 to 32 := 32;
SMPL_DEPTH : integer range 2 to 1048576 := 16384;
...
port (
smpl_clk : in std_ulogic;
reset : in std_ulogic;
sample : in std_ulogic_vector(SMPL_WIDTH-1 downto 0);
...
end entity;

architecture behavioral ...

type smpl_memory_t is array (SMPL_DEPTH-1 downto 0) of
std_ulogic_vector (sample'range);
type ts_memory_t is array (SMPL_DEPTH-1 downto 0) of
std_ulogic_vector (TS_WIDTH-1 downto 0);

signal smpl_memory : smpl_memory_t;
signal ts_memory : ts_memory_t;

signal we : std_ulogic;
signal en : std_ulogic;
signal addr : std_ulogic_vector(log2(SMPL_DEPTH)-1 downto 0);
oops, should be:

signal smpl_di : std_ulogic_vector(sample'range);
signal smpl_do : std_ulogic_vector(sample'range);
signal ts_di : std_ulogic_vector(TS_WIDTH-1 downto 0);
signal ts_do : std_ulogic_vector(TS_WIDTH-1 downto 0);
signal ts_smpl_data : std_ulogic_vector(63 downto 0);

begin

smpl_di <= sample;
ts_di <= ts_count;
ts_smpl_data(63 downto 32) <=
(ts_smpl_data(ts_do'range) => ts_do, others => '0');
ts_smpl_data(31 downto 0) <=
(ts_smpl_data(smpl_do'range) => smpl_do, others => '0');

ts_ram: process ...
smpl_ram: process ...

The goal is to align the vectors ts_do and smpl_do to a 32bit boundary;
the upper 32-bit word should hold the ts_do and the lower the smpl_do
regardless of the length of each vector. Unused bits should be tied to
'0'. Therefore the 64-bit data word is independ of the length of ts_do
and smpl_do.
Error Message is:

** Error: Signal "ts_do" is type ieee.std_logic_1164.std_ulogic_vector;
expecting type ieee.std_logic_1164.std_ulogic.
** Error: Cannot resolve slice name as type std.standard.natural.
** Warning: Non-locally static choice (association #1, choice #1) is
allowed only if it is the only choice of the only association.
** Error: Signal "smpl_do" is type
ieee.std_logic_1164.std_ulogic_vector; expecting type
ieee.std_logic_1164.std_ulogic.
** Error: Cannot resolve slice name as type std.standard.natural.
** Warning: Non-locally static choice (association #1, choice #1) is
allowed only if it is the only choice of the only association.

The problem still exist.

Thanks
Olaf
 
On Sat, 02 Jun 2007 09:43:08 +0200, Olaf <olaf@mdcc.de> wrote:

Hello,

I have the following code:
There's LOTS wrong with it.

type smpl_memory_t is array (SMPL_DEPTH-1 downto 0) of
std_ulogic_vector (sample'range);
[...]
signal smpl_memory : smpl_memory_t;
[...]
signal smpl_di : std_ulogic_vector(smpl_memory'range);
smpl_memory'range is (SMPL_DEPTH-1 downto 0). I suspect
you don't want smpl_di to have one bit for each location in
the memory. My guess is that you want it to have the same
number of bits as each WORD in the memory. It should
probably be indexed by (sample'range). Similarly for ts_memory.

ts_smpl_data(63 downto 32) <=
(ts_smpl_data(ts_do'range) => ts_do, others => '0');
[...]
The goal is to align the vectors ts_do and smpl_do to a 32bit boundary;
the upper 32-bit word should hold the ts_do and the lower the smpl_do
regardless of the length of each vector. Unused bits should be tied to
'0'. Therefore the 64-bit data word is independ of the length of ts_do
and smpl_do.
ts_do is an array, and in this context VHDL is expecting a single bit.
I don't know of any easy way to use aggregates like this. You can
use concatenation, but it would require some nasty subscript range
calculations and type qualifications, so again it's a bad idea.

Try this...

process (ts_do, smpl_do) is
variable ts_word, smpl_word: std_ulogic_vector(31 downto 0);
begin
ts_word := (others => '0');
smpl_word := (others => '0');
ts_word(ts_do'range) := ts_do;
smpl_word(smpl_do'range) := smpl_do;
ts_smpl_data <= ts_word & smpl_word;
end process;

Using a process allows me to default all locations of ts_word
to zero, and then overwrite just the appropriate bits with
your data value.

You could also consider writing a RESIZE function that does
something rather similar. My previous code example assumes
that ts_do and smpl_do are no more than 32 bits wide, and
have (N-1 downto 0) subscript ranges; the function can
easily be made more robust.

function resize (
data: in std_ulogic_vector;
bits: positive)
) return std_ulogic_vector
is
constant d: std_ulogic_vector(data'length-1 downto 0) := data;
variable result: std_ulogic_vector(bits-1 downto 0)
:= (others => '0');
begin
if d'length > bits then -- truncation
return d(bits-1 downto 0);
else -- zero fill
result(d'range) := d;
return result;
end if;
end;

And now you can get your 64-bit double-word like this...

ts_smpl_data <= resize(ts_do, 32) & resize(smpl_do, 32);

Hope this helps
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
function resize (
data: in std_ulogic_vector;
bits: positive)
) return std_ulogic_vector
is
constant d: std_ulogic_vector(data'length-1 downto 0) := data;
variable result: std_ulogic_vector(bits-1 downto 0)
:= (others => '0');
begin
if d'length > bits then -- truncation
return d(bits-1 downto 0);
else -- zero fill
result(d'range) := d;
return result;
end if;
end;

And now you can get your 64-bit double-word like this...

ts_smpl_data <= resize(ts_do, 32) & resize(smpl_do, 32);

Hope this helps
cool, thanks. Google brought the resize function for signed and unsigned
vectors. Does it exist for std_(u)logic_vectors as well or does I have
to use a project specific function like this above?

Thanks
Olaf
 
On Mon, 04 Jun 2007 07:45:45 +0200, Olaf <is.er@inter.net> wrote:

Google brought the resize function for signed and unsigned
vectors. Does it exist for std_(u)logic_vectors as well or does I have
to use a project specific function like this above?
No, it must be do-it-yourself. The package functions
numeric_std.resize [[un]signed, natural] can be generic because
the argument data type decides whether zero- or sign-extension
is done. For std_logic_vector there's no general way to
know this. So I suggest you put this, and other such functions,
into a project-specific package. You could then provide a
nice wrapper for it:

package olafs_bit_bashing;
constant wordSize: postive := 32;
function resize(...) -- prototype, as discussed;
function rightPack(v: std_ulogic_vector)
return std_ulogic_vector;
end;
package body olafs_bit_bashing;
function resize(...) is... -- implementation
function rightPack(v: std_ulogic_vector)
return std_ulogic_vector is
begin
return resize(v, wordSize);
end;
end;

Packages containing project configuration constants are a
great way to manage this kind of thing and keep your code
tidy. VHDL-2006 package generics will make them even better;
for example, wordSize in my package above could be a generic
and then you can instantiate ("use") the same package in
various places, with various different generic values.

Note also that you can press the numeric_std.resize function
into service to save yourself some implementation hassle.
Here's the resize function, rewritten this way:


function resize (
data: in std_ulogic_vector;
bits: positive)
) return std_ulogic_vector
is
begin
return std_ulogic_vector(resize(unsigned(data), bits));
end;
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
No, it must be do-it-yourself. The package functions
numeric_std.resize [[un]signed, natural] can be generic because
the argument data type decides whether zero- or sign-extension
is done. For std_logic_vector there's no general way to
know this. So I suggest you put this, and other such functions,
into a project-specific package. You could then provide a
nice wrapper for it:

package olafs_bit_bashing;
[...]


:)

Thanks a lot
Olaf
 

Welcome to EDABoard.com

Sponsor

Back
Top