Introducing a delay in VHDL is pretty easy with a wait for statement. But it has the disadvantage that it is not synthesisable. Most of the practical designs, so require another way to introduce a delay.
In this article I will use a counter and state machine to introduce the delay. We have an input signal, and we want to assign it to the output only after (say) 100 clock cycles. With this objective in my mind , first I have drawn a state machine.
There are two states in the state machine - idle and delay_c.
when the system is in idle state it waits for a valid input bit at the port data_in. whenever the data is valid, valid_data will go high. Upon receiving a valid data, the system moves to delay_c state where a counter, c is incremented every clock cycle till it reaches the maximum delay value(Here it is 100). Once the max count is reached system goes back to idle state and the input data will be assigned to output data. This process goes on and on.
I have written the VHDL codes and testbench code for the above state machine. See the below simulated result to see how it works:
The VHDL code is given below. It is well commented, so I wont be explaining it any further.
In this article I will use a counter and state machine to introduce the delay. We have an input signal, and we want to assign it to the output only after (say) 100 clock cycles. With this objective in my mind , first I have drawn a state machine.
There are two states in the state machine - idle and delay_c.
when the system is in idle state it waits for a valid input bit at the port data_in. whenever the data is valid, valid_data will go high. Upon receiving a valid data, the system moves to delay_c state where a counter, c is incremented every clock cycle till it reaches the maximum delay value(Here it is 100). Once the max count is reached system goes back to idle state and the input data will be assigned to output data. This process goes on and on.
I have written the VHDL codes and testbench code for the above state machine. See the below simulated result to see how it works:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity delay is
port( Clk : in std_logic;
valid_data : in std_logic; -- goes high when the input is valid.
data_in : in std_logic; -- the data input
data_out : out std_logic --the delayed input data.
);
end delay;
architecture Behaviora of delay is
signal c : integer := 0;
constant d : integer := 100; --number of clock cycles by which input should be delayed.
signal data_temp : std_logic := '0';
type state_type is (idle,delay_c); --defintion of state machine type
signal next_s : state_type; --declare the state machine signal.
begin
process(Clk)
begin
if(rising_edge(Clk)) then
case next_s is
when idle =>
if(valid_data= '1') then
next_s <= delay_c;
data_temp <= data_in; --register the input data.
c <= 1;
end if;
when delay_c =>
if(c = d) then
c <= 1; --reset the count
data_out <= data_temp; --assign the output
next_s <= idle; --go back to idle state and wait for another valid data.
else
c <= c + 1;
end if;
when others =>
NULL;
end case;
end if;
end process;
end Behaviora;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity delay is
port( Clk : in std_logic;
valid_data : in std_logic; -- goes high when the input is valid.
data_in : in std_logic; -- the data input
data_out : out std_logic --the delayed input data.
);
end delay;
architecture Behaviora of delay is
signal c : integer := 0;
constant d : integer := 100; --number of clock cycles by which input should be delayed.
signal data_temp : std_logic := '0';
type state_type is (idle,delay_c); --defintion of state machine type
signal next_s : state_type; --declare the state machine signal.
begin
process(Clk)
begin
if(rising_edge(Clk)) then
case next_s is
when idle =>
if(valid_data= '1') then
next_s <= delay_c;
data_temp <= data_in; --register the input data.
c <= 1;
end if;
when delay_c =>
if(c = d) then
c <= 1; --reset the count
data_out <= data_temp; --assign the output
next_s <= idle; --go back to idle state and wait for another valid data.
else
c <= c + 1;
end if;
when others =>
NULL;
end case;
end if;
end process;
end Behaviora;
The following testbench code was used to test the code.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
signal Clk : std_logic := '0';
signal valid_data : std_logic := '0';
signal data_in,data_out : std_logic := '0';
constant Clk_period : time := 5 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.delay PORT MAP (
Clk => Clk,
valid_data => valid_data,
data_in => data_in,
data_out => data_out
);
-- Clock process definitions
Clk_process :process
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for 100 ns;
valid_data <= '1';
data_in <= '1';
wait;
end process;
END;
USE ieee.std_logic_1164.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
signal Clk : std_logic := '0';
signal valid_data : std_logic := '0';
signal data_in,data_out : std_logic := '0';
constant Clk_period : time := 5 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: entity work.delay PORT MAP (
Clk => Clk,
valid_data => valid_data,
data_in => data_in,
data_out => data_out
);
-- Clock process definitions
Clk_process :process
begin
Clk <= '0';
wait for Clk_period/2;
Clk <= '1';
wait for Clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
wait for 100 ns;
valid_data <= '1';
data_in <= '1';
wait;
end process;
END;
The above design was successfully synthesized in Xilinx ISE software. Note that there are lot of different situations in which a delay can be introduced. But understanding the above concept well, will help you in most of the cases.
There is one limitation to this design. If the input value keep changing before the delay count is reached, then it will only take the first valid value. If you want a delay pipeline then you have to implement a FIFO whose size will depend on the amount of delay. In our case we will need a FIFO size of 100 bits. I will try to cover this in another article.
Some of these articles may be helpful:
Delay generator using a counter.
Clock frequency converter in VHDL.
No comments:
Post a Comment