M
Manfred Balik
Guest
Please can someone help me:
I have realized a watch viewing nanoseconds and seconds from a 31.611 MHz
clock (it's the only one in the design).
For high precision I count in femtoseconds - out of them, I calculate
nanoseconds and seconds.
Unfortunately the code I wrote is to slow in the Altera APEX 20KE I use
Please can someone help me to improve the code
Thanks, Manfred
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY timestamp_counter IS
PORT
(
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
time_sec : OUT STD_LOGIC_VECTOR(0 to 30);
time_nanosec : OUT STD_LOGIC_VECTOR(0 to 29)
);
END timestamp_counter;
ARCHITECTURE timestamp_counter_architecture OF timestamp_counter IS
CONSTANT clock_cycle_femtosec : integer := 31_634_558; -- 1 clock cycle in
femto seconds
-- 31.611 MHz == 31,634 557 590 712 ... ns
-- => Error: -4.09288E-16 s/cycle
-- = -1.2938E-8 s/sec
-- = -7.7628E-7 s/min
-- = -4.65768E-5 s/h
-- = -1.1178432E-3 s/day
-- = -0,408012768 s/year (-0,4091306112 s/leap year ;-))
FUNCTION int2slvect(int_value : INTEGER; size : INTEGER) RETURN
std_logic_vector;
FUNCTION int2slvect(int_value : INTEGER; size : INTEGER) RETURN
std_logic_vector IS
VARIABLE result : std_logic_vector(0 TO size-1);
BEGIN
FOR i IN 0 TO size-1 LOOP
IF ((int_value/(2**i)) REM 2) = 0 THEN
result(i) := '0';
ELSE
result(i) := '1';
END IF;
END LOOP;
RETURN result;
END int2slvect;
BEGIN
timestamp_counter_process : PROCESS (clk,reset) IS
VARIABLE sec: integer RANGE 0 TO 2_147_483_647;
VARIABLE nanosec: integer RANGE 0 TO 1_000_000_050;
VARIABLE femtosec: integer RANGE 0 TO 33_000_000;
VARIABLE read_timespec_prev: std_logic;
BEGIN
IF reset = '1' THEN
sec := 0;
nanosec := 0;
femtosec := 0;
read_timespec_prev := '0';
timespec_sec <= (OTHERS => '0');
timespec_nanosec <= (OTHERS => '0');
time_sec <= (OTHERS => '0');
time_nanosec <= (OTHERS => '0');
ELSIF clk'event AND clk = '1' THEN
femtosec := femtosec + clock_cycle_femtosec;
IF femtosec > 31_999_999 THEN
nanosec := nanosec + 32;
femtosec := femtosec - 32_000_000;
ELSIF femtosec > 30_999_999 THEN
nanosec := nanosec + 31;
femtosec := femtosec - 31_000_000;
END IF;
IF nanosec > 999_999_999 THEN
sec := sec + 1;
nanosec := nanosec - 1_000_000_000;
END IF;
time_sec <= int2slvect(sec,31);
time_nanosec <= int2slvect(nanosec,30);
END IF;
END PROCESS timestamp_counter_process;
END timestamp_counter_architecture;
I have realized a watch viewing nanoseconds and seconds from a 31.611 MHz
clock (it's the only one in the design).
For high precision I count in femtoseconds - out of them, I calculate
nanoseconds and seconds.
Unfortunately the code I wrote is to slow in the Altera APEX 20KE I use
Please can someone help me to improve the code
Thanks, Manfred
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY timestamp_counter IS
PORT
(
clk : IN STD_LOGIC;
reset : IN STD_LOGIC;
time_sec : OUT STD_LOGIC_VECTOR(0 to 30);
time_nanosec : OUT STD_LOGIC_VECTOR(0 to 29)
);
END timestamp_counter;
ARCHITECTURE timestamp_counter_architecture OF timestamp_counter IS
CONSTANT clock_cycle_femtosec : integer := 31_634_558; -- 1 clock cycle in
femto seconds
-- 31.611 MHz == 31,634 557 590 712 ... ns
-- => Error: -4.09288E-16 s/cycle
-- = -1.2938E-8 s/sec
-- = -7.7628E-7 s/min
-- = -4.65768E-5 s/h
-- = -1.1178432E-3 s/day
-- = -0,408012768 s/year (-0,4091306112 s/leap year ;-))
FUNCTION int2slvect(int_value : INTEGER; size : INTEGER) RETURN
std_logic_vector;
FUNCTION int2slvect(int_value : INTEGER; size : INTEGER) RETURN
std_logic_vector IS
VARIABLE result : std_logic_vector(0 TO size-1);
BEGIN
FOR i IN 0 TO size-1 LOOP
IF ((int_value/(2**i)) REM 2) = 0 THEN
result(i) := '0';
ELSE
result(i) := '1';
END IF;
END LOOP;
RETURN result;
END int2slvect;
BEGIN
timestamp_counter_process : PROCESS (clk,reset) IS
VARIABLE sec: integer RANGE 0 TO 2_147_483_647;
VARIABLE nanosec: integer RANGE 0 TO 1_000_000_050;
VARIABLE femtosec: integer RANGE 0 TO 33_000_000;
VARIABLE read_timespec_prev: std_logic;
BEGIN
IF reset = '1' THEN
sec := 0;
nanosec := 0;
femtosec := 0;
read_timespec_prev := '0';
timespec_sec <= (OTHERS => '0');
timespec_nanosec <= (OTHERS => '0');
time_sec <= (OTHERS => '0');
time_nanosec <= (OTHERS => '0');
ELSIF clk'event AND clk = '1' THEN
femtosec := femtosec + clock_cycle_femtosec;
IF femtosec > 31_999_999 THEN
nanosec := nanosec + 32;
femtosec := femtosec - 32_000_000;
ELSIF femtosec > 30_999_999 THEN
nanosec := nanosec + 31;
femtosec := femtosec - 31_000_000;
END IF;
IF nanosec > 999_999_999 THEN
sec := sec + 1;
nanosec := nanosec - 1_000_000_000;
END IF;
time_sec <= int2slvect(sec,31);
time_nanosec <= int2slvect(nanosec,30);
END IF;
END PROCESS timestamp_counter_process;
END timestamp_counter_architecture;