Implementing Delay In a Case Statement

 

Maxplus 2 and VHDL itself don't support the implementation of delays inside a case statement. For example the following code:

case instruction is

when first_command =>

instruction1;

wait for 20 ns;

instruction2;

when second_command=>

instruction1;

.

.

.

will not be accepted, since Maxplus2 does not support the use of a delay command such as wait inside a conditional clause. However, when we are dealing with hardware that require a sequence of different signals to be sent out to it, with delays between each of them, this feature is needed, especially when there is more than one sequence to be sent. In this case, a case statement with delays in between instructions is needed.

This can be worked around using a counter attached to the entity containing the implementation of the case statement. A counter with an enable signal can be used to time the delay between instructions. The counter is enabled when the first instruction is run, and then the counter is done, it sets the enable signal for the next instruction.

The code for the counter follows:

entity DelayTimer is

port(

clock: in std_logic;

reset: in std_logic;

overflow: out std_logic; -- the signal that’s set when count is done

count_enable: in std_logic – signal to enable the counter);

end DelayTimer;

architecture behavior of DelayTimer is

signal counter_value: std_logic_vector(DELAY_COUNTER_WIDTH-1 downto 0);

begin

sync: process(clock) is

begin

if rising_edge(clock) then

if reset = '1' then

counter_value <= 0;

overflow <= '0';

elsif count_enable = '1' then

if (counter_value = VALUE_TO_COUNT) then

counter_value <= 0;

overflow <= '1';

else

counter_value <= counter_value + '1';

overflow <= '0';

end if;

else

counter_value <= counter_value;

overflow <= '0';

end if; -- reset | count | else

end if; -- rising clock edge

end process sync;

end behavior;

 To use this combination, the case statement and the counter are placed inside a process responsive to a rising clock edge. Simply connect the count_enable input of this counter to an intermediate signal, and use that signal at the start of the process. Say the signal is named delay_done:
receive: process(clock)

begin

if rising_edge(clock) then

-- all actions are synchronous, and so they need the clock edge

if delay_done = '1' then

enable_delay <= '0'; -- stop counter and reset it

reset_delaytimer <= '1';

else

reset_delaytimer <= ‘0’;

end if;

case instruction is

when first_command =>

instruction1;

enable_delay <= ’1’; -- start counter

when second_command=>

instruction1;

.

.

.

 Now there is a delay after the instruction inside the case statement, and the instruction’s value will remain this way until the delay time is up. The length of delay can be set by changing the DELAY_COUNTER_WIDTH constant inside the counter.

 

For additional information, contact Chen-song.

Group members:

Chen-song Qin (cqin@ee.ualberta.ca)

Sydney Tang (sat@ee.ualberta.ca)

Su-Tarn Lim (sulim@ee.ualberta.ca)