apb_lfr_time_management.vhd
329 lines
| 10.2 KiB
| text/x-vhdl
|
VhdlLexer
pellion
|
r293 | ---------------------------------------------------------------------------------- | ||
-- Company: | ||||
-- Engineer: | ||||
-- | ||||
-- Create Date: 11:17:05 07/02/2012 | ||||
-- Design Name: | ||||
-- Module Name: apb_lfr_time_management - Behavioral | ||||
-- Project Name: | ||||
-- Target Devices: | ||||
-- Tool versions: | ||||
-- Description: | ||||
-- | ||||
-- Dependencies: | ||||
-- | ||||
-- Revision: | ||||
-- Revision 0.01 - File Created | ||||
-- Additional Comments: | ||||
-- | ||||
---------------------------------------------------------------------------------- | ||||
LIBRARY IEEE; | ||||
USE IEEE.STD_LOGIC_1164.ALL; | ||||
USE IEEE.NUMERIC_STD.ALL; | ||||
LIBRARY grlib; | ||||
USE grlib.amba.ALL; | ||||
USE grlib.stdlib.ALL; | ||||
USE grlib.devices.ALL; | ||||
LIBRARY lpp; | ||||
USE lpp.apb_devices_list.ALL; | ||||
USE lpp.general_purpose.ALL; | ||||
USE lpp.lpp_lfr_time_management.ALL; | ||||
pellion
|
r458 | USE lpp.lpp_lfr_time_management_apbreg_pkg.ALL; | ||
pellion
|
r293 | |||
ENTITY apb_lfr_time_management IS | ||||
GENERIC( | ||||
pellion
|
r329 | pindex : INTEGER := 0; --! APB slave index | ||
paddr : INTEGER := 0; --! ADDR field of the APB BAR | ||||
pmask : INTEGER := 16#fff#; --! MASK field of the APB BAR | ||||
FIRST_DIVISION : INTEGER := 374; | ||||
NB_SECOND_DESYNC : INTEGER := 60 | ||||
pellion
|
r293 | ); | ||
PORT ( | ||||
clk25MHz : IN STD_LOGIC; --! Clock | ||||
pellion
|
r329 | clk24_576MHz : IN STD_LOGIC; --! secondary clock | ||
pellion
|
r293 | resetn : IN STD_LOGIC; --! Reset | ||
pellion
|
r329 | grspw_tick : IN STD_LOGIC; --! grspw signal asserted when a valid time-code is received | ||
apbi : IN apb_slv_in_type; --! APB slave input signals | ||||
apbo : OUT apb_slv_out_type; --! APB slave output signals | ||||
pellion
|
r293 | coarse_time : OUT STD_LOGIC_VECTOR(31 DOWNTO 0); --! coarse time | ||
pellion
|
r453 | fine_time : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); --! fine TIME | ||
--------------------------------------------------------------------------- | ||||
LFR_soft_rstn : OUT STD_LOGIC | ||||
pellion
|
r293 | ); | ||
END apb_lfr_time_management; | ||||
ARCHITECTURE Behavioral OF apb_lfr_time_management IS | ||||
CONSTANT REVISION : INTEGER := 1; | ||||
CONSTANT pconfig : apb_config_type := ( | ||||
pellion
|
r329 | 0 => ahb_device_reg (VENDOR_LPP, 14, 0, REVISION, 0), | ||
pellion
|
r293 | 1 => apb_iobar(paddr, pmask) | ||
); | ||||
TYPE apb_lfr_time_management_Reg IS RECORD | ||||
pellion
|
r329 | ctrl : STD_LOGIC; | ||
pellion
|
r336 | soft_reset : STD_LOGIC; | ||
coarse_time_load : STD_LOGIC_VECTOR(30 DOWNTO 0); | ||||
pellion
|
r293 | coarse_time : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||
fine_time : STD_LOGIC_VECTOR(15 DOWNTO 0); | ||||
pellion
|
r453 | LFR_soft_reset : STD_LOGIC; | ||
pellion
|
r293 | END RECORD; | ||
SIGNAL r : apb_lfr_time_management_Reg; | ||||
pellion
|
r329 | |||
pellion
|
r293 | SIGNAL Rdata : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||
SIGNAL force_tick : STD_LOGIC; | ||||
SIGNAL previous_force_tick : STD_LOGIC; | ||||
SIGNAL soft_tick : STD_LOGIC; | ||||
SIGNAL coarsetime_reg_updated : STD_LOGIC; | ||||
pellion
|
r336 | SIGNAL coarsetime_reg : STD_LOGIC_VECTOR(30 DOWNTO 0); | ||
pellion
|
r293 | |||
pellion
|
r329 | --SIGNAL coarse_time_new : STD_LOGIC; | ||
SIGNAL coarse_time_new_49 : STD_LOGIC; | ||||
SIGNAL coarse_time_49 : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
SIGNAL coarse_time_s : STD_LOGIC_VECTOR(31 DOWNTO 0); | ||||
--SIGNAL fine_time_new : STD_LOGIC; | ||||
--SIGNAL fine_time_new_temp : STD_LOGIC; | ||||
SIGNAL fine_time_new_49 : STD_LOGIC; | ||||
SIGNAL fine_time_49 : STD_LOGIC_VECTOR(15 DOWNTO 0); | ||||
SIGNAL fine_time_s : STD_LOGIC_VECTOR(15 DOWNTO 0); | ||||
SIGNAL tick : STD_LOGIC; | ||||
SIGNAL new_timecode : STD_LOGIC; | ||||
SIGNAL new_coarsetime : STD_LOGIC; | ||||
pellion
|
r293 | |||
pellion
|
r329 | SIGNAL time_new_49 : STD_LOGIC; | ||
SIGNAL time_new : STD_LOGIC; | ||||
pellion
|
r336 | |||
----------------------------------------------------------------------------- | ||||
SIGNAL force_reset : STD_LOGIC; | ||||
SIGNAL previous_force_reset : STD_LOGIC; | ||||
SIGNAL soft_reset : STD_LOGIC; | ||||
SIGNAL soft_reset_sync : STD_LOGIC; | ||||
----------------------------------------------------------------------------- | ||||
SIGNAL rstn_LFR_TM : STD_LOGIC; | ||||
pellion
|
r293 | |||
BEGIN | ||||
pellion
|
r453 | LFR_soft_rstn <= NOT r.LFR_soft_reset; | ||
pellion
|
r293 | PROCESS(resetn, clk25MHz) | ||
BEGIN | ||||
IF resetn = '0' THEN | ||||
Rdata <= (OTHERS => '0'); | ||||
pellion
|
r336 | r.coarse_time_load <= (OTHERS => '0'); | ||
r.soft_reset <= '0'; | ||||
pellion
|
r329 | r.ctrl <= '0'; | ||
pellion
|
r453 | r.LFR_soft_reset <= '1'; | ||
pellion
|
r293 | force_tick <= '0'; | ||
previous_force_tick <= '0'; | ||||
soft_tick <= '0'; | ||||
coarsetime_reg_updated <= '0'; | ||||
ELSIF clk25MHz'EVENT AND clk25MHz = '1' THEN | ||||
coarsetime_reg_updated <= '0'; | ||||
pellion
|
r329 | force_tick <= r.ctrl; | ||
pellion
|
r293 | previous_force_tick <= force_tick; | ||
IF (previous_force_tick = '0') AND (force_tick = '1') THEN | ||||
soft_tick <= '1'; | ||||
ELSE | ||||
soft_tick <= '0'; | ||||
END IF; | ||||
pellion
|
r336 | |||
force_reset <= r.soft_reset; | ||||
previous_force_reset <= force_reset; | ||||
IF (previous_force_reset = '0') AND (force_reset = '1') THEN | ||||
soft_reset <= '1'; | ||||
ELSE | ||||
soft_reset <= '0'; | ||||
END IF; | ||||
pellion
|
r293 | |||
--APB Write OP | ||||
IF (apbi.psel(pindex) AND apbi.penable AND apbi.pwrite) = '1' THEN | ||||
CASE apbi.paddr(7 DOWNTO 2) IS | ||||
pellion
|
r458 | WHEN ADDR_LFR_TM_CONTROL => | ||
pellion
|
r453 | r.ctrl <= apbi.pwdata(0); | ||
r.soft_reset <= apbi.pwdata(1); | ||||
r.LFR_soft_reset <= apbi.pwdata(2); | ||||
pellion
|
r458 | WHEN ADDR_LFR_TM_TIME_LOAD => | ||
pellion
|
r336 | r.coarse_time_load <= apbi.pwdata(30 DOWNTO 0); | ||
pellion
|
r293 | coarsetime_reg_updated <= '1'; | ||
WHEN OTHERS => | ||||
pellion
|
r332 | NULL; | ||
pellion
|
r293 | END CASE; | ||
pellion
|
r336 | ELSE | ||
IF r.ctrl = '1' THEN | ||||
r.ctrl <= '0'; | ||||
END if; | ||||
IF r.soft_reset = '1' THEN | ||||
r.soft_reset <= '0'; | ||||
END if; | ||||
pellion
|
r293 | END IF; | ||
--APB READ OP | ||||
IF (apbi.psel(pindex) AND (NOT apbi.pwrite)) = '1' THEN | ||||
CASE apbi.paddr(7 DOWNTO 2) IS | ||||
pellion
|
r458 | WHEN ADDR_LFR_TM_CONTROL => | ||
pellion
|
r332 | Rdata(0) <= r.ctrl; | ||
pellion
|
r336 | Rdata(1) <= r.soft_reset; | ||
pellion
|
r453 | Rdata(2) <= r.LFR_soft_reset; | ||
Rdata(31 DOWNTO 3) <= (others => '0'); | ||||
pellion
|
r458 | WHEN ADDR_LFR_TM_TIME_LOAD => | ||
pellion
|
r336 | Rdata(30 DOWNTO 0) <= r.coarse_time_load(30 DOWNTO 0); | ||
pellion
|
r458 | WHEN ADDR_LFR_TM_TIME_COARSE => | ||
pellion
|
r332 | Rdata(31 DOWNTO 0) <= r.coarse_time(31 DOWNTO 0); | ||
pellion
|
r458 | WHEN ADDR_LFR_TM_TIME_FINE => | ||
pellion
|
r293 | Rdata(31 DOWNTO 16) <= (OTHERS => '0'); | ||
pellion
|
r329 | Rdata(15 DOWNTO 0) <= r.fine_time(15 DOWNTO 0); | ||
pellion
|
r293 | WHEN OTHERS => | ||
pellion
|
r332 | Rdata(31 DOWNTO 0) <= (others => '0'); | ||
pellion
|
r293 | END CASE; | ||
END IF; | ||||
END IF; | ||||
END PROCESS; | ||||
pellion
|
r458 | apbo.pirq <= (OTHERS => '0'); | ||
pellion
|
r329 | apbo.prdata <= Rdata; | ||
pellion
|
r293 | apbo.pconfig <= pconfig; | ||
apbo.pindex <= pindex; | ||||
pellion
|
r329 | |||
----------------------------------------------------------------------------- | ||||
-- IN | ||||
coarse_time <= r.coarse_time; | ||||
fine_time <= r.fine_time; | ||||
coarsetime_reg <= r.coarse_time_load; | ||||
pellion
|
r293 | ----------------------------------------------------------------------------- | ||
pellion
|
r329 | ----------------------------------------------------------------------------- | ||
-- OUT | ||||
pellion
|
r293 | r.coarse_time <= coarse_time_s; | ||
r.fine_time <= fine_time_s; | ||||
----------------------------------------------------------------------------- | ||||
----------------------------------------------------------------------------- | ||||
tick <= grspw_tick OR soft_tick; | ||||
SYNC_VALID_BIT_1 : SYNC_VALID_BIT | ||||
GENERIC MAP ( | ||||
NB_FF_OF_SYNC => 2) | ||||
PORT MAP ( | ||||
clk_in => clk25MHz, | ||||
pellion
|
r329 | clk_out => clk24_576MHz, | ||
pellion
|
r293 | rstn => resetn, | ||
sin => tick, | ||||
sout => new_timecode); | ||||
SYNC_VALID_BIT_2 : SYNC_VALID_BIT | ||||
GENERIC MAP ( | ||||
NB_FF_OF_SYNC => 2) | ||||
PORT MAP ( | ||||
clk_in => clk25MHz, | ||||
pellion
|
r329 | clk_out => clk24_576MHz, | ||
pellion
|
r293 | rstn => resetn, | ||
sin => coarsetime_reg_updated, | ||||
sout => new_coarsetime); | ||||
pellion
|
r336 | |||
SYNC_VALID_BIT_3 : SYNC_VALID_BIT | ||||
GENERIC MAP ( | ||||
NB_FF_OF_SYNC => 2) | ||||
PORT MAP ( | ||||
clk_in => clk25MHz, | ||||
clk_out => clk24_576MHz, | ||||
rstn => resetn, | ||||
sin => soft_reset, | ||||
sout => soft_reset_sync); | ||||
pellion
|
r293 | |||
pellion
|
r329 | ----------------------------------------------------------------------------- | ||
--SYNC_FF_1 : SYNC_FF | ||||
pellion
|
r293 | -- GENERIC MAP ( | ||
-- NB_FF_OF_SYNC => 2) | ||||
-- PORT MAP ( | ||||
pellion
|
r329 | -- clk => clk25MHz, | ||
-- rstn => resetn, | ||||
-- A => fine_time_new_49, | ||||
-- A_sync => fine_time_new_temp); | ||||
--lpp_front_detection_1 : lpp_front_detection | ||||
-- PORT MAP ( | ||||
-- clk => clk25MHz, | ||||
-- rstn => resetn, | ||||
-- sin => fine_time_new_temp, | ||||
-- sout => fine_time_new); | ||||
--SYNC_VALID_BIT_4 : SYNC_VALID_BIT | ||||
-- GENERIC MAP ( | ||||
-- NB_FF_OF_SYNC => 2) | ||||
-- PORT MAP ( | ||||
-- clk_in => clk24_576MHz, | ||||
pellion
|
r293 | -- clk_out => clk25MHz, | ||
-- rstn => resetn, | ||||
pellion
|
r329 | -- sin => coarse_time_new_49, | ||
-- sout => coarse_time_new); | ||||
pellion
|
r293 | |||
pellion
|
r329 | time_new_49 <= coarse_time_new_49 OR fine_time_new_49; | ||
pellion
|
r293 | |||
SYNC_VALID_BIT_4 : SYNC_VALID_BIT | ||||
pellion
|
r329 | GENERIC MAP ( | ||
NB_FF_OF_SYNC => 2) | ||||
PORT MAP ( | ||||
clk_in => clk24_576MHz, | ||||
clk_out => clk25MHz, | ||||
rstn => resetn, | ||||
sin => time_new_49, | ||||
sout => time_new); | ||||
pellion
|
r293 | |||
pellion
|
r329 | |||
pellion
|
r293 | PROCESS (clk25MHz, resetn) | ||
BEGIN -- PROCESS | ||||
IF resetn = '0' THEN -- asynchronous reset (active low) | ||||
fine_time_s <= (OTHERS => '0'); | ||||
coarse_time_s <= (OTHERS => '0'); | ||||
ELSIF clk25MHz'EVENT AND clk25MHz = '1' THEN -- rising clock edge | ||||
pellion
|
r329 | IF time_new = '1' THEN | ||
fine_time_s <= fine_time_49; | ||||
pellion
|
r293 | coarse_time_s <= coarse_time_49; | ||
END IF; | ||||
END IF; | ||||
END PROCESS; | ||||
pellion
|
r336 | |||
rstn_LFR_TM <= '0' WHEN resetn = '0' ELSE | ||||
'0' WHEN soft_reset_sync = '1' ELSE | ||||
'1'; | ||||
pellion
|
r293 | ----------------------------------------------------------------------------- | ||
-- LFR_TIME_MANAGMENT | ||||
----------------------------------------------------------------------------- | ||||
lfr_time_management_1 : lfr_time_management | ||||
GENERIC MAP ( | ||||
pellion
|
r329 | FIRST_DIVISION => FIRST_DIVISION, | ||
NB_SECOND_DESYNC => NB_SECOND_DESYNC) | ||||
pellion
|
r293 | PORT MAP ( | ||
pellion
|
r329 | clk => clk24_576MHz, | ||
pellion
|
r336 | rstn => rstn_LFR_TM, | ||
pellion
|
r293 | |||
pellion
|
r329 | tick => new_timecode, | ||
pellion
|
r293 | new_coarsetime => new_coarsetime, | ||
pellion
|
r336 | coarsetime_reg => coarsetime_reg(30 DOWNTO 0), | ||
pellion
|
r293 | |||
fine_time => fine_time_49, | ||||
fine_time_new => fine_time_new_49, | ||||
coarse_time => coarse_time_49, | ||||
coarse_time_new => coarse_time_new_49); | ||||
pellion
|
r334 | END Behavioral; | ||