ONE clock period pulse based on trigger signal

David Kester picture David Kester · Nov 24, 2013 · Viewed 21k times · Source

i am making a midi interface. UART works fine, it sends the 8 bit message along with a flag to a control unit. When the flag goes high, the unit will store the message in a register and make a clr_flag high in order to set the flag of UART low again. The problem is that i can not make this clr_flag one period long. I need it to be ONE period long, because this signal also controls a state machine that indicates what kind of message is being stored (note_on -> key_note -> velocity, for example).

My question here is, how can a signal (flag in this case) trigger a pulse just for one clk period? what i have now makes almost a pulse during a clock period, but i does it twice, because the flag has not become 0 yet. ive tried many ways and now i have this:

get_data:process(clk, flag)
  begin
  if reset = '1' then
    midi <= (others => '0');
    clr_flag <= '0';
    control_flag <= '0';

  elsif ((clk'event and clk='1') and flag = '1') then
      midi <= data_in;
      clr_flag <= '1'; 
      control_flag <= '1';     
  elsif((clk'event and clk='0') and control_flag = '1') then
    control_flag <= '0';
  elsif((clk'event and clk='1') and control_flag = '0') then
    clr_flag <= '0';
  end if;
end process;

the problem with this double pulse or longer than one period pulse(before this, i had something that made clr_flag a two period clk pulse), is that the system will go though two states instead of one per flag.

so in short: when one signal goes high (independent of when it goes low), a pulse during one clock period should be generated.

thanks for your help.

Answer

user_1818839 picture user_1818839 · Nov 24, 2013

The trick to making a single cycle pulse is realising that having made the pulse, you have to wait as long as the trigger input is high before getting back to the start. Essentially you are building a very simple state machine, but with only 2 states you can use a simple boolean to tell them apart.

Morten is correct about the need to adopt one of the standard patterns for a clocked process; I have chosen a different one that works equally well.

get_data:process(clk, reset)
   variable idle : boolean;
begin
   if reset = '1' then
      idle := true;
   elsif rising_edge(clk) then
      clr_flag <= '0';     -- default action
      if idle then
         if flag = '1' then
            clr_flag <= '1';  -- overrides default FOR THIS CYCLE ONLY
            idle <= false;
         end if;
      else
         if flag = '0' then
            idle := true;
         end if;
      end if;
  end if;
end process;