Creating delay chain with generics

T

Tobias Baumann

Hi

I try to implement a synthesizable delay chain. Here a working example:

library ieee;
use ieee.std_logic_1164.all;

entity delay_gate is

generic (
ACTIVE_EDGE : std_logic := '1';
MAX_DELAY_GATE_CYCLES : integer := 7
);

port (
clk_in : in std_logic;

data_in : in std_logic_vector(9 downto 0);
num_delays_in : in integer range 0 to MAX_DELAY_GATE_CYCLES;
data_q : out std_logic_vector(9 downto 0)

);

end entity delay_gate;

architecture RTL of delay_gate is

type delay_gate_data_type is array (0 to MAX_DELAY_GATE_CYCLES) of
std_logic_vector(9 downto 0);

signal delay_data : delay_gate_data_type := (others => (others =>
'0'));

begin

-- first element has no delay
delay_data(0) <= data_in;

delay_proc: process(clk_in)
begin
if (clk_in'event and clk_in = ACTIVE_EDGE) then

delay_data(1) <= delay_data(0);
delay_data(2) <= delay_data(1);
delay_data(3) <= delay_data(2);
delay_data(4) <= delay_data(3);
delay_data(5) <= delay_data(4);
delay_data(6) <= delay_data(5);
delay_data(7) <= delay_data(6);

end if;
end process;

with num_delays_in select
data_q <= delay_data(0) when 0,
delay_data(1) when 1,
delay_data(2) when 2,
delay_data(3) when 3,
delay_data(4) when 4,
delay_data(5) when 5,
delay_data(6) when 6,
delay_data(7) when 7,
delay_data(0) when others;

end architecture RTL;

The problem is that I want to have a real generic entity so that I
haven't to change delay_proc and the with...select statement by hand.

Can someone help me finding the correct VHDL syntax? I tried using a
for...loop, but the simulation results aren't good (data_q is undefined).

Thanks a lot for any help.

Tobias
 
R

Rob Gaddi

Hi

I try to implement a synthesizable delay chain. Here a working example:

library ieee;
use ieee.std_logic_1164.all;

entity delay_gate is

generic (
ACTIVE_EDGE : std_logic := '1';
MAX_DELAY_GATE_CYCLES : integer := 7
);

port (
clk_in : in std_logic;

data_in : in std_logic_vector(9 downto 0);
num_delays_in : in integer range 0 to MAX_DELAY_GATE_CYCLES;
data_q : out std_logic_vector(9 downto 0)

);

end entity delay_gate;

architecture RTL of delay_gate is

type delay_gate_data_type is array (0 to MAX_DELAY_GATE_CYCLES) of
std_logic_vector(9 downto 0);

signal delay_data : delay_gate_data_type := (others => (others =>
'0'));

begin

-- first element has no delay
delay_data(0) <= data_in;

delay_proc: process(clk_in)
begin
if (clk_in'event and clk_in = ACTIVE_EDGE) then

delay_data(1) <= delay_data(0);
delay_data(2) <= delay_data(1);
delay_data(3) <= delay_data(2);
delay_data(4) <= delay_data(3);
delay_data(5) <= delay_data(4);
delay_data(6) <= delay_data(5);
delay_data(7) <= delay_data(6);

end if;
end process;

with num_delays_in select
data_q <= delay_data(0) when 0,
delay_data(1) when 1,
delay_data(2) when 2,
delay_data(3) when 3,
delay_data(4) when 4,
delay_data(5) when 5,
delay_data(6) when 6,
delay_data(7) when 7,
delay_data(0) when others;

end architecture RTL;

The problem is that I want to have a real generic entity so that I
haven't to change delay_proc and the with...select statement by hand.

Can someone help me finding the correct VHDL syntax? I tried using a
for...loop, but the simulation results aren't good (data_q is undefined).

Thanks a lot for any help.

Tobias

Delay chains are tricky nastiness that in practice no one sensible
should ever use. So when I've use them, I generally find
that I need to directly instantiate some kind of low-level primitive of
the specific target device. Then I'll lay some vendor-specific
placement constraints over top, in order to get something that a) won't
synthesize out and b) holds anything even resembling a constant timing
between builds.

Regarding your design, you can't really do what you want with a clocked
process. A clocked process implies "Figure this all out ahead of time,
and put flops that latch the result of it all on this clock edge.",
which is the antithesis of what you want.

To be a bit of a jerk for a moment, you don't seem to have a
particularly strong grasp of VHDL or FPGA design. That's no crime, we
all cut our teeth sometime, but anything involving asynchronous delay
lines tends to be pretty touchy, advanced stuff that serious FPGA
jocks with lots of experience will go to great lengths to avoid. If you
can explain a bit more about your problem, there's a very good chance
that there's a better solution. Or worse, that there isn't, but
the one you're trying won't work either.
 
T

Tobias Baumann

Thanks for your answer.

The problem I try to solve:

I have some data, which will be generated synchronously with my clock.
In some cases I need the data with an latency for a well known number of
clock cycles. So I need an entity where I can set the number of clock
cycles to delay my data. Maybe "delay chain" isn't the right keyword but
"register pipelining". And I think register pipelining can be well done
in FPGA using VHDL.

Maybe you can give me a hint how to build up such an entity.

Tobias
 
R

Rob Gaddi

Thanks for your answer.

The problem I try to solve:

I have some data, which will be generated synchronously with my clock.
In some cases I need the data with an latency for a well known number of
clock cycles. So I need an entity where I can set the number of clock
cycles to delay my data. Maybe "delay chain" isn't the right keyword but
"register pipelining". And I think register pipelining can be well done
in FPGA using VHDL.

Maybe you can give me a hint how to build up such an entity.

Tobias

That's a much easier problem than I thought you had. In that case,
basically what you need is to take advantage of the fact that arrays
can be indexed and sliced. Try something like this:

....
type delay_gate_data_type is array (1 to MAX_DELAY_GATE_CYCLES) of
std_logic_vector(9 downto 0);

signal delay_data : delay_gate_data_type := (others => (others =>
'0'));

begin

delay_proc: process(clk_in)
begin
if (clk_in'event and clk_in = ACTIVE_EDGE) then
delay_data <= data_in & delay_data(1 to MAX_DELAY_GATE_CYCLES-1);
end if;
end process;

data_q <= data_in when (num_delays_in = 0)
else delay_data(num_delays_in);
....
 
E

Enrik Berkhan

Tobias Baumann said:
Can someone help me finding the correct VHDL syntax? I tried using a
for...loop, but the simulation results aren't good (data_q is undefined).

the following should work, not even generate is needed here:

-- 8< --
architecture RTL of delay_gate is

type delay_gate_data_type is array (0 to MAX_DELAY_GATE_CYCLES)
of std_logic_vector(9 downto 0);
signal delay_data : delay_gate_data_type := (others => (others => '0'));

begin

-- first element has no delay
delay_data(0) <= data_in;

delay_proc: process(clk_in)
begin
if clk_in'event and clk_in = ACTIVE_EDGE then
delay_data(1 to MAX_DELAY_GATE_CYCLES) <=
delay_data(0 to MAX_DELAY_GATE_CYCLES-1);
end if;
end process;

data_q <= delay_data(num_delays_in);

end architecture RTL;
-- >8 --

Looks good in ModelSim and in Quartus II (11.1), using the expected number of
FFs and some additional LEs for the output mux.

Enrik
 
G

Gerhard Hoffmann

I have some data, which will be generated synchronously with my clock.
In some cases I need the data with an latency for a well known number of
clock cycles. So I need an entity where I can set the number of clock
cycles to delay my data. Maybe "delay chain" isn't the right keyword but
"register pipelining". And I think register pipelining can be well done
in FPGA using VHDL.

Maybe you can give me a hint how to build up such an entity.

take a look at my sine & cosine module on

< http://opencores.org/project,sincos >

it contains a programmable pipeline register entity that does exactly
that.

regards, Gerhard
 
Joined
Jan 29, 2009
Messages
152
Reaction score
0
This compiles (untested though) :
Code:
library ieee;
use ieee.std_logic_1164.all;

entity delay_gate is

generic (
ACTIVE_EDGE : std_logic := '1';
MAX_DELAY_GATE_CYCLES : integer := 7
);

port (
clk_in : in std_logic;

data_in : in std_logic_vector(9 downto 0);
num_delays_in : in integer range 0 to MAX_DELAY_GATE_CYCLES;
data_q : out std_logic_vector(9 downto 0)

);

end entity delay_gate;

architecture RTL of delay_gate is

type delay_gate_data_type is array (0 to MAX_DELAY_GATE_CYCLES) of
std_logic_vector(9 downto 0);

signal delay_data : delay_gate_data_type := (others => (others =>
'0'));

begin

-- first element has no delay
delay_data(0) <= data_in;

delay_proc: process(clk_in)
begin
if (clk_in'event and clk_in = ACTIVE_EDGE) then

  for i in 0 to MAX_DELAY_GATE_CYCLES-1 loop
    delay_data(i + 1) <= delay_data(i);
  end loop;

end if;
end process;

process (num_delays_in, delay_data)
begin
--  case num_delays_in is
--    when 0 to cycles => data_q <= delay_data(num_delays_in);
--    when others => data_q <= delay_data(0);
--  end case;
  if num_delays_in >= 0 and num_delays_in <= MAX_DELAY_GATE_CYCLES then
    data_q <= delay_data(num_delays_in);
  else
    data_q <= delay_data(0);
  end if;
end process;

end architecture RTL;
I first replaced the 'select' statement with equivalent process -- but that complained about the generic not being 'locally static'.
Replacing by the 'if' helps there -- at least to compile.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top