VHDL coding tips and tricks: [Part 3] Synthesisable VHDL code to replace the "wait for" statement

Tuesday, November 17, 2015

[Part 3] Synthesisable VHDL code to replace the "wait for" statement

In the past, I have written two posts(part 1 and part 2) in this topic. But I think they are not clear enough for some people. Through this article I want to share, a much more practically useful code for using in your design.

The famous wait for statement is used normally in testbenches for creating a delay. It is equivalent to the '#' operator in Verilog. But if you want to synthesis the design, in other words, if you want to implement your design idea in hardware, you have to replace wait statement.

There are many ways you can do this. Part 1 and Part 2, I have explained before, are two of them. This is the third way. Suppose there is a signal bit_in, which has to be delayed for a time period of delay_time. In order to do this, I create a delay pipeline. From one end I keep feeding the bit_in bit. And from the other end of pipeline I take out the output bit_out. The bits inside the pipeline is always left shifted at the positive edge of the clock cycle. So we can have variables delays depending on the size of the pipeline register.

Delay Generator vhdl code:

library IEEE;

entity delay_gen is 
      Clk : in std_logic; 
        reset : in std_logic;       
      bit_in :in std_logic;  
      bit_out :out std_logic
end delay_gen;

architecture Behavioral of delay_gen is 

constant Clk_freq : integer := 50; --set the frequency of clock(in MHz) here. (50 MHz default)
constant Delay_time : integer := 100;  --delay time in ns(nano seconds)
--choose the delay time such that the below equation results in a perfect integer value.
constant size_pipeline : integer := ( (Delay_time*Clk_freq) / 1000);   
--register for storing all the bit_in values.
signal pipeline_reg : std_logic_vector(size_pipeline-1 downto 0) := (others => '0');


    if(reset = '1') then
        pipeline_reg <= (others => '0');
        bit_out <= '0';
    elsif(rising_edge(Clk)) then
        pipeline_reg <= pipeline_reg(size_pipeline-2 downto 0) & bit_in; --left shift
        bit_out <= pipeline_reg(size_pipeline-1); --MSB is assigned to output.
    end if;
end process;    

end Behavioral;

Testbench Code:

USE ieee.std_logic_1164.ALL;
END tb;
    -- Component Declaration for the Unit Under Test (UUT)
    COMPONENT delay_gen is 
            Clk : in std_logic; 
            reset : in std_logic;       
            bit_in :in std_logic;  
            bit_out :out std_logic
        end COMPONENT;

   signal Clk,reset,bit_in : std_logic := '0';
   signal bit_out : std_logic := '0';
   constant Clk_freq : integer := 50;  --frequency of clock in MHz
    constant Clk_period : time := (1000/Clk_freq)*1 ns;  --Clk period in nano seconds.
    -- Instantiate the delay line
   delay_line : delay_gen PORT MAP (
          Clk => Clk,
             reset => reset,
             bit_in => bit_in,
             bit_out => bit_out

   -- Generate clock
   Clk_process :process
        Clk <= '0';
        wait for Clk_period/2;
        Clk <= '1';
        wait for Clk_period/2;
   end process;
   stim_proc: process
        wait until rising_edge(Clk);
        bit_in <= '0';  wait for Clk_period*3;
        bit_in <= '1';  wait for Clk_period*1;
        reset <= '1';   wait for Clk_period*10;
        reset <= '0';   wait for Clk_period*1;
        bit_in <= '0';  wait for Clk_period*2;
        bit_in <= '1';  wait for Clk_period*3;
        bit_in <= '0';  wait for Clk_period;
   end process;


Simulation Waveform:

The code was simulated using Xilinx ISE 13.1. The following waveform verifies the working of the design.

Synthesis Results:

The design was successfully synthesised for Virtex 4 fpga and a theoretical maximum frequency of 1800 MHz was obtained. This proves that the design itself doesn't generate any significant delay.

How to use this code in your design?

The code can be used in any design by modifying a few constants.

The frequency of the input clock can  be changed here:
constant Clk_freq : integer := 50; --Its in Mhz
The delay time in nano seconds can be changed here:
constant Delay_time : integer := 100;  --Its in nano seconds

But one thing you have to make sure when you select the above two values. The equation,

( (Delay_time*Clk_freq) / 1000)

should always generate a decimal value(no fractions). Otherwise the delay implemented wont be accurate.

Happy Designing!!!

1 comment: