⬆️ ⬇️

VHDL delay element. Another look

Good day.

The answer to the topic " Delay Element on VHDL " is prepared in order to give an idea of ​​possible implementations of signal delays in the FPGA.



Schemes with asynchronous reset are no worse than synchronous circuits. But only in the case when you have solid knowledge of the time delays between the signals arriving at the input and the calculated time delays for your implementation in your FPGA. But then the main advantage of the FPGA is lost - the ability to add new functionality to the circuit or change the used contacts for I / O signals, since for each new implementation it is necessary to take into account its new time delays and not the fact that they suit you.



In the case of a circuit from the topic “Delay Element on VHDL”, the delay will be almost required only in a special case - the front reftime comes immediately after the front of the reference frequency. And why this heaped logic?

')

It is much easier, if you need a small delay, to put several D-triggers with synchronization from the reference frequency. In this case, the delay will be a multiple of the reference frequency period clk20Mhz. In the example below, if there is no reset signal at each edge, signal B will repeat signal A, signal C will repeat signal B. The delay between signals A and C will be in two periods of the reference frequency. Add new D-triggers to achieve the desired delay.



  1. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  2. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  3. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  4. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  5. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  6. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  7. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  8. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  9. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;
  10. process (clk20Mhz,reset,A) -- begin if reset = '1' then B <= '0'; C <= '0'; elsif (clk20Mhz'event and clk20Mhz = '1') then B <= A; C <= B; end if; end process;




In the case when you want to get a delay less than the reference frequency (that is, to trigger triggers at a higher frequency), you will have to use the Digital Clock Manager . At the input of the block, we submit the reference frequency and the parameters of the new frequency (there is a ready output of double frequency, but you can output the frequency multiplied by the ratio of whole coefficients; frequency sharing is also possible). The resulting frequency is used to clock the process with triggers and to obtain a delay less than the reference frequency period included in the FPGA from the crystal oscillator.



It is possible to easily get doubled frequency and without DCM, instead of using the signal front condition (clk20Mhz'event and clk20Mhz = '1') signal change condition (clk20Mhz'event), that is, at each front or fall of the reference frequency, but it is important that the period high level was equal to the low level period.



The third case is when you need to get a delay for a time that is much longer than the reference frequency period. It is unreasonable to spend the whole DCM on creating a “slow” frequency. It is much more profitable to create a counter. In the absence of a reset signal on each front, the logical vector storing the value of counted cycles will increase until the condition for achieving the given constant x "FF" equal to the decimal number 255 is fulfilled and the signal A changes its value to the opposite. This is a simple divider of the reference frequency in the frequency of the signal A with a factor of 254. Thanks to Ocelot for the remark, this is a simple divider of the reference frequency on the counter - each count to 256 marks half the period of the new frequency. The resulting frequency will be 512 times smaller than the reference. Although no one forbids in the FPGA to use a logical vector of a larger number of digits, but here the complexity in wiring will increase. It is better to use a cascade of counters.



  1. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  2. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  3. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  4. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  5. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  6. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  7. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  8. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  9. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  10. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  11. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  12. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  13. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  14. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  15. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

  16. process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;

process (clk,reset) begin if reset = '1' then A <= '0'; count <= (others=>'0'); -- count else if rising_edge(clk) then if count=x"FF" then count <= (others=>'0'); A <= not A; else count <= count + 1; end if; end if; end if; end process;





In conclusion, in synchronous circuits implemented in the FPGA, the delay is always a multiple of the frequency period. In the case of synchronous input signals, it is possible to obtain a delay with an accuracy of no more than the propagation time of the signal in the FPGA between the stages of the triggers. In the case of asynchronous input signals, you can get a delay of no less and no more than a time multiple of the periods of the reference frequency. For this, the frequency multiplication is done to narrow the delay time interval.



And you should take a closer look at self-timed circuits - the future of the FPGA is behind them.



Thank.

Source: https://habr.com/ru/post/126803/



All Articles