Search code examples
vhdlfpgahdl

How can I generate a "tick" inside a process in VHDL?


I am writing a specified UART component in VHDL.

send: process(send_start)
    variable bit_index : integer range 0 to 2 := 0;
begin
    if (falling_edge(send_start)) then
        if (start = '0' and transceiver_start = '1') then
            bit_index := 0;
        end if;

        transceiver_start <= '1';
        if (bit_index = 0) then
            temp_data <= data.RE;
            bit_index := 1;
            transceiver_start <= '0';
            delay_counter <= 0;
        elsif (bit_index = 1) then
            temp_data <= data.IM;
            bit_index := 2;
            transceiver_start <= '0';
        end if;
    end if;
end process;

The falling edge of the transceiver_start signal triggers the sub-component to run. I wanted to trigger it twice, but I do not know how to generate a second falling edge.

I thought about using a concurrent process, which would basically reset the transceiver_start signal to it's hi-state after delay_counter reaches some limit. Therefore I could bring it down inside the send process again to generate a falling edge. However, this makes me have two driving processes for the delay_counter signal, and I read that having resolution functions is not a good practice for synthesis (this code needs to be synthesizable.)

Is there any way for me to generate that falling edge when bit_index = 1?


Solution

  • FPGA devices and related synthesis tools are optimized for synchronous logic, thus VHDL where a clock triggers process execution. Using a specific signal to trigger process execution, as in the question code, is thus not in line with the indented FPGA and VHDL design methodology.

    Instead, use an internal clock to trigger process execution, usually the rising edge of the clock. Actual update inside the process can then be conditional on detection of change to a control signal, which can be send_start.

    process (clock) is
    begin
      if rising_edge(clock) then
        send_start_prev <= send_start;  -- Previous for edge detection
        if ((send_start = '0') and (send_start_prev = '1')) then  -- Falling edge of send_start
          ...  -- More code
        end if;
      end if;
    end process;
    

    For rerunning of conditional process code, for example based on bit_index = 1, the process contents can be updated like:

        send_start_prev <= send_start;  -- Previous for edge detection
        rerun_request   <= '0';  -- Default no rerun
        if ((send_start = '0') and (send_start_prev = '1')) or  -- Falling edge of send_start
           (rerun_request = '1') then  -- Rerun request
          if bit_index = 1 then
            rerun_request <= '1';
          end if;
          ...  -- More code
        end if;