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;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity delay_gen is
port(
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');
begin
process(Clk,reset)
begin
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:
Simulation Waveform:
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.
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.
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;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity delay_gen is
port(
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');
begin
process(Clk,reset)
begin
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:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT delay_gen is
port(
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.
BEGIN
-- 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
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
stim_proc: process
begin
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;
wait;
end process;
END;
USE ieee.std_logic_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT delay_gen is
port(
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.
BEGIN
-- 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
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
stim_proc: process
begin
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;
wait;
end process;
END;
The code was simulated using Xilinx ISE 13.1. The following waveform verifies the working of the design.
Synthesis Results:
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
constant Delay_time : integer := 100; --Its in nano seconds
( (Delay_time*Clk_freq) / 1000)
should always generate a decimal value(no fractions). Otherwise the delay implemented wont be accurate.
Happy Designing!!!
can i get synthesizable code for 8 point fft
ReplyDelete