![]() |
|
|
|
#1 |
|
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. Niv (KP) |
|
|
|
|
#2 |
|
Posts: n/a
|
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 Ken Cecka |
|
|
|
#3 |
|
Posts: n/a
|
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; Ken Cecka |
|
|
|
#4 |
|
Posts: n/a
|
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. Niv (KP) |
|
|
|
#5 |
|
Posts: n/a
|
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 Andy |
|
|
|
#6 |
|
Posts: n/a
|
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 Andy |
|
|
|
#7 |
|
Posts: n/a
|
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 Andy |
|
|
|
#8 |
|
Posts: n/a
|
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 Andy |
|
|
|
#9 |
|
Posts: n/a
|
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. Niv (KP) |
|
|
|
#10 |
|
Posts: n/a
|
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 Andy |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| VHDL and EDK: Custom IP core containing an array as a port using EDK | allsey_1987 | Hardware | 0 | 10-27-2009 02:26 PM |
| constants as of array of integers, for loops | octavsly | Hardware | 0 | 04-25-2009 11:53 AM |
| Array Programme | rits | Software | 2 | 03-04-2009 05:18 PM |
| Websites content reading code like title of any website. | Ali_ggl | General Help Related Topics | 0 | 01-24-2008 05:37 AM |
| DVD Reading probelm | michelebargeman@yahoo.com | DVD Video | 1 | 03-15-2006 05:59 PM |