shaiko
Advanced Member level 5
- Joined
- Aug 20, 2011
- Messages
- 2,644
- Helped
- 303
- Reputation
- 608
- Reaction score
- 297
- Trophy points
- 1,363
- Activity points
- 18,302
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
library work ;
use work.package_functions_general.all ;
entity delay_generator is
generic
(
FREQUENCY : positive := 50000000
) ;
port
(
CLOCK : in std_logic ;
INPUT : in std_logic ;
RESET : in std_logic ;
DELAY_DURATION : in unsigned ;
OUTPUT : out std_logic
);
end entity delay_generator ;
architecture synthesizable_generator_delay of delay_generator is
constant width_unsigned_frequency : positive := log_2_decimal ( FREQUENCY ) ;
constant unsigned_frequency : unsigned := to_unsigned ( FREQUENCY , width_unsigned_frequency ) ;
constant maximum_possible_delay_duration : unsigned ( DELAY_DURATION ' range ) := ( others => '1' ) ;
constant maximum_possible_cycles_to_delay : unsigned := cylces_from_time ( maximum_possible_delay_duration , "ns" , unsigned_frequency ) ;
constant shift_register_width : positive := to_integer ( maximum_possible_cycles_to_delay ) ;
signal shift_register : unsigned ( shift_register_width - 1 downto 0 ) := ( others => '0' ) ;
signal required_number_of_cycles : unsigned ( 31 downto 0 ) := ( others => '0' ) ;
begin
required_number_of_cycles <= cylces_from_time ( DELAY_DURATION , "ns" , unsigned_frequency ) ;
[COLOR="#FF0000"]OUTPUT <= shift_register ( to_integer ( required_number_of_cycles ) ) ;[/COLOR]
shifting_left : process ( RESET , CLOCK ) is
begin
if RESET = '1' then
shift_register <= ( others => '0' ) ;
elsif rising_edge ( CLOCK ) then
shift_register <= shift_register ( shift_register ' high - 1 downto 0 ) & INPUT ;
end if ;
end process shifting_left ;
end architecture synthesizable_generator_delay ;
This suggests that the signal "required_number_of_cycles" is supposedly 2097151 . Looking at the waveform window indeed shows that the signal is given this value (when it should've been given "000000000000111110100" (500 decimal).** Fatal: (vsim-3734) Index value 2097151 is out of range 104856 downto 0.
--OUTPUT <= shift_register ( to_integer ( required_number_of_cycles ) ) ;
I don't see why. My log2 is thoroughly tested and works fine.Wouldn't it be better to use log2() function from math_real library then create ist's own version ?
I disagree. Driving "DELAY_DURATION" with a variable ( not a constant) may result in the implementation of very slow combinatorial logic - yet it's perfectly synthesizable. Anyways, this is out of the scope for this post.Also you need to take into account that if DELAY_DURATION port is not driven by a constant you will end up with very unsythesable code.
sure.we need package_functions_general.all to compile the code
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
package package_functions_general is
function log_2_decimal ( d : natural ) return natural ; -- Gives the bit number of the MSB ( for example 230 in decimal is 11100110 in binary. So the function will return the number: 7.
function restoring_divide
(
numerator : unsigned ;
denominator : unsigned
)
return unsigned ;
function time_period_from_frequency -- Calculates the time period in "time_units" of "frequency_hz".
(
frequency_hz : unsigned ;
time_units : string
)
return unsigned ;
function cylces_from_time -- Calculates the number of cycles that are needed for "desired_time" in "time_units" to pass when the clock frequency is "frequency_hz".
(
desired_time : unsigned ;
time_units : string ;
frequency_hz : unsigned
)
return unsigned ;
end package package_functions_general ;
package body package_functions_general is
function restoring_divide
(
numerator : unsigned ;
denominator : unsigned
)
return unsigned is
variable temp_numerator : unsigned ( numerator ' range ) := numerator ;
variable temp_numerator_with_denominator_length : unsigned ( denominator ' range ) := ( others => '0' ) ;
variable temp_denominator : unsigned ( denominator ' range ) := denominator ;
variable temp_denominator_with_numerator_length : unsigned ( numerator ' range ) := ( others => '0' ) ;
variable temp_remainder : unsigned ( denominator ' length downto 0 ) := ( others => '0' ) ;
variable temp_remainder_with_numerator_length : unsigned ( numerator ' length downto 0 ) := ( others => '0' ) ;
begin
if numerator ' length = denominator ' length then
for index in 0 to denominator ' length - 1
loop
temp_remainder ( denominator ' length - 1 downto 1 ) :=
temp_remainder ( denominator ' length - 2 downto 0 ) ;
temp_remainder ( 0 ) :=
temp_numerator ( numerator ' length - 1 ) ;
temp_numerator ( numerator ' length - 1 downto 1 ) :=
temp_numerator ( numerator ' length - 2 downto 0 ) ;
temp_remainder := temp_remainder - temp_denominator ;
if ( temp_remainder ( denominator ' length ) = '1' ) then
temp_numerator ( 0 ) := '0' ;
temp_remainder := temp_remainder + temp_denominator ;
else
temp_numerator ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator ;
elsif numerator ' length > denominator ' length then
temp_denominator_with_numerator_length := resize ( denominator , numerator ' length ) ;
for index in 0 to temp_denominator_with_numerator_length ' length - 1
loop
temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length - 1 downto 1 ) :=
temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length - 2 downto 0 ) ;
temp_remainder_with_numerator_length ( 0 ) := temp_numerator ( numerator ' length - 1 ) ;
temp_numerator ( numerator ' length - 1 downto 1 ) := temp_numerator ( numerator ' length - 2 downto 0 ) ;
temp_remainder_with_numerator_length := temp_remainder_with_numerator_length - temp_denominator ;
if ( temp_remainder_with_numerator_length ( temp_denominator_with_numerator_length ' length ) = '1' ) then
temp_numerator ( 0 ) := '0' ;
temp_remainder_with_numerator_length := temp_remainder_with_numerator_length + temp_denominator ;
else
temp_numerator ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator ;
else
temp_numerator_with_denominator_length := resize ( numerator , denominator ' length ) ;
for index in 0 to denominator ' length - 1
loop
temp_remainder ( denominator ' length - 1 downto 1 ) := temp_remainder ( denominator ' length - 2 downto 0 ) ;
temp_remainder ( 0 ) := temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 1 ) ;
temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 1 downto 1 ) :=
temp_numerator_with_denominator_length ( temp_numerator_with_denominator_length ' length - 2 downto 0 ) ;
temp_remainder := temp_remainder - temp_denominator ;
if ( temp_remainder ( denominator ' length ) = '1' ) then
temp_numerator_with_denominator_length ( 0 ) := '0' ;
temp_remainder := temp_remainder + temp_denominator ;
else
temp_numerator_with_denominator_length ( 0 ) := '1' ;
end if ;
end loop ;
return temp_numerator_with_denominator_length ;
end if ;
end function restoring_divide ;
function log_2_decimal
(
d : natural
)
return natural is
variable temp_d : natural := d ;
variable n : natural := 0 ;
begin
while temp_d > 1
loop
temp_d := temp_d / 2 ;
n := n + 1 ;
end loop ;
if d > 2 ** n then
return ( n + 1 ) ;
else
return ( n ) ;
end if ;
end function log_2_decimal ;
function time_period_from_frequency
(
frequency_hz : unsigned ;
time_units : string
)
return unsigned is
variable second_ms : unsigned ( 9 downto 0 ) := "1111101000" ; -- 1,000 ms is 1 second.
variable second_us : unsigned ( 19 downto 0 ) := "11110100001001000000" ; -- 1,000,000 us is 1 second.
variable second_ns : unsigned ( 31 downto 0 ) := "00111011100110101100101000000000" ; -- 1,000,000,000 ns is 1 second.
variable result_ms : unsigned ( 9 downto 0 ) := ( others => '0' ) ;
variable result_us : unsigned ( 19 downto 0 ) := ( others => '0' ) ;
variable result_ns : unsigned ( 31 downto 0 ) := ( others => '0' ) ;
begin
if time_units = "ms" then
result_ms := restoring_divide ( second_ms , frequency_hz ) ;
return result_ms ;
elsif time_units = "us" then
result_us := restoring_divide ( second_us , frequency_hz ) ;
return result_us ;
elsif time_units = "ns" then
result_ns := restoring_divide ( second_ns , frequency_hz ) ;
return result_ns ;
end if ;
end function time_period_from_frequency ;
function cylces_from_time -- Calculates the number of cycles that are needed for "desired_time" in "time_units" to pass when the clock frequency is "frequency_hz".
(
desired_time : unsigned ;
time_units : string ;
frequency_hz : unsigned
)
return unsigned is
variable result_ms : unsigned ( 9 downto 0 ) := ( others => '0' ) ;
variable result_us : unsigned ( 19 downto 0 ) := ( others => '0' ) ;
variable result_ns : unsigned ( 31 downto 0 ) := ( others => '0' ) ;
variable result_ps : unsigned ( 39 downto 0 ) := ( others => '0' ) ;
variable result_fs : unsigned ( 49 downto 0 ) := ( others => '0' ) ;
begin
if time_units = "ms" then
result_ms := restoring_divide ( desired_time , time_period_from_frequency ( frequency_hz , time_units ) ) ;
return result_ms ;
elsif time_units = "us" then
result_us := restoring_divide ( desired_time , time_period_from_frequency ( frequency_hz , time_units ) ) ;
return result_us ;
elsif time_units = "ns" then
result_ns := restoring_divide ( desired_time , time_period_from_frequency ( frequency_hz , time_units ) ) ;
return result_ns ;
elsif time_units = "ps" then
result_ps := restoring_divide ( desired_time , time_period_from_frequency ( frequency_hz , time_units ) ) ;
return result_ps ;
elsif time_units = "fs" then
result_fs := restoring_divide ( desired_time , time_period_from_frequency ( frequency_hz , time_units ) ) ;
return result_fs ;
end if ;
end function cylces_from_time ;
end package body package_functions_general ;
I don't see why. My log2 is thoroughly tested and works fine.
signal CLOCK,INPUT,RESET,OUTPUT : std_logic := '1';
signal DELAY_DURATION : unsigned(20 downto 0) := to_unsigned(0,21);
begin
DELAY_DURATION <= to_unsigned(10000,21);
CLOCK <= not CLOCK after 10 ns;
RESET <= '0' after 5 ns;
INPUT <= '0' after 30 ns;
I disagree. Driving "DELAY_DURATION" with a variable ( not a constant) may result in the implementation of very slow combinatorial logic - yet it's perfectly synthesizable. Anyways, this is out of the scope for this post.
Strange. I use Modelsim and it fails...works well.
There's nothing un-synthesizable in nature with any of the functions in the package.On 2nd biggest Cyclone V with 21-bit delay_duraration, Quartus try to synthesie the code now for 16 minutes (46%) and still counting the time.
can you please post your TB ?I used now Modelsim ALTERA STARTER EDITION 10.1d still ok
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity eda is
end entity eda;
architecture BEHAVE of eda is
component delay_generator is
generic
(
FREQUENCY : positive := 50000000
) ;
port
(
CLOCK : in std_logic ;
INPUT : in std_logic ;
RESET : in std_logic ;
DELAY_DURATION : in unsigned ;
OUTPUT : out std_logic
);
end component delay_generator ;
-----------------------------------------------------
signal CLOCK,INPUT,RESET,OUTPUT : std_logic := '1';
signal DELAY_DURATION : unsigned(20 downto 0) := to_unsigned(0,21);
begin
DELAY_DURATION <= to_unsigned(10000,21);
CLOCK <= not CLOCK after 10 ns;
RESET <= '0' after 5 ns;
INPUT <= '0' after 30 ns;
DD: delay_generator port map (
CLOCK => CLOCK,
INPUT => INPUT,
RESET => RESET,
DELAY_DURATION => DELAY_DURATION,
OUTPUT => OUTPUT
);
end architecture BEHAVE;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
entity eda is
end entity eda;
architecture BEHAVE of eda is
component delay_generator is
generic
(
FREQUENCY : positive := 50000000
) ;
port
(
CLOCK : in std_logic ;
INPUT : in std_logic ;
RESET : in std_logic ;
DELAY_DURATION : in unsigned ;
OUTPUT : out std_logic
);
end component delay_generator ;
-----------------------------------------------------
signal CLOCK,INPUT,RESET,OUTPUT : std_logic := '1';
signal DELAY_DURATION : unsigned(20 downto 0) [COLOR="#FF0000"]:= to_unsigned(0,21)[/COLOR];
begin
DELAY_DURATION <= to_unsigned(10000,21);
CLOCK <= not CLOCK after 10 ns;
RESET <= '0' after 5 ns;
INPUT <= '0' after 30 ns;
DD: delay_generator port map (
CLOCK => CLOCK,
INPUT => INPUT,
RESET => RESET,
DELAY_DURATION => DELAY_DURATION,
OUTPUT => OUTPUT
);
end architecture BEHAVE;
signal shift_register : unsigned ( shift_register_width downto 0 ) := ( others => '0' ) ;
signal shift_register : unsigned ( shift_register_width [COLOR="#FF0000"]- 1[/COLOR] downto 0 ) := ( others => '0' ) ;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?