Commit b6b7d9c2 authored by Pascal Bos's avatar Pascal Bos

fixed issue with hours > 15, added an extra bit.

parent 77ad7376
Pipeline #5219 failed with stage
in 3 seconds
......@@ -12,9 +12,9 @@
-- Last update: 2021-05-04
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: A module that takes the TAI signal from white rabbit and
-- Description: A module that takes the TAI signal from white rabbit and
-- converts it into IRIG_B data. The PR signal is in sync with the PPS.
--
--
-------------------------------------------------------------------------------
-- Copyright (c) 2021 Nikhef
-------------------------------------------------------------------------------
......@@ -46,12 +46,12 @@ entity wr_irigb_conv is
generic(
clk_freq : natural := 125000000
);
Port (
Port (
clk_i : in std_logic;
rst_n_i : in std_logic;
pps_i : in std_logic;
irig_b_o : out std_logic;
irig_b_ctrl_i : in std_logic_vector(17 downto 0) := (others => '0');
irig_b_ctrl_i : in std_logic_vector(17 downto 0) := (others => '0');
tm_time_valid_i : in std_logic;
tm_tai_i : in std_logic_vector(39 downto 0)
);
......@@ -64,42 +64,42 @@ architecture Behavioral of wr_irigb_conv is
signal pps_trigger : std_logic;
type state_type_irig is (IDLE, PR,SEC,P1,MIN,P2,HOUR,P3,DAY_L,P4,DAY_H,P5,YEAR,P6,CTRL_1,P7,CTRL_2,P8,SBS_L,P9,SBS_H,P0,WAIT_FOR_PPS);
signal prs,nxt : state_type_irig;
type divisors_type is array(0 to 4) of std_logic_vector(23 downto 0);
type divideds_type is array(0 to 4) of std_logic_vector(39 downto 0);
type quotients_type is array(0 to 4) of std_logic_vector(39 downto 0);
type quotients_type is array(0 to 4) of std_logic_vector(39 downto 0);
type remainders_type is array(0 to 4) of std_logic_vector(19 downto 0);
constant divisors : divisors_type := (x"00003c", --60 seconds in minute
x"00003c", --60 minutes in hour
x"000018", --24 hours in day
x"0005b5", --365.25*4 days in 4 years
x"015180"); --seconds in a day
signal divideds : divideds_type;
signal quotients : quotients_type;
signal remainders : remainders_type;
signal divideds : divideds_type;
signal quotients : quotients_type;
signal remainders : remainders_type;
--signal divider_pipe_valids : std_logic_vector(0 to 5);
signal divider_input_valids : std_logic_vector(0 to 5);
signal divider_output_valids : std_logic_vector(0 to 5);
signal start_dividers : std_logic;
signal seconds : std_logic_vector(5 downto 0);
signal minutes : std_logic_vector(5 downto 0);
signal hours : std_logic_vector(3 downto 0);
signal hours : std_logic_vector(4 downto 0);
signal days : std_logic_vector(8 downto 0);
signal years : std_logic_vector(39 downto 0); --should outlast the sun
signal sbs : std_logic_vector(17 downto 0);
signal enable_bcd_conv : std_logic;
--all bcd signals are 4bits * amount * of digits + 1 index marker
signal seconds_bcd : std_logic_vector(7 downto 0);
signal minutes_bcd : std_logic_vector(8 downto 0);
signal hours_bcd : std_logic_vector(8 downto 0);
signal days_bcd : std_logic_vector(17 downto 0);
signal years_bcd : std_logic_vector(8 downto 0);
signal years_bcd : std_logic_vector(8 downto 0);
signal days_bcd_tdata_2 : std_logic_vector(23 downto 0);
signal years_bcd_tdata : std_logic_vector(23 DOWNTO 0);
......@@ -108,24 +108,24 @@ architecture Behavioral of wr_irigb_conv is
signal seconds_bcd_tdata : std_logic_vector(23 DOWNTO 0);
signal minutes_bcd_tdata : std_logic_vector(23 DOWNTO 0);
signal days_bcd_valid_1 : std_logic;
signal bcd_ready : std_logic;
type irig_signal_type is (ONE, ZERO, MARK);
signal irig_sig : irig_signal_type;
signal irig_counter_enable : std_logic;
signal irig_bit_comp : std_logic;
signal irig_bit_comp : std_logic;
signal irig_word_cnt : integer range 0 to 8;
constant bit_time : integer := clk_freq/100;
constant bit_time : integer := clk_freq/100;
constant zero_time : natural := bit_time / 5;
constant one_time : natural := bit_time / 2;
constant mark_time : natural := bit_time - zero_time;
signal irig_cnt : integer range 0 to bit_time;
signal total_days : unsigned(39 downto 0);
signal total_days_valid : std_logic;
COMPONENT tai_divider
PORT (
aclk : IN STD_LOGIC;
......@@ -197,24 +197,24 @@ pps_trigger <= '1' when pps_i = '1' and pps_reg = '0' else '0';
-- this statement generates the 4 dividers for: Seconds&Minutes, Hours, Years and SBS, days is a bit more complicated --
-- it utilizes both the dividers "Answer/Quotient" and "Remainder", as can be seen below --
--
-- ___________ ___________ ___________ ___________
-- ___________ ___________ ___________ ___________
-- --------->| |-------------->| |-------------->| |--------------->| |-------->[current year since 1970]
-- Tai_Time | DIVIDE BY |(Answer) | DIVIDE BY |(Answer) | DIVIDE BY |(Answer) |Day in the |
-- Tai_Time | DIVIDE BY |(Answer) | DIVIDE BY |(Answer) | DIVIDE BY |(Answer) |Day in the |
-- (seconds) | 60 | | 60 | | 24 | |year engine|
-- | |------------ | |------------ | |------------ | see |------------
-- | |(Remainder) | | |(Remainder) | | |(Remainder) | | below | |
-- |___________| | |___________| | |___________| | |___________| |
-- V V V V
-- | |------------ | |------------ | |------------ | see |------------
-- | |(Remainder) | | |(Remainder) | | |(Remainder) | | below | |
-- |___________| | |___________| | |___________| | |___________| |
-- V V V V
-- [seconds in the current minute] [minutes in the current hour] [Hour in the current day] [Day in the current year - 1]
--
--
-- Day in the year Engine
-- ______ ___________ _________________
-- --------->| |---------------->| |-------------->| Multiply by 4 |------------------------------------------
-- Days | +365 | | DIVIDE BY |(Answer) | (bit shift 2) | _|_ _|_ _|_ _|_
-- Days | +365 | | DIVIDE BY |(Answer) | (bit shift 2) | _|_ _|_ _|_ _|_
-- | | | 1461 | |_________________| |+ 0|-->year|+ 1|-->year|+ 2|-->year|+ 3|-->year (+29 years) (to start in 2000 instead of 1969)
-- |______| | |------------ ________ |___| |___| |___| |___|
-- | |(Remainder) | / <365 |-----------0 | | |
-- |______| | |------------ ________ |___| |___| |___| |___|
-- | |(Remainder) | / <365 |-----------0 | | |
-- |___________| | / | | | | |
-- | | <730 |-----------|-----------0 | |
-- ->| | | | | |
......@@ -225,7 +225,7 @@ pps_trigger <= '1' when pps_i = '1' and pps_reg = '0' else '0';
-- | | | |
-- _|__ _|__ _|__ _|___
-- |-0 |->days|-365|->days|-730|->days|-1095|->days (+1 for zero-day)
-- |____| |____| |____| |_____|
-- |____| |____| |____| |_____|
......@@ -256,10 +256,10 @@ divider_input_valids(1) <= divider_output_valids(0);
divideds(1) <= quotients(0);
--#2 divde by 24 (hours)
divider_input_valids(2) <= divider_output_valids(1);
divideds(2) <= quotients(1);
divideds(2) <= quotients(1);
--#3 divde by 1461 (4 years)
divider_input_valids(3) <= total_days_valid;
divideds(3) <= std_logic_vector(total_days);
divideds(3) <= std_logic_vector(total_days);
--#4 divide by 15180 (seconds in day)
divider_input_valids(4) <= start_dividers;
divideds(4) <= tai_time_s;
......@@ -291,7 +291,7 @@ begin
hours <= (others => '0');
days <= (others => '0');
years <= (others => '0');
sbs <= (others => '0');
sbs <= (others => '0');
enable_bcd_conv <= '0';
remaining_days := (others => '0');
block_4_years := (others => '0');
......@@ -307,7 +307,7 @@ begin
all_rdy(1) := '1';
end if;
if divider_output_valids(2) = '1' then --latch hours
hours <= remainders(2)(3 downto 0);
hours <= remainders(2)(4 downto 0);
all_rdy(2) := '1';
end if;
if divider_output_valids(3) = '1' then --calculate days and years.
......@@ -326,7 +326,7 @@ begin
years_buffer := (block_4_years(37 downto 0) & "00") + 2;
days <= std_logic_vector(remaining_days(8 downto 0)-1095+1);
end if;
if years_buffer >= 30 then --Check if is before the year 2000 or after.
if years_buffer >= 30 then --Check if is before the year 2000 or after.
years_buffer := years_buffer - 30;
else
years_buffer := years_buffer + 70;
......@@ -363,18 +363,18 @@ begin
end if;
end if;
end process irig_counter;
irig_bit_comp <= '1' when irig_cnt = bit_time-1 else '0';
irig_bit_comp <= '1' when irig_cnt = bit_time-1 else '0';
--the driver of the irig_b outbut signal
--this is combinatoric to ensure a same-clock cycle start with the pps.
irig_b_o <= pps_i when (prs = IDLE or prs = WAIT_FOR_PPS)
else '0' when (rst_n_i = '0')
or (irig_cnt > mark_time)
irig_b_o <= pps_i when (prs = IDLE or prs = WAIT_FOR_PPS)
else '0' when (rst_n_i = '0')
or (irig_cnt > mark_time)
or (irig_cnt > one_time and irig_sig = ONE)
or (irig_cnt > zero_time and irig_sig = ZERO)
or (irig_cnt > zero_time and irig_sig = ZERO)
else '1';
--counts its position within the current irig_b word ( f.e.: 1,2,4,8,10,20,40)
--counts its position within the current irig_b word ( f.e.: 1,2,4,8,10,20,40)
word_counter : process (clk_i, rst_n_i) is
begin
if rst_n_i = '0' then
......@@ -399,7 +399,7 @@ begin
end if;
end process state_register;
next_state_decoder : process(prs,rst_n_i,pps_trigger,irig_word_cnt,irig_bit_comp,irig_cnt) is
next_state_decoder : process(prs,rst_n_i,pps_trigger,irig_word_cnt,irig_bit_comp,irig_cnt) is
begin
if rst_n_i = '0' then
nxt <= IDLE;
......@@ -407,7 +407,7 @@ begin
nxt <= PR;
else
case prs is
when IDLE =>
when IDLE =>
nxt <= IDLE; -- stay here until pps_trigger jumps to PR.
when PR =>
if irig_bit_comp = '1' then
......@@ -415,7 +415,7 @@ begin
else
nxt <= PR;
end if;
when SEC =>
when SEC =>
if irig_word_cnt >= 7 and irig_bit_comp = '1' then --checks if the last bit has been send
nxt <= P1;
else
......@@ -427,13 +427,13 @@ begin
else
nxt <= P1;
end if;
when MIN =>
when MIN =>
if irig_word_cnt >= 8 and irig_bit_comp = '1' then
nxt <= P2;
else
nxt <= MIN;
end if;
when P2 =>
end if;
when P2 =>
if irig_bit_comp = '1' then
nxt <= HOUR;
else
......@@ -444,8 +444,8 @@ begin
nxt <= P3;
else
nxt <= HOUR;
end if;
when P3 =>
end if;
when P3 =>
if irig_bit_comp = '1' then
nxt <= DAY_L;
else
......@@ -487,7 +487,7 @@ begin
else
nxt <= P6;
end if;
when CTRL_1 =>
when CTRL_1 =>
if irig_word_cnt >= 8 and irig_bit_comp = '1' then
nxt <= P7;
else
......@@ -541,18 +541,18 @@ begin
end if;
end process next_state_decoder;
output_decoder : process(prs, irig_word_cnt, seconds_bcd, minutes_bcd, hours_bcd, days_bcd, years_bcd, irig_b_ctrl_s, sbs) is
output_decoder : process(prs, irig_word_cnt, seconds_bcd, minutes_bcd, hours_bcd, days_bcd, years_bcd, irig_b_ctrl_s, sbs) is
variable irig_bit : std_logic;
variable irig_mark : std_logic;
begin
irig_mark := '0';
irig_bit := '0';
case prs is
when IDLE | PR | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 | P9 | P0 | WAIT_FOR_PPS =>
case prs is
when IDLE | PR | P1 | P2 | P3 | P4 | P5 | P6 | P7 | P8 | P9 | P0 | WAIT_FOR_PPS =>
irig_mark := '1'; -- All these states are MARK signals.
when SEC =>
when SEC =>
irig_bit := seconds_bcd(irig_word_cnt);
when MIN =>
irig_bit := minutes_bcd(irig_word_cnt);
......@@ -571,9 +571,9 @@ begin
when SBS_L =>
irig_bit := sbs(irig_word_cnt);
when SBS_H =>
irig_bit := sbs(irig_word_cnt+9);
irig_bit := sbs(irig_word_cnt+9);
end case;
if irig_mark = '1' then
irig_sig <= MARK;
elsif irig_bit = '1' then
......@@ -584,14 +584,14 @@ begin
end process output_decoder;
--The divide-by-ten dividers to convert binary values into bcd values
-- ___________
-- ___________
-- --------->| |---------> 4
-- Value | DIVIDE BY | (Answer)
-- (binary) | 10 |
-- [f.e: 42] | |---------> 2
-- | | (Remainder)
-- |___________|
--
-- Value | DIVIDE BY | (Answer)
-- (binary) | 10 |
-- [f.e: 42] | |---------> 2
-- | | (Remainder)
-- |___________|
--
--The diveder for "days" has an additional divide-by-100 divider because there are more then 99 days in a year.
seconds_bcd_divider : bcd_divider
PORT MAP (
......@@ -608,7 +608,7 @@ seconds_bcd_divider : bcd_divider
);
--all the bcd data has some '0' inserted between then to separate decimal and unit, as is requierd by IRIG
seconds_bcd <= seconds_bcd_tdata(10 downto 8) & '0' & seconds_bcd_tdata(3 downto 0);
minutes_bcd_divider : bcd_divider
PORT MAP (
aclk => clk_i,
......@@ -623,8 +623,8 @@ minutes_bcd_divider : bcd_divider
m_axis_dout_tdata => minutes_bcd_tdata
);
minutes_bcd <= '0' & minutes_bcd_tdata(10 downto 8) & '0' & minutes_bcd_tdata(3 downto 0);
hours_bcd_divider : bcd_divider
PORT MAP (
aclk => clk_i,
......@@ -633,14 +633,14 @@ hours_bcd_divider : bcd_divider
s_axis_divisor_tdata => x"0A",
s_axis_dividend_tvalid => enable_bcd_conv,
s_axis_dividend_tready => open,
s_axis_dividend_tdata(15 downto 4) => (others => '0'),
s_axis_dividend_tdata(3 downto 0) => hours,
s_axis_dividend_tdata(15 downto 5) => (others => '0'),
s_axis_dividend_tdata(4 downto 0) => hours,
m_axis_dout_tvalid => open,
m_axis_dout_tdata => hours_bcd_tdata
);
hours_bcd <= "00" & hours_bcd_tdata(9 downto 8) & '0' & hours_bcd_tdata(3 downto 0);
years_bcd_divider : bcd_divider
PORT MAP (
aclk => clk_i,
......@@ -668,21 +668,21 @@ days_bcd_divider_1 : bcd_divider
m_axis_dout_tvalid => days_bcd_valid_1,
m_axis_dout_tdata => days_bcd_tdata_2
);
days_bcd_divider_2 : bcd_divider
PORT MAP (
aclk => clk_i,
s_axis_divisor_tvalid => days_bcd_valid_1,
s_axis_divisor_tready => open,
s_axis_divisor_tdata => x"0A",
s_axis_divisor_tdata => x"0A",
s_axis_dividend_tvalid => days_bcd_valid_1,
s_axis_dividend_tready => open,
s_axis_dividend_tdata(15 downto 8) => (others => '0'),
s_axis_dividend_tdata(7 downto 0) => days_bcd_tdata_2(7 downto 0),
m_axis_dout_tvalid => bcd_ready,
m_axis_dout_tdata => days_bcd_tdata_1
);
);
days_bcd <= "0000000" & days_bcd_tdata_2(9 downto 8) & days_bcd_tdata_1(11 downto 8) & '0' & days_bcd_tdata_1(3 downto 0);
end Behavioral;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment