Re: Problem with simple VHDL piece of code



On Jul 12, 3:14 pm, Jonathan Bromley <jonathan.brom...@xxxxxxxxxxxxx>
wrote:
On Thu, 12 Jul 2007 11:18:18 -0700, Jaco

Naude <naude.j...@xxxxxxxxx> wrote:
I'm wondering if any VHDL expert out there can tell me why the
following piece of code isn't working. It should be a simple clock
divider, enabling the CE signal on every counter'th pulse. However the
counter increase line counter := 1+ counter does not increment the
variable. If I change the 1 to for example 20 it stays 20 throughout
the simulation. I'm sure the input signals are correct... Any
suggestions would be helpful.

I'm fairly sure that it's the <= comparisons that are breaking
your design, but while we have the code in front of us there
are a few design style issues that might be worth pursuing.
Would it be fair to guess that you are by habit a software
person, moving into hardware? :-)

process (clk)
variable counter : integer :=0;

Initialisation doesn't usually work in hardware. Better
to use an explicit reset of some kind (as you have done).

begin
if (clk'event and clk = '1') then
counter_out <= counter;

I'm guessing this is just a diagnostic output, so that you
can easily see what "counter" is doing? Note that it lags
behind "counter" by one clock cycle.

if rst <= '1' then
counter := 0;
ce_out <= '1';
end if;

OK. Synchronous reset; I'm sure that's what you intended,
but it's worth checking...

if start <= '1' and rst <= '0' then

if rst='1' then
....reset actions
elsif start='1' then
....main code body
end if

would perhaps have been neater, and easier to follow.

if counter < counter_top + 1 then

Again I'm guessing. counter_top is an incoming signal, perhaps
the contents of a writeable register? This comparison is rather
expensive in hardware, since you are building an incrementer
and a magnitude comparator. For dividers like this, it's
almost always better to preset the counter to the limit
value and then count it down until it reaches a constant
(1 or 0, in most situations).

ce_out <= '0';
counter := 1 + counter;

Are you happy for ce_out to freeze at '1' if someone drops the
'start' signal at an inopportune moment? It may be better to
default ce_out to '0' and set it to '1' only for a single clock
when the wraparound occurs.

else
counter := 0;
ce_out <= '1';
end if;
else
ce_out <= '1';
end if;
end if;
end process;

Finally, your integer counter seems to be unconstrained;
consequently, it will probably be synthesised to 32 bits.
There are various opinions about this, but my own practice
is always to use the numeric_std UNSIGNED or SIGNED vector
types rather than integers.

If I take all my own advice, I end up with something like
this:

constant counter_bits: positive := 16; -- or maybe a generic
signal counter_top: unsigned(counter_bits-1 downto 0);
signal ce_out, start, rst: std_logic;
....
process (clk)
variable counter: unsigned(counter_top'range);
begin
if rising_edge(clk) then
ce_out <= '0';
if rst = '1' then
ce_out <= '1';
counter := counter_top;
elsif start = '1' then
if counter = 0 then
ce_out <= '1';
counter := counter_top;
else
counter := counter - 1;
end if;
end if;
end process;

Note that this generates ce_out with a period of
(counter_top + 1) cycles. If you want the period
to be exactly (counter_top) then you should test
"if counter=1" for the wraparound. The limit
comparator is now trivial, and involves no arithmetic.

Also, note that ce_out will be asserted for the whole
time that rst is asserted. If you don't want that, it
might be better to reset the counter to 1 so that ce_out
is asserted on the first clock after reset is released.

I hope it's clear from the above that you have a lot of
choices, and my suggestions may or may not be useful
depending on what else is happening in your system.

HTH
--
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...@xxxxxxxxxxxxxxxxx://www.MYCOMPANY.com

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

OTOH, if you want to use integers, here's how:

....
variable counter : integer range 0 to 2**counter_bits-1;
....
counter := to_integer(counter_top); -- unless counter_top was also
integer
....

A smart synthesizer might do a reachability analysis on the counter,
and determine that it always contains values between 0 and
counter_top, inclusive, and size counter appropriately all by itself.
Most synthesizers would, I fear, not be so smart.

A smart synthesizer might also be able to use the carry (borrow) out
bit from the decrementer to determine if the count was zero.
Otherwise, one could code it as follows:

....
if count - 1 < 0 then -- don't try this with unsigned/slv
....

Andy

.



Relevant Pages

  • Re: Problem with simple VHDL piece of code
    ... I'm sure the input signals are correct... ... to use an explicit reset of some kind. ... behind "counter" by one clock cycle. ... comparator is now trivial, and involves no arithmetic. ...
    (comp.lang.vhdl)
  • Re: Mixed clocked/combinatorial coding styles
    ... I wouldn't use a device input that performs a device wide reset ... as a clock input had better be able to cope with the clock shutting ... The outputs of the shift registers become the reset signals ... requirement to go active at the end of configuration, ...
    (comp.lang.vhdl)
  • Stupid Newby Question: VHDL/CPLD Shift Register Reset Problem
    ... Let's say I'm building a simple 8-bit shift register (serial in, ... IO_GCK2 clock input of the CPLD. ... The reason I'm asking is because I am having some reset problems when ... end SerialToParallel; ...
    (comp.lang.vhdl)
  • Re: DCM problem with a SPARTAN-3 from xilinx: large range of clock input signal
    ... to the reset pin, but when I do that is just stays in reset. ... Maybe it's better to explain how I now reset the DCM. ... I've got two counters, one counts the incoming clock signal and the ...
    (comp.lang.vhdl)
  • Re: alternate synchronous process template
    ... two separate processes (one with async reset, one without), in one ... to generate the reset signal to everything else in the design and then ... first rising edge of the clock the outputs are in a different state. ...
    (comp.lang.vhdl)