Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Reading an Array of vectors.

Reply
Thread Tools

Reading an Array of vectors.

 
 
Niv (KP)
Guest
Posts: n/a
 
      02-13-2009
I have an interface to a set of identical ADC's, the number of which
is set by a generic "N", (range of 1 to 16)
All are triggered & sampled in parallel, so only one clock & enable
generated, but "N" data paths back

I have to read the vectors over a CPU bus one at a time.

As the number of vectors is generic dependant, how to I code the case
statement for the reads.

e.g.

CASE address IS
WHEN "0000" => read_bus <= adc_bus(0);
WHEN "0001" => read_bus <= adc_bus(1);

-- etc
END CASE;

What I want to do is loop on 0 to (N-1 ) on the CASE satement.

The only way I can think of is to create an array 16 wide of (31
downto 0), default assign all to '0's
then in a loop of 0 to (N- 1) assign this new array to the incoming
array.

I then code the case statement so it has all 16 possible states, and
reads this new array one slice at a time.
Software can decide how to read depending on the actual number of ADCs
instantiated.

Is there a better way? (Not used arrays of vectors with generic ports
etc before, if you hadn't already guessed)!
I could hard code the whole lot for a fixed number of ADC's very
easily, but RE_USE is key at the moment.

TIA, Niv.
 
Reply With Quote
 
 
 
 
Ken Cecka
Guest
Posts: n/a
 
      02-13-2009
Niv (KP) wrote:

> I have an interface to a set of identical ADC's, the number of which
> is set by a generic "N", (range of 1 to 16)
> All are triggered & sampled in parallel, so only one clock & enable
> generated, but "N" data paths back
>
> I have to read the vectors over a CPU bus one at a time.
>
> As the number of vectors is generic dependant, how to I code the case
> statement for the reads.
>
> e.g.
>
> CASE address IS
> WHEN "0000" => read_bus <= adc_bus(0);
> WHEN "0001" => read_bus <= adc_bus(1);
>
> -- etc
> END CASE;
>
> What I want to do is loop on 0 to (N-1 ) on the CASE satement.
>
> The only way I can think of is to create an array 16 wide of (31
> downto 0), default assign all to '0's
> then in a loop of 0 to (N- 1) assign this new array to the incoming
> array.
>
> I then code the case statement so it has all 16 possible states, and
> reads this new array one slice at a time.
> Software can decide how to read depending on the actual number of ADCs
> instantiated.
>
> Is there a better way? (Not used arrays of vectors with generic ports
> etc before, if you hadn't already guessed)!
> I could hard code the whole lot for a fixed number of ADC's very
> easily, but RE_USE is key at the moment.
>
> TIA, Niv.


I haven't studied the netlist to verify how this gets translated, but the way I've solved this in my projects that seems to simulate and synthesize fine is:

FOR i IN adc_bus'RANGE LOOP
IF (address = CONV_STD_LOGIC_VECTOR(i, 5)) THEN
read_bus <= adc_bus(i);
END IF;
END LOOP;

This should unroll into a series of IF statements at synthesis time - one for each possible value of address.

Ken
 
Reply With Quote
 
 
 
 
Ken Cecka
Guest
Posts: n/a
 
      02-13-2009
Ken Cecka wrote:

> Niv (KP) wrote:
>
>> I have an interface to a set of identical ADC's, the number of which
>> is set by a generic "N", (range of 1 to 16)
>> All are triggered & sampled in parallel, so only one clock & enable
>> generated, but "N" data paths back
>>
>> I have to read the vectors over a CPU bus one at a time.
>>
>> As the number of vectors is generic dependant, how to I code the case
>> statement for the reads.
>>
>> e.g.
>>
>> CASE address IS
>> WHEN "0000" => read_bus <= adc_bus(0);
>> WHEN "0001" => read_bus <= adc_bus(1);
>>
>> -- etc
>> END CASE;
>>
>> What I want to do is loop on 0 to (N-1 ) on the CASE satement.
>>
>> The only way I can think of is to create an array 16 wide of (31
>> downto 0), default assign all to '0's
>> then in a loop of 0 to (N- 1) assign this new array to the incoming
>> array.
>>
>> I then code the case statement so it has all 16 possible states, and
>> reads this new array one slice at a time.
>> Software can decide how to read depending on the actual number of ADCs
>> instantiated.
>>
>> Is there a better way? (Not used arrays of vectors with generic ports
>> etc before, if you hadn't already guessed)!
>> I could hard code the whole lot for a fixed number of ADC's very
>> easily, but RE_USE is key at the moment.
>>
>> TIA, Niv.

>
> I haven't studied the netlist to verify how this gets translated, but the
> way I've solved this in my projects that seems to simulate and synthesize
> fine is:
>
> FOR i IN adc_bus'RANGE LOOP
> IF (address = CONV_STD_LOGIC_VECTOR(i, 5)) THEN
> read_bus <= adc_bus(i);
> END IF;
> END LOOP;
>
> This should unroll into a series of IF statements at synthesis time - one
> for each possible value of address.
>
> Ken


Forgot to mention that you can get the the equivalent of a WHEN OTHERS by adding an initial assignment to read_bus before the loop:

read_bus <= (OTHERS => '0');
FOR i IN adc_bus'RANGE LOOP
IF (address = CONV_STD_LOGIC_VECTOR(i, 5)) THEN
read_bus <= adc_bus(i);
END IF;
END LOOP;

 
Reply With Quote
 
Niv (KP)
Guest
Posts: n/a
 
      02-13-2009
On 13 Feb, 17:46, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Fri, 13 Feb 2009 17:34:05 +0000, Alan Fitch wrote:
> > * *process(clock)
> > * *begin
> > * * *if rising_edge(clock) then
> > * * * *if enable = '1' then
> > * * * * *for i in 0 to n-1 loop
> > * * * * * *if to_integer(unsigned(address)) = i then
> > * * * * * * *read_bus(i) <= adc_bus(i);
> > * * * * * *end if;
> > * * * * *end loop;
> > * * * *end if;
> > * *end process;

>
> >Due to "last assignment wins" a.k.a intertial delay, this will mean
> >effectively there is a higher priority to higher addresses - but as only
> >one address can be true (they're mutually exclusive) I would hope
> >synthesis would produce sensible code,

>
> If synthesis doesn't sort out the mutual-exclusivity
> for itself, you can give it a helpful hint by implying
> an AND-OR tree instead of the pri-mux. *I've used this
> with some success in designs that have a large number
> of readable registers. *
>
> Similar overall shape to Alan's solution, but with an
> extra variable to accumulate the sum-of-products:
>
> * * process(clock)
> * * * variable readback: std_logic_vector(read_bus'range);
> * * begin
> * * * if rising_edge(clock) then
> * * * * readback := (others => '0'); *-- start with all-zero
> * * * * if enable = '1' then
> * * * * * for i in 0 to n-1 loop
> * * * * * * if to_integer(unsigned(address)) = i then
> * * * * * * * readback := readback or adc_bus(i);
> * * * * * * end if;
> * * * * * end loop;
> * * * * * read_bus <= readback;
> * * * * end if;
> * * end process;
>
> Note that this iterate-through-the-addresses arrangement
> also allows for more complex address matching schemes.
> Instead of the equality test on the address, consider
> using a user-written address matching function:
>
> * if adrs_match(address, i) then ...
>
> This allows for sparse address spaces, "registers" that
> span more than one address (they would then use a few
> low-order address bits internally to determine their
> functionality), and "interesting" variable register maps.
> --
> 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.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com
>
> The contents of this message may contain personal views which
> are not the views of Doulos Ltd., unless specifically stated.- Hide quoted text -
>
> - Show quoted text -


Thanks chaps,
Plenty of options & food for thought there.
Regards, Niv.
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      02-13-2009
On Feb 13, 11:27*am, Jim Lewis <j...@synthworks.com> wrote:
> On the other hand, you can avoid the looping by using the
> following (one step, no loops, no if statement). *to_integer
> is from package numeric_std.
>
> library ieee ;
> use ieee.numeric_std.all ;
> . . .
>
> read_bus <= adc_bus(to_integer(unsigned(address))) ;
>


This works so long as any possible value on address is within the
index range of adc_bus (or if you can use the mod operator on address
to limit it). It is quick and to the point though. Otherwise, the for-
loop with a comparison of address and each possible index is required.

Andy
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      02-13-2009
On Feb 13, 11:34*am, Alan Fitch <alan.fi...@spamtrap.com> wrote:
>
> Due to "last assignment wins" a.k.a intertial delay, this will mean
> effectively there is a higher priority to higher addresses - but as only
> one address can be true (they're mutually exclusive) I would hope
> synthesis would produce sensible code,
>


You can use an exit statement, and/or alter the direction of the loop
index range to alter the priority of the unrolled if statements.
Although in most cases using equality comparisons to the same object
(address in this case), the synthesis tool will figure out that the
comparisons are mutually exclusive. Thus no priority is assigned,
rendering index order and/or exit statements moot, except with regard
to simulation performance.

Within vhdl/process contexts, "last assignment wins" and "inertial
delay" are completely different concepts. Inertial delay has to do
with multiple waveforms driven onto one signal at different simulation
times, and which one will take precedence. Inside a process, multiple
assignments between waits happen in zero simulation time, and there is
only one value/waveform that actually gets promoted to that process's
lone driver for the signal (and it is the last assignment that is
promoted).

Andy
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      02-16-2009
On Feb 14, 2:58*am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Fri, 13 Feb 2009 13:09:13 -0800 (PST), Andy wrote:
> >Within vhdl/process contexts, "last assignment wins" and "inertial
> >delay" are completely different concepts.

>
> Sorry Andy, I don't think that is correct at all.
>
> >Inertial delay has to do
> >with multiple waveforms driven onto one signal at different simulation
> >times

>
> Or at the same time. *One consistent set of rules covers all cases.
>
> > Inside a process, multiple
> >assignments between waits happen in zero simulation time

>
> For sure.
>
> >only one value/waveform that actually gets promoted to that process's
> >lone driver for the signal (and it is the last assignment that is
> >promoted).

>
> Yes, but that behaviour is only guaranteed BECAUSE OF the
> inertial delay rules. *Contrast with zero-delay nonblocking
> assignments in Verilog, which use non-overwriting transport
> delay; Verilog is obliged to introduce an intuitively
> sensible, but conceptually tiresome, kludge into the
> language definition to guarantee that multiple updates
> on the same signal have the effect that you expect.
> Even then, the use of transport rather than inertial
> delay raises the possibility of unwanted zero-width
> glitches that may or may not be seen as events in
> simulation. *And the absence of inertial delay for
> procedural signal assignment makes it impossible to
> rescind a future scheduled signal update in a reliable
> manner.
>
> So, all in all, inertial delay is rather important for
> getting sensible last-write-wins behaviour for signal
> assignment.


If I read your argument correctly, one should be able to use transport
delay to allow prior writes (in same process cycle) to show up in the
waveform...

Andy
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      02-16-2009
On Feb 16, 1:23*pm, Andy <jonesa...@comcast.net> wrote:
> If I read your argument correctly, one should be able to use transport
> delay to allow prior writes (in same process cycle) to show up in the
> waveform...
>
> Andy


To illustrate:

process(clk) is
begin
if rising_edge(clk) then
s <= transport e;
s <= transport e + 1;
s <= transport e + 2;
end if;
end process;

Per your argument, for how long should e and e+1 show up before the
value of s settles on e+2?

Andy
 
Reply With Quote
 
Niv (KP)
Guest
Posts: n/a
 
      02-17-2009
On 13 Feb, 19:49, "Niv (KP)" <kev.pars...@mbda-systems.com> wrote:
> On 13 Feb, 17:46, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
> wrote:
>
>
>
>
>
> > On Fri, 13 Feb 2009 17:34:05 +0000, Alan Fitch wrote:
> > > * *process(clock)
> > > * *begin
> > > * * *if rising_edge(clock) then
> > > * * * *if enable = '1' then
> > > * * * * *for i in 0 to n-1 loop
> > > * * * * * *if to_integer(unsigned(address)) = i then
> > > * * * * * * *read_bus(i) <= adc_bus(i);
> > > * * * * * *end if;
> > > * * * * *end loop;
> > > * * * *end if;
> > > * *end process;

>
> > >Due to "last assignment wins" a.k.a intertial delay, this will mean
> > >effectively there is a higher priority to higher addresses - but as only
> > >one address can be true (they're mutually exclusive) I would hope
> > >synthesis would produce sensible code,

>
> > If synthesis doesn't sort out the mutual-exclusivity
> > for itself, you can give it a helpful hint by implying
> > an AND-OR tree instead of the pri-mux. *I've used this
> > with some success in designs that have a large number
> > of readable registers. *

>
> > Similar overall shape to Alan's solution, but with an
> > extra variable to accumulate the sum-of-products:

>
> > * * process(clock)
> > * * * variable readback: std_logic_vector(read_bus'range);
> > * * begin
> > * * * if rising_edge(clock) then
> > * * * * readback := (others => '0'); *-- start with all-zero
> > * * * * if enable = '1' then
> > * * * * * for i in 0 to n-1 loop
> > * * * * * * if to_integer(unsigned(address)) = i then
> > * * * * * * * readback := readback or adc_bus(i);
> > * * * * * * end if;
> > * * * * * end loop;
> > * * * * * read_bus <= readback;
> > * * * * end if;
> > * * end process;

>
> > Note that this iterate-through-the-addresses arrangement
> > also allows for more complex address matching schemes.
> > Instead of the equality test on the address, consider
> > using a user-written address matching function:

>
> > * if adrs_match(address, i) then ...

>
> > This allows for sparse address spaces, "registers" that
> > span more than one address (they would then use a few
> > low-order address bits internally to determine their
> > functionality), and "interesting" variable register maps.
> > --
> > 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.brom...@MYCOMPANY.comhttp://www.MYCOMPANY.com

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

>
> > - Show quoted text -

>
> Thanks chaps,
> Plenty of options & food for thought there.
> Regards, Niv.- Hide quoted text -
>
> - Show quoted text -


I wasn't quite right when I said "N" was a generic!

I have a package with the following:

PACKAGE ad7476_pkg IS

CONSTANT num_of_convs : INTEGER := 5; -- Number of parallel
ADC's.


TYPE d_conv_bus IS ARRAY(num_of_convs-1 DOWNTO 0)
OF STD_LOGIC_VECTOR(31 DOWNTO 0);

TYPE d_convs_in IS ARRAY(num_of_convs-1 DOWNTO 0)
OF STD_LOGIC;

END ad7476_pkg;

The "d_conv_bus" is used to declare the o/p port on teh ADC controller
and the
i/p port on my address decoder, so the results get read in ascending
order (loop dependent).
The ADC controller also has an i/p port of "d_convs_in", which
promulgates to the top level of the block.

I would like to instnace this top level block with a generic that
overrides the package constant
"num_of_convs", but can't figure how to do this.

As it is, with the constant 5, all works fine, and I can read the
values back as suggested in earlier posts.
I'd just like to make it more flexible.

TIA, Niv.
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      02-17-2009
On Feb 16, 2:13*pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
> On Mon, 16 Feb 2009 11:23:28 -0800 (PST), Andy wrote:
> >If I read your argument correctly, one should be able to use transport
> >delay to allow prior writes (in same process cycle) to show up in the
> >waveform...

>
> I'm not 100% sure I understand what you mean, so please
> excuse me if I've misunderstood.
>
> A transport signal assignment in VHDL:
>
> * S <= transport EXPR after T;
>
> schedules an update of S to EXPR at time NOW+T,
> and also deletes any pending updates on S for
> times >= NOW+T. *Pending updates on S for
> times < NOW+T are preserved, however.
>


In my way of thinking, Inertial and Transport mechanisms are opposite
of each other. If (and I don't think it does) the inertial delay
mechanism is causing some behavior (discarding all but the last of all
non-delayed outputs in the delta cycle following the process cycle),
then transport delay ought to avoid that behavior (allow the multiple
outputs to appear), which we both agree will not happen.

> You can't get more than one update on a signal
> in a given delta cycle in VHDL, no matter what you do.


THIS is exactly what I'm getting at. The fact that the last assignment
in a process cycle wins (esp. among assignments with no delays) has
nothing to do with inertial delay, it has to do with the fact that all
of the (zero delay) signal updates from a single process cycle are
effective in the same delta cycle, and there is no smaller subdivision
of "time" to spread multiple updates over. So the last assignment is
chosen as the update for that delta cycle, and earlier ones are
discarded.

In other words, the reason that multiple delta cycles are not used,
and therefore only one (any one) assignment must be chosen to be
promoted, has nothing to do with inertial delay. I understand your
assertion that the reason the last one is chosen is at least
consistent with, if not controlled by, the inertial delay mechanism.

Perhaps to help illustrate this:

process (e)
variable temp : unsigned(s'range);
begin
temp := e;
temp := e+1;
temp := e+2;
s <= temp;
end process;

Is the above any different from:

process (e)
begin
s <= e;
s <= e+1;
s <= e+2;
end process;

Maybe this is all in how the simulator optimizes execution (i.e.
removing prior writes up front, rather than using the signal update
(inertial) mechanism to do so). Just for the record, I think we both
agree there is absolutely no difference WRT synthesis.

Thank you for the explanation of verilog behavior. It reinforces my
desire not to migrate to verilog (or SystemVerilog, if it has these
same issues).

Andy


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const and array of array (of array ...) Mara Guida C Programming 3 09-03-2009 07:54 AM
Reading array of unknown size from file to array Denis Palas Java 2 12-19-2006 11:14 PM
length of an array in a struct in an array of structs in a struct in an array of structs Tuan Bui Perl Misc 14 07-29-2005 02:39 PM
Length of Array of Array of Array Tom Perl Misc 3 12-20-2004 05:23 PM
[newbie]saving and reading array of associative array Yvon Thoraval Ruby 5 09-17-2003 07:54 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57