Array Types

M

Matt North

Guest
I have a type which is generated in a package:

<<type matrix is array(natural range<>) of bit_vector(7 downto 0);

the functions in the package return constrained arrays of type matrix:

<<return matrix is variable result: matrix(0 to length);

When i then go to use the type matrix in my entity:

<<variable rom:=matrix;

I get a warning saying that rom cant be an unconstrained type, i understand
that matrix is unconstrained (array(natural range<>)) however the results
returned by the function in the package constrain the array.

Does anyone know of anyway of constraining the type matrix in the package
depending on the size of the array that each individual function returns?
In the finished code i would like to have a number of functions which all
return different sized arrays (all of the same type), which can then be used
by the entity.

Thanks,
Matt
 
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnjbcv$m7k@newton.cc.rl.ac.uk...

I have a type which is generated in a package:
type matrix is array(natural range<>) of bit_vector(7 downto 0);
the functions in the package return constrained arrays of type matrix:
return matrix is variable result: matrix(0 to length);
When i then go to use the type matrix in my entity:
variable rom:=matrix;
I get a warning saying that rom cant be an unconstrained type, i
understand
that matrix is unconstrained (array(natural range<>)) however the results
returned by the function in the package constrain the array.

Does anyone know of anyway of constraining the type matrix in the package
depending on the size of the array that each individual function returns?
In the finished code i would like to have a number of functions which all
return different sized arrays (all of the same type), which can then be
used
by the entity.
I suspect you're fighting VHDL here, rather than letting it help you.

First, the answer to your explicit question: Yes, but it's clumsy.
Variables must be given a constrained subtype (so that the compiler
knows how much memory to allocate for them, as a first cut at an
explanation). If each of your functions returns a specific
constrained subtype of "matrix" then you can use it thus:

function fun_matN (...) return matrix(N-1 downto 0);
...
-- Make a constant whose range matches fun_matN().
-- Function parameters can be any old junk, because
-- you are never going to use the value of its result.
constant const_matN: matrix := fun_matN(...);
-- Use that constant's range to create a variable:
variable var_matN: matrix(const_matN'range);

Now that you've done this, of course, you can with confidence
write procedural code thus:

var_matN := fun_matN(...);

BUT................
in my experience it's pretty rare for it to be useful to return
a variety of fixed-width results from a variety of functions.
I can't speak for your application of course, but generally
it's much more useful to have the function return a result whose
range is determined dynamically, based on the properties of its
parameters. For example, the "+" operator in numeric_std
returns a result whose width is the larger of its two operands'
widths. In this kind of situation, you can generally decide
in advance what ranges your various data items need.

If your function is genuinely returning a constant - for example,
some constant vector that needs calculation but is always the
same, such as a Fibonacci sequence or the values of
arctan(2^-n) needed for a CORDIC engine - then you can drop
its result into a VHDL constant. As my example above shows,
you don't need to specify the range of a constant; it's
determined from the constant's initialisation expression.

Finally, one last idea: Consider writing a "resize"
procedure that allows you to shoe-horn the result of
any "matrix" expression into an arbitrary "matrix"
variable. Of course, the correct behaviour of truncation
and extension depends on what you're trying to do - in
my example I fill from left to right, throwing away
unused right-hand elements of the source matrix, and
padding un-filled right-hand elements of the destination
with a dummy value.

procedure coerce (
dst: out matrix;
src: in matrix;
dummy: bit_vector(7 downot 0) := "00000000") is
-- Normalise array ranges to 1..N layout.
alias norm_src: matrix(1 to src'length) is src;
alias norm_dst: matrix(1 to dst'length) is dst;
begin
for i in norm_dst'range loop
if i > src'length then
norm_dst(i) := dummy;
else
norm_dst(i) := norm_src(i);
end if;
end loop;
end; -- procedure coerce

Give us a bit more detail about what you are trying to do,
and perhaps we can be more helpful for your specific needs.
--
Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
I have a type which is generated in a package:

type matrix is array(natural range<>) of bit_vector(7 downto 0);

the functions in the package return constrained arrays of type matrix:

return matrix is variable result: matrix(0 to length);

When i then go to use the type matrix in my entity:

variable rom:=matrix;

I get a warning saying that rom cant be an unconstrained type, i understand
that matrix is unconstrained (array(natural range<>)) however the results
returned by the function in the package constrain the array.

Does anyone know of anyway of constraining the type matrix in the package
depending on the size of the array that each individual function returns?
In the finished code i would like to have a number of functions which all
return different sized arrays (all of the same type), which can then be used
by the entity.
Matt,
You need to constraint the variable.
function X (data : matrix) return matrix is
variable result : matrix(0 to data'lenth);
begin
...
return result;
end function X;

process ...
variable rom : matrix(0 to 127);
begin
rom := X(rom);
----------------------------------------------------------------------------
Ben Cohen Publisher, Trainer, Consultant (310) 721-4830
http://www.vhdlcohen.com/ vhdlcohen@aol.com
Author of following textbooks:
* Using PSL/SUGAR with Verilog and VHDL
Guide to Property Specification Language for ABV, 2003 isbn 0-9705394-4-4
* Real Chip Design and Verification Using Verilog and VHDL, 2002 isbn
0-9705394-2-8
* Component Design by Example ", 2001 isbn 0-9705394-0-1
* VHDL Coding Styles and Methodologies, 2nd Edition, 1999 isbn 0-7923-8474-1
* VHDL Answers to Frequently Asked Questions, 2nd Edition, isbn 0-7923-8115
------------------------------------------------------------------------------
 
Ive has a go at implementing your comments but i cant seem to get it to
work.
I will explain my situation in greater detail.

I have package which has a number of functions in them which all return a
variable result of type matrix which is an unconstrained array of bit_vector

One of the functions shown below is ChWrite which is given a string of text
which it converts each ascii character into a bit_vector, the length of
array that this functions returns
therefore changes with each call dependant on the variable 'length'.

--declaration in package
type matrix is array (natural range<>) of bit_vector(7 downto 0);

function ChWrite (font: string(1 to 3); char: string; length: integer)
return matrix;

--function
function ChWrite (font: string(1 to 3); char: string; length: integer)
return matrix is
subtype int_r is integer range 0 to 1;
variable i: int_r :=0;
variable n, ch_int: integer :=0;
variable ch: character;
variable result: matrix(0 to length);
begin

while i<1 loop

if font="nrm" then
result(0):=X"1d";
i:=1;
elsif font="sml" then
result(0):=X"1c";
i:=1;
elsif font="lrg" then
result(0):=X"1e";
i:=1;
else
result(0):=X"1d";
i:=1;
end if;

exit when i=1;
end loop;


while n<length loop
ch:=char(n+1);
ch_int:=character'POS(ch);
result(n+1):=to_bitvector(std_logic_vector(to_unsigned(ch_int, 8)));
n:=n+1;
exit when n=length;
end loop;

return result;
end ChWrite;

The code below shows what i am doing with the result returned from the
function above.
rom is of type matrix, but needs to be constrained by the size of the array
returned by ChWrite.

signal rom: matrix(0 to ??);
signal nxt_line: matrix(0 to 2);

begin

nxt_line<=(X"0d", X"0a", X"20");

process(rst, clk, ilock)
begin
if rising_edge(clk) then
if ilock(0)='0' then
rom<=(ChWrite("sml", "LD1: something", 24) & nxt_line);
elsif ilock(1)='0' then
rom<=(ChWrite("sml", "LD2: something else", 35) & nxt_line);
elsif ilock(2)='0' then
rom<=(ChWrite("sml", "LD3: something different", 14) & nxt_line);
else
rom:=(others=>"00000000");
end if;
end if;
end process;

As you can see the result from ChWrite will be a different size each time,
making it very hard to constrain rom.
"Jonathan Bromley" <jonathan.bromley@doulos.com> wrote in message
news:bnje6a$sc$1$8300dec7@news.demon.co.uk...
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnjbcv$m7k@newton.cc.rl.ac.uk...

I have a type which is generated in a package:
type matrix is array(natural range<>) of bit_vector(7 downto 0);
the functions in the package return constrained arrays of type matrix:
return matrix is variable result: matrix(0 to length);
When i then go to use the type matrix in my entity:
variable rom:=matrix;
I get a warning saying that rom cant be an unconstrained type, i
understand
that matrix is unconstrained (array(natural range<>)) however the
results
returned by the function in the package constrain the array.

Does anyone know of anyway of constraining the type matrix in the
package
depending on the size of the array that each individual function
returns?
In the finished code i would like to have a number of functions which
all
return different sized arrays (all of the same type), which can then be
used
by the entity.

I suspect you're fighting VHDL here, rather than letting it help you.

First, the answer to your explicit question: Yes, but it's clumsy.
Variables must be given a constrained subtype (so that the compiler
knows how much memory to allocate for them, as a first cut at an
explanation). If each of your functions returns a specific
constrained subtype of "matrix" then you can use it thus:

function fun_matN (...) return matrix(N-1 downto 0);
...
-- Make a constant whose range matches fun_matN().
-- Function parameters can be any old junk, because
-- you are never going to use the value of its result.
constant const_matN: matrix := fun_matN(...);
-- Use that constant's range to create a variable:
variable var_matN: matrix(const_matN'range);

Now that you've done this, of course, you can with confidence
write procedural code thus:

var_matN := fun_matN(...);

BUT................
in my experience it's pretty rare for it to be useful to return
a variety of fixed-width results from a variety of functions.
I can't speak for your application of course, but generally
it's much more useful to have the function return a result whose
range is determined dynamically, based on the properties of its
parameters. For example, the "+" operator in numeric_std
returns a result whose width is the larger of its two operands'
widths. In this kind of situation, you can generally decide
in advance what ranges your various data items need.

If your function is genuinely returning a constant - for example,
some constant vector that needs calculation but is always the
same, such as a Fibonacci sequence or the values of
arctan(2^-n) needed for a CORDIC engine - then you can drop
its result into a VHDL constant. As my example above shows,
you don't need to specify the range of a constant; it's
determined from the constant's initialisation expression.

Finally, one last idea: Consider writing a "resize"
procedure that allows you to shoe-horn the result of
any "matrix" expression into an arbitrary "matrix"
variable. Of course, the correct behaviour of truncation
and extension depends on what you're trying to do - in
my example I fill from left to right, throwing away
unused right-hand elements of the source matrix, and
padding un-filled right-hand elements of the destination
with a dummy value.

procedure coerce (
dst: out matrix;
src: in matrix;
dummy: bit_vector(7 downot 0) := "00000000") is
-- Normalise array ranges to 1..N layout.
alias norm_src: matrix(1 to src'length) is src;
alias norm_dst: matrix(1 to dst'length) is dst;
begin
for i in norm_dst'range loop
if i > src'length then
norm_dst(i) := dummy;
else
norm_dst(i) := norm_src(i);
end if;
end loop;
end; -- procedure coerce

Give us a bit more detail about what you are trying to do,
and perhaps we can be more helpful for your specific needs.
--
Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW,
UK
Tel: +44 (0)1425 471223 mail:
jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web:
http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnm0m3$135u@newton.cc.rl.ac.uk...

[snip function code...]
The code below shows what i am doing with the result
returned from the function above.

rom is of type matrix, but needs to be constrained
by the size of the array returned by ChWrite.
signal rom: matrix(0 to ??);
signal nxt_line: matrix(0 to 2);
I'm kinda bewildered here. If "rom" is a signal, then its size
is fixed for the life of the simulation. You can't make a signal
stretch dynamically according to what you put in it.

Consequently, it would make more sense to arrange your ChWrite
function to return a result of the appropriate size, rather
than trying to squeeze the wrong-size result into "rom".
You can do that either by passing the function an extra
parameter indicating how large a result it should create,
or by re-coding it as a procedure (see below).

As you can see the result from ChWrite
will be a different size each time,
making it very hard to constrain rom.
Indeed!

The question is: what are you REALLY trying to do?

If "rom" is just an internal variable in some kind of
test bench, then you should probably re-cast it as a
variable of access type. The LINE type in std.textio
works like this, and gives you (in effect) variable-length
strings; you can do the same yourself. But of course it
doesn't work for signals, because (as I already mentioned)
a signal is created once and for all at the beginning
of simulation.

But if you genuinely need "rom" to be a signal, perhaps
because it's really a buffer in synthesised logic, then
surely its size will be fixed in hardware; and therefore
you need to modify ChWrite so it puts its result into
an appropriate *part* of "rom". To do this, it's probably
best to re-cast ChWrite as a procedure rather than as a
function. You then supply "rom" as an "out" parameter of
the procedure; the procedure can find out how big its
parameter is, and fill the appropriate slice of it.

Finally, I'll ask again: is "rom" intended to be a constant?
If so, then declare it as a constant and your problems go
away.

To sum up: as I said in an earlier post, I think you're
fighting VHDL instead of letting it work for you; but I
can't help much more without some context about what
you are trying to achieve.

--

Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan,

Thanks for your quick reply.

You can't make a signal
stretch dynamically according to what you put in it.
This would indicate why i am having so much trouble!!

A bit of background to the project this concerns.
I am driving a VFD using a Lattice CPLD, the CPLD looks at a number of
inputs, if an input goes high it indicates an interlock has been tripped
and writes information about the alarm on a VFD screen.
Thus rom cant be constant as different info needs to be written to the VFD
depending on which interlock
has tripped.
I decided to write a package which encompases all of the VFD software
commands as functions, making it neater to write and easier to understand.
Especially when it comes to writing text to the VFD; writing a string is
alot easier than looking at an ascii table and writing the hex. into the
array.

Consequently, it would make more sense to arrange your ChWrite
function to return a result of the appropriate size, rather
than trying to squeeze the wrong-size result into "rom".
My function does this already as you have to specify the string length when
you call the function.

<<function ChWrite (font: string(1 to 3); char: string; length: integer)
<< return matrix is variable result: matrix(0 to length);
<<blahblah.....
<<return result;

Anyway I have managed to solve the trouble i was having, using the code
below (not a very good solution but it does the job)

signal rom: matrix(0 to a_large_no.);

process(rst, clk, ilock)
begin
if rising_edge(clk) then
if ilock(0)='0' then
rom(0 to 27)<=(ChWrite("sml", "LD1: I've switched no. 1", 24) &
nxt_line);

elsif ilock(1)='0' then
rom(0 to 38)<=(ChWrite("sml", "LD2: asdfg", 35) & nxt_line);

elsif ilock(2)='0' then
rom(0 to 17)<=(ChWrite("sml", "LD3: DANGER!!!", 14) & nxt_line);

else
rom<=(others=>"00000000");
end if;
end if;
end process;

Thanks for your help.
Matt

"Jonathan Bromley" <jonathan.bromley@doulos.com> wrote in message
news:bnm37m$8rv$1$8302bc10@news.demon.co.uk...
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnm0m3$135u@newton.cc.rl.ac.uk...

[snip function code...]
The code below shows what i am doing with the result
returned from the function above.

rom is of type matrix, but needs to be constrained
by the size of the array returned by ChWrite.
signal rom: matrix(0 to ??);
signal nxt_line: matrix(0 to 2);

I'm kinda bewildered here. If "rom" is a signal, then its size
is fixed for the life of the simulation. You can't make a signal
stretch dynamically according to what you put in it.

Consequently, it would make more sense to arrange your ChWrite
function to return a result of the appropriate size, rather
than trying to squeeze the wrong-size result into "rom".
You can do that either by passing the function an extra
parameter indicating how large a result it should create,
or by re-coding it as a procedure (see below).

As you can see the result from ChWrite
will be a different size each time,
making it very hard to constrain rom.

Indeed!

The question is: what are you REALLY trying to do?

If "rom" is just an internal variable in some kind of
test bench, then you should probably re-cast it as a
variable of access type. The LINE type in std.textio
works like this, and gives you (in effect) variable-length
strings; you can do the same yourself. But of course it
doesn't work for signals, because (as I already mentioned)
a signal is created once and for all at the beginning
of simulation.

But if you genuinely need "rom" to be a signal, perhaps
because it's really a buffer in synthesised logic, then
surely its size will be fixed in hardware; and therefore
you need to modify ChWrite so it puts its result into
an appropriate *part* of "rom". To do this, it's probably
best to re-cast ChWrite as a procedure rather than as a
function. You then supply "rom" as an "out" parameter of
the procedure; the procedure can find out how big its
parameter is, and fill the appropriate slice of it.

Finally, I'll ask again: is "rom" intended to be a constant?
If so, then declare it as a constant and your problems go
away.

To sum up: as I said in an earlier post, I think you're
fighting VHDL instead of letting it work for you; but I
can't help much more without some context about what
you are trying to achieve.

--

Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW,
UK
Tel: +44 (0)1425 471223 mail:
jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web:
http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnm4ru$113o@newton.cc.rl.ac.uk...

A bit of background to the project this concerns.
I am driving a VFD using a Lattice CPLD, the CPLD looks at a number of
inputs, if an input goes high it indicates an interlock has been tripped
and writes information about the alarm on a VFD screen.
Thus rom cant be constant as different info needs to be written to the VFD
depending on which interlock
has tripped.
I decided to write a package which encompases all of the VFD software
commands as functions, making it neater to write and easier to understand.
Especially when it comes to writing text to the VFD; writing a string is
alot easier than looking at an ascii table and writing the hex. into the
array.
This is good, but may make things a little difficult in hardware...

Consequently, it would make more sense to arrange your ChWrite
function to return a result of the appropriate size, rather
than trying to squeeze the wrong-size result into "rom".

My function does this already as you have to specify the string length
when
you call the function.
Yes - but the relationship is somewhat indirect. Your "length"
parameter is essentially just the length of the (readable) argument
string. You don't need to pass that; it can easily be derived from
the string parameter anyhow.

Anyway I have managed to solve the trouble i was having, using the code
below (not a very good solution but it does the job)
Can I go back to my suggestion about a procedure? Also, you can
exploit constants far more than you have done.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package VFD_Stuff is
constant next_line: string := CR & LF & ' ';
constant fontSmall: bit_vector := X"1c";
constant fontNormal: bit_vector := X"1d";
constant fontLarge: bit_vector := X"1e";
procedure ChWrite(
signal dest: out matrix;
font: bit_vector;
info: string);
function char_to_bv(c: character) return bit_vector;
end; -- package VFD_Stuff

package body VFD_Stuff is
function char_to_bv(c: character) return bit_vector is
begin
return to_bitvector(std_logic_vector(to_unsigned(c'pos, 8)));
end; -- function char_to_bv
procedure ChWrite(
signal dest: out matrix;
font: bit_vector;
info: string) is
begin
for i in dest'range loop
if i=0 then
-- Put font control into first element
dest(0) <= font;
elsif i <= dest'high then
if i <= info'length then
-- Copy string to destination
dest(i) <= char_to_bv(info(i));
else
-- Pack remainder of dest with null
dest(i) <= (others => '0');
end if;
else
-- Truncate info if we fell off the end of dest
return;
end if;
end loop;
end; -- proc ChWrite
end; -- package body VFD_Stuff
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now let's use it....
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
constant ROM_SIZE: positive := 40; -- or whatever
signal rom: matrix(0 to ROM_SIZE-1);

process(rst, clk) -- don't need ilock in sensitivity list
begin
if rising_edge(clk) then
-- Default assignment to "rom"...
rom<=(others=>"00000000");
if ilock(0)='0' then
ChWrite(rom, fontSmall, "LD1: I've switched no. 1" & next_line);
elsif ilock(1)='0' then
ChWrite(rom, fontSmall, "LD2: asdfg" & next_line);
elsif ilock(2)='0' then
ChWrite(rom, fontSmall, "LD3: DANGER!!!" & nxt_line);
end if;
end if;
end process;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

What I've written above does exactly the same as your
code, but I think it's a bit cleaner and more maintainable.

Question: in hardware, your "rom" will end up as a massive
collection of flip-flops.... is that what you want???
--
Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Johnathan,

I agree that using a procedure as a subprogram is definately the way to go,
as a function can only return one result.
Your example below is a more readable version than my original code,
thankyou for your help.
It is still a slight annoyance that the range of rom cannot be passed from
the procedure making its size dynamic with regard
to the string length, but this cannot be done in the real world with memory
so why should vhdl do it!!!

As regards your comment about rom being a no. of flip-flops. I realise that
i will have to model a ram structure, however different
synthesis tools recognise memory architectures in different ways to enable
them to match the process to a memory macro (as i am sure you well know!).
I am using Leonardo Spectrum, i haven't modelled ram in it before, it will
be interesting to see how well it models ram.

Thanks,

Matt

"Jonathan Bromley" <jonathan.bromley@doulos.com> wrote in message
news:bnm79n$2kk$1$8300dec7@news.demon.co.uk...
"Matt North" <m.r.w.north@NO_SPAMrl.ac.uk> wrote in
message news:bnm4ru$113o@newton.cc.rl.ac.uk...

A bit of background to the project this concerns.
I am driving a VFD using a Lattice CPLD, the CPLD looks at a number of
inputs, if an input goes high it indicates an interlock has been tripped
and writes information about the alarm on a VFD screen.
Thus rom cant be constant as different info needs to be written to the
VFD
depending on which interlock
has tripped.
I decided to write a package which encompases all of the VFD software
commands as functions, making it neater to write and easier to
understand.
Especially when it comes to writing text to the VFD; writing a string is
alot easier than looking at an ascii table and writing the hex. into the
array.

This is good, but may make things a little difficult in hardware...

Consequently, it would make more sense to arrange your ChWrite
function to return a result of the appropriate size, rather
than trying to squeeze the wrong-size result into "rom".

My function does this already as you have to specify the string length
when
you call the function.

Yes - but the relationship is somewhat indirect. Your "length"
parameter is essentially just the length of the (readable) argument
string. You don't need to pass that; it can easily be derived from
the string parameter anyhow.

Anyway I have managed to solve the trouble i was having, using the code
below (not a very good solution but it does the job)

Can I go back to my suggestion about a procedure? Also, you can
exploit constants far more than you have done.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
package VFD_Stuff is
constant next_line: string := CR & LF & ' ';
constant fontSmall: bit_vector := X"1c";
constant fontNormal: bit_vector := X"1d";
constant fontLarge: bit_vector := X"1e";
procedure ChWrite(
signal dest: out matrix;
font: bit_vector;
info: string);
function char_to_bv(c: character) return bit_vector;
end; -- package VFD_Stuff

package body VFD_Stuff is
function char_to_bv(c: character) return bit_vector is
begin
return to_bitvector(std_logic_vector(to_unsigned(c'pos, 8)));
end; -- function char_to_bv
procedure ChWrite(
signal dest: out matrix;
font: bit_vector;
info: string) is
begin
for i in dest'range loop
if i=0 then
-- Put font control into first element
dest(0) <= font;
elsif i <= dest'high then
if i <= info'length then
-- Copy string to destination
dest(i) <= char_to_bv(info(i));
else
-- Pack remainder of dest with null
dest(i) <= (others => '0');
end if;
else
-- Truncate info if we fell off the end of dest
return;
end if;
end loop;
end; -- proc ChWrite
end; -- package body VFD_Stuff
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now let's use it....
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
constant ROM_SIZE: positive := 40; -- or whatever
signal rom: matrix(0 to ROM_SIZE-1);

process(rst, clk) -- don't need ilock in sensitivity list
begin
if rising_edge(clk) then
-- Default assignment to "rom"...
rom<=(others=>"00000000");
if ilock(0)='0' then
ChWrite(rom, fontSmall, "LD1: I've switched no. 1" & next_line);
elsif ilock(1)='0' then
ChWrite(rom, fontSmall, "LD2: asdfg" & next_line);
elsif ilock(2)='0' then
ChWrite(rom, fontSmall, "LD3: DANGER!!!" & nxt_line);
end if;
end if;
end process;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

What I've written above does exactly the same as your
code, but I think it's a bit cleaner and more maintainable.

Question: in hardware, your "rom" will end up as a massive
collection of flip-flops.... is that what you want???
--
Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW,
UK
Tel: +44 (0)1425 471223 mail:
jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web:
http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 

Welcome to EDABoard.com

Sponsor

Back
Top