diff --git a/modules/Manifest.py b/modules/Manifest.py index 368277410609e7d7727747773a35f3385381dbea..f1a3ef004bc7fb932313ea41f7b25bc8189c5b17 100644 --- a/modules/Manifest.py +++ b/modules/Manifest.py @@ -16,5 +16,6 @@ modules = { "wr_streamers", "wr_nic", "wr_txtsu", + "wr_irig", ] } diff --git a/modules/wr_irig/Manifest.py b/modules/wr_irig/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..38e6d03089f25878fc8989a35bee193309a178c9 --- /dev/null +++ b/modules/wr_irig/Manifest.py @@ -0,0 +1 @@ +files = ["wr_irig_slave.vhd", "xwr_irig_slave.vhd", "irig_slave_regs.vhd"] diff --git a/modules/wr_irig/generate_cheby_files.sh b/modules/wr_irig/generate_cheby_files.sh new file mode 100755 index 0000000000000000000000000000000000000000..a17adf479aae01db445a14724962a4140b4bb8fc --- /dev/null +++ b/modules/wr_irig/generate_cheby_files.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +cheby -i irig_slave_regs.cheby --gen-hdl irig_slave_regs.vhd +cheby -i irig_slave_regs.cheby --gen-c irig_slave_regs.h \ No newline at end of file diff --git a/modules/wr_irig/irig_slave_regs.cheby b/modules/wr_irig/irig_slave_regs.cheby new file mode 100644 index 0000000000000000000000000000000000000000..79e5be0c0f525e542ecafcfc2bdf505e3b972c81 --- /dev/null +++ b/modules/wr_irig/irig_slave_regs.cheby @@ -0,0 +1,130 @@ +##############################################################################; +## Title : IRIG-B Register Block (slave) +## Project : White Rabbit Switch +##############################################################################; +## File : irig_slave_regs.cheby +## Author : Harvey Leicester +## Company : CERN BE-CEM-EDL +## Created : 2024-10-17 +## Last update: 2024-10-17 +############################################################################## +## Description: register interface for irig slave +############################################################################## +## +## Copyright (c) 2024 CERN / BE-CEM-EDL +## +## This source file is free software; you can redistribute it +## and/or modify it under the terms of the GNU Lesser General +## Public License as published by the Free Software Foundation; +## either version 2.1 of the License, or (at your option) any +## later version. +## +## This source is distributed in the hope that it will be +## useful, but WITHOUT ANY WARRANTY; without even the implied +## warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +## PURPOSE. See the GNU Lesser General Public License for more +## details. +## +## You should have received a copy of the GNU Lesser General +## Public License along with this source; if not, download it +## from http://www.gnu.org/licenses/lgpl-2.1l.html +## +##############################################################################- + +memory-map: + name: irig_slave + description: IRIG-B slave register block + bus: wb-32-be + x-hdl: + iogroup: irig_regs + name-suffix: _regs + schema-version: + core: 2.0.0 + x-conversions: 1.0.0 + x-hdl: 1.0.0 + x-map-info: 1.0.0 + x-wbgen: 1.0.0 + children: + - reg: + name: CR + description: Control Register + width: 32 + access: rw + address: 0x0 + children: + - field: + name: enable + description: enable flag + range: 0 + - reg: + name: TOD + description: Time of day hr:min:sec + width: 32 + access: ro + children: + - field: + name: seconds + description: seconds from irig frame + range: 7-0 + - field: + name: minutes + description: minutes from irig frame + range: 16-8 + - field: + name: hours + description: hours from irig frame + range: 28-20 + - field: + name: valid + description: valid flag + range: 31 + - reg: + name: DATE + description: Date, Years / Days + width: 32 + access: ro + children: + - field: + name: days + description: days from irig frame + range: 10-0 + - field: + name: years + description: years from irig frame + range: 24-16 + - field: + name: valid + description: valid flag + range: 31 + - reg: + name: CTRL + description: Control functions 0 & 1 + width: 32 + access: ro + children: + - field: + name: fcn0 + description: control function 0 + range: 8-0 + - field: + name: fcn1 + description: control function 1 + range: 24-16 + - field: + name: valid + description: valid flag + range: 31 + - reg: + name: SBS + description: Straight Binary Seconds + width: 32 + access: ro + children: + - field: + name: sbs + description: sbs from irig frame + range: 17-0 + - field: + name: valid + description: valid flag + range: 31 \ No newline at end of file diff --git a/modules/wr_irig/irig_slave_regs.vhd b/modules/wr_irig/irig_slave_regs.vhd new file mode 100644 index 0000000000000000000000000000000000000000..877bb9ad7117d49249f832f591e8cdbc1abc46ea --- /dev/null +++ b/modules/wr_irig/irig_slave_regs.vhd @@ -0,0 +1,228 @@ +-- Do not edit. Generated by cheby 1.6.dev0 using these options: +-- -i irig_slave_regs.cheby --gen-hdl irig_slave_regs.vhd +-- Generated on Thu Oct 24 14:19:28 2024 by harvey + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package irig_slave_regs_pkg is + type t_irig_regs_master_out is record + CR_enable : std_logic; + end record t_irig_regs_master_out; + subtype t_irig_regs_slave_in is t_irig_regs_master_out; + + type t_irig_regs_slave_out is record + TOD_seconds : std_logic_vector(7 downto 0); + TOD_minutes : std_logic_vector(8 downto 0); + TOD_hours : std_logic_vector(8 downto 0); + TOD_valid : std_logic; + DATE_days : std_logic_vector(10 downto 0); + DATE_years : std_logic_vector(8 downto 0); + DATE_valid : std_logic; + CTRL_fcn0 : std_logic_vector(8 downto 0); + CTRL_fcn1 : std_logic_vector(8 downto 0); + CTRL_valid : std_logic; + SBS_sbs : std_logic_vector(17 downto 0); + SBS_valid : std_logic; + end record t_irig_regs_slave_out; + subtype t_irig_regs_master_in is t_irig_regs_slave_out; + +end irig_slave_regs_pkg; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.irig_slave_regs_pkg.all; + +entity irig_slave_regs is + port ( + rst_n_i : in std_logic; + clk_i : in std_logic; + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_adr_i : in std_logic_vector(4 downto 2); + wb_sel_i : in std_logic_vector(3 downto 0); + wb_we_i : in std_logic; + wb_dat_i : in std_logic_vector(31 downto 0); + wb_ack_o : out std_logic; + wb_err_o : out std_logic; + wb_rty_o : out std_logic; + wb_stall_o : out std_logic; + wb_dat_o : out std_logic_vector(31 downto 0); + -- Wires and registers + irig_regs_i : in t_irig_regs_master_in; + irig_regs_o : out t_irig_regs_master_out + ); +end irig_slave_regs; + +architecture syn of irig_slave_regs is + signal rd_req_int : std_logic; + signal wr_req_int : std_logic; + signal rd_ack_int : std_logic; + signal wr_ack_int : std_logic; + signal wb_en : std_logic; + signal ack_int : std_logic; + signal wb_rip : std_logic; + signal wb_wip : std_logic; + signal CR_enable_reg : std_logic; + signal CR_wreq : std_logic; + signal CR_wack : std_logic; + signal rd_ack_d0 : std_logic; + signal rd_dat_d0 : std_logic_vector(31 downto 0); + signal wr_req_d0 : std_logic; + signal wr_adr_d0 : std_logic_vector(4 downto 2); + signal wr_dat_d0 : std_logic_vector(31 downto 0); +begin + + -- WB decode signals + wb_en <= wb_cyc_i and wb_stb_i; + + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + wb_rip <= '0'; + else + wb_rip <= (wb_rip or (wb_en and not wb_we_i)) and not rd_ack_int; + end if; + end if; + end process; + rd_req_int <= (wb_en and not wb_we_i) and not wb_rip; + + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + wb_wip <= '0'; + else + wb_wip <= (wb_wip or (wb_en and wb_we_i)) and not wr_ack_int; + end if; + end if; + end process; + wr_req_int <= (wb_en and wb_we_i) and not wb_wip; + + ack_int <= rd_ack_int or wr_ack_int; + wb_ack_o <= ack_int; + wb_stall_o <= not ack_int and wb_en; + wb_rty_o <= '0'; + wb_err_o <= '0'; + + -- pipelining for wr-in+rd-out + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + rd_ack_int <= '0'; + wb_dat_o <= "00000000000000000000000000000000"; + wr_req_d0 <= '0'; + wr_adr_d0 <= "000"; + wr_dat_d0 <= "00000000000000000000000000000000"; + else + rd_ack_int <= rd_ack_d0; + wb_dat_o <= rd_dat_d0; + wr_req_d0 <= wr_req_int; + wr_adr_d0 <= wb_adr_i; + wr_dat_d0 <= wb_dat_i; + end if; + end if; + end process; + + -- Register CR + irig_regs_o.CR_enable <= CR_enable_reg; + process (clk_i) begin + if rising_edge(clk_i) then + if rst_n_i = '0' then + CR_enable_reg <= '0'; + CR_wack <= '0'; + else + if CR_wreq = '1' then + CR_enable_reg <= wr_dat_d0(0); + end if; + CR_wack <= CR_wreq; + end if; + end if; + end process; + + -- Register TOD + + -- Register DATE + + -- Register CTRL + + -- Register SBS + + -- Process for write requests. + process (wr_adr_d0, wr_req_d0, CR_wack) begin + CR_wreq <= '0'; + case wr_adr_d0(4 downto 2) is + when "000" => + -- Reg CR + CR_wreq <= wr_req_d0; + wr_ack_int <= CR_wack; + when "001" => + -- Reg TOD + wr_ack_int <= wr_req_d0; + when "010" => + -- Reg DATE + wr_ack_int <= wr_req_d0; + when "011" => + -- Reg CTRL + wr_ack_int <= wr_req_d0; + when "100" => + -- Reg SBS + wr_ack_int <= wr_req_d0; + when others => + wr_ack_int <= wr_req_d0; + end case; + end process; + + -- Process for read requests. + process (wb_adr_i, rd_req_int, CR_enable_reg, irig_regs_i.TOD_seconds, + irig_regs_i.TOD_minutes, irig_regs_i.TOD_hours, + irig_regs_i.TOD_valid, irig_regs_i.DATE_days, + irig_regs_i.DATE_years, irig_regs_i.DATE_valid, + irig_regs_i.CTRL_fcn0, irig_regs_i.CTRL_fcn1, + irig_regs_i.CTRL_valid, irig_regs_i.SBS_sbs, irig_regs_i.SBS_valid) begin + -- By default ack read requests + rd_dat_d0 <= (others => 'X'); + case wb_adr_i(4 downto 2) is + when "000" => + -- Reg CR + rd_ack_d0 <= rd_req_int; + rd_dat_d0(0) <= CR_enable_reg; + rd_dat_d0(31 downto 1) <= (others => '0'); + when "001" => + -- Reg TOD + rd_ack_d0 <= rd_req_int; + rd_dat_d0(7 downto 0) <= irig_regs_i.TOD_seconds; + rd_dat_d0(16 downto 8) <= irig_regs_i.TOD_minutes; + rd_dat_d0(19 downto 17) <= (others => '0'); + rd_dat_d0(28 downto 20) <= irig_regs_i.TOD_hours; + rd_dat_d0(30 downto 29) <= (others => '0'); + rd_dat_d0(31) <= irig_regs_i.TOD_valid; + when "010" => + -- Reg DATE + rd_ack_d0 <= rd_req_int; + rd_dat_d0(10 downto 0) <= irig_regs_i.DATE_days; + rd_dat_d0(15 downto 11) <= (others => '0'); + rd_dat_d0(24 downto 16) <= irig_regs_i.DATE_years; + rd_dat_d0(30 downto 25) <= (others => '0'); + rd_dat_d0(31) <= irig_regs_i.DATE_valid; + when "011" => + -- Reg CTRL + rd_ack_d0 <= rd_req_int; + rd_dat_d0(8 downto 0) <= irig_regs_i.CTRL_fcn0; + rd_dat_d0(15 downto 9) <= (others => '0'); + rd_dat_d0(24 downto 16) <= irig_regs_i.CTRL_fcn1; + rd_dat_d0(30 downto 25) <= (others => '0'); + rd_dat_d0(31) <= irig_regs_i.CTRL_valid; + when "100" => + -- Reg SBS + rd_ack_d0 <= rd_req_int; + rd_dat_d0(17 downto 0) <= irig_regs_i.SBS_sbs; + rd_dat_d0(30 downto 18) <= (others => '0'); + rd_dat_d0(31) <= irig_regs_i.SBS_valid; + when others => + rd_ack_d0 <= rd_req_int; + end case; + end process; +end syn; diff --git a/modules/wr_irig/wr_irig_slave.vhd b/modules/wr_irig/wr_irig_slave.vhd new file mode 100644 index 0000000000000000000000000000000000000000..97fba7dc020881b6adb817fad97439f9719abbc9 --- /dev/null +++ b/modules/wr_irig/wr_irig_slave.vhd @@ -0,0 +1,358 @@ +------------------------------------------------------------------------------- +-- Title : WR Switch IRIG slave module +-- Project : White Rabbit Switch +------------------------------------------------------------------------------- +-- File : wr_irig_slave.vhd +-- Author : Harvey Leicester +-- Company : CERN BE-CEM-EDL +-- Created : 2024-10-23 +-- Last update: 2024-10-23 +-- Platform : FPGA-generic +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- IRIG-B004 slave interface +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 - 2024 CERN / BE-CEM-EDL +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.gencores_pkg.all; + +entity wr_irig_slave is + generic ( + g_clks_per_ms : integer := 62500 + ); + port ( + clk_sys_i : in std_logic; --sys / sampling clock + rst_sys_n_i : in std_logic; --sys rst + irig_i : in std_logic; --irig data in + + secs_o : out std_logic_vector(7 downto 0); --seconds + mins_o : out std_logic_vector(8 downto 0); --minutes + hrs_o : out std_logic_vector(8 downto 0); --hours + days_o : out std_logic_vector(10 downto 0); --day of year + year_o : out std_logic_vector(8 downto 0); --year + ctrl0_o : out std_logic_vector(8 downto 0); --control function 0 + ctrl1_o : out std_logic_vector(8 downto 0); --contorl function 1 + sbs_o : out std_logic_vector(17 downto 0); --straight binary seconds + valid_o : out std_logic; --output valid + pps_o : out std_logic --pps out, generated from start of irig frame + ); +end entity wr_irig_slave; + +architecture rtl of wr_irig_slave is + + constant c_MARKER_MS : integer := 8; + constant c_HIGH_MS : integer := 5; + constant c_LOW_MS : integer := 2; + constant c_NUM_FIELDS : integer := 10; + constant c_TICK_CNT_SOF : integer := 10; + constant c_TICK_CNT_FRAME : integer := 1000; + constant c_TICK_CNT_PREF : integer := 991; + + type t_irig_frame_state is + ( + S_IDLE, + S_PARSE8B, + S_WAITMARKER, + S_PARSE9B + ); + + type t_irig_smpl_state is + ( + S_IDLE, + S_SMPL + ); + + type t_frame_sof_state is + ( + S_IDLE, + S_CHECKSOF + ); + + signal irig_frame_state : t_irig_frame_state := S_IDLE; + signal irig_smpl_state : t_irig_smpl_state := S_IDLE; + signal frame_sof_state : t_frame_sof_state := S_IDLE; + + type t_field_array is array (0 to c_NUM_FIELDS-1) of std_logic_vector(8 downto 0); + + signal field : t_field_array; + signal d_synced, d_rising, d_falling : std_logic; + signal sreg : std_logic_vector(8 downto 0); + signal high_cnt, field_cnt : unsigned(3 downto 0); + signal tick : std_logic; + signal clk_cnt : unsigned(15 downto 0); + signal count_ms : unsigned(3 downto 0); + signal bit_count : unsigned(3 downto 0); + signal tick_cnt : unsigned(9 downto 0); + + signal sof, synced : std_logic; + signal marker, irig_data : std_logic; + signal d_valid, field_valid, smpl_err : std_logic; + signal secs : std_logic_vector(7 downto 0); + signal mins, hrs, days0, days1, yrs, ctrl0, ctrl1, sbs0, sbs1 : std_logic_vector(8 downto 0); + +begin + + U_sync_data: gc_sync_ffs + port map + ( + clk_i => clk_sys_i, + rst_n_i => '1', + data_i => irig_i, + synced_o => d_synced, + npulse_o => d_falling, + ppulse_o => d_rising + ); + + p_tick_gen: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if (rst_sys_n_i = '0' or d_rising = '1') then + clk_cnt <= to_unsigned(g_clks_per_ms/2, clk_cnt'length); + else + clk_cnt <= clk_cnt+1; + if(clk_cnt >=(g_clks_per_ms)-1) then + clk_cnt <= (others => '0'); + end if; + end if; + end if; + end process; + + --sample tick + tick <= '1' when (clk_cnt = g_clks_per_ms-1) else '0'; + + p_smpl_sm: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if (rst_sys_n_i = '0') then + irig_smpl_state <= S_IDLE; + else + + irig_data <= '0'; + d_valid <= '0'; + marker <= '0'; + smpl_err <= '0'; + + case irig_smpl_state is + + when S_IDLE => high_cnt <= (others => '0'); + if(tick = '1') then + if(d_synced = '1') then + high_cnt <= high_cnt+1; + irig_smpl_state <= S_SMPL; + end if; + end if; + + when S_SMPL => if(tick = '1') then + if(d_synced = '1') then + high_cnt <= high_cnt+1; + else + irig_smpl_state <= S_IDLE; + if(high_cnt = c_HIGH_MS) then + irig_data <= '1'; + d_valid <= '1'; + elsif(high_cnt = c_LOW_MS) then + irig_data <= '0'; + d_valid <= '1'; + elsif(high_cnt = c_MARKER_MS) then + marker <= '1'; + else + smpl_err <= '1'; --something gone wrong + end if; + end if; + end if; + + when others => irig_smpl_state <= S_IDLE; + + end case; + end if; + end if; + end process; + + p_sof_detect: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if(rst_sys_n_i = '0') then + frame_sof_state <= S_IDLE; + else + + sof <= '0'; + + case frame_sof_state is + + when S_IDLE => if(marker = '1') then + frame_sof_state <= S_CHECKSOF; + end if; + + when S_CHECKSOF => if(d_valid = '1' or smpl_err = '1') then + frame_sof_state <= S_IDLE; + elsif(marker = '1') then --got 2 markers in a row + sof <= '1'; + frame_sof_state <= S_IDLE; + end if; + + when others => frame_sof_state <= S_IDLE; + + end case; + end if; + end if; + end process; + + --counter synced to sof + p_tick_cnt: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if (rst_sys_n_i = '0' or sof = '1') then + tick_cnt <= (others => '0'); + else + if(tick = '1') then + tick_cnt <= tick_cnt + 1; + end if; + end if; + end if; + end process; + + --check got sof when expected, used to generate valid and gate pps + p_sync_gen: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if(rst_sys_n_i = '0') then + synced <= '0'; + else + if (tick_cnt >= c_TICK_CNT_FRAME) then + synced <= '0'; + if(sof = '1') then + synced <= '1'; + end if; + end if; + end if; + end if; + end process; + + --parse the frame + p_frame_sm: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if(rst_sys_n_i = '0') then + field <= (others => (others => '0')); + irig_frame_state <= S_IDLE; + else + + field_valid <= '0'; + + case irig_frame_state is + + when S_IDLE => field_cnt <= (others => '0'); + if(sof = '1') then + irig_frame_state <= S_PARSE8B; --first field (seconds) is 8 bits, others are 9 + end if; + + when S_PARSE8B => if(tick = '1') then + if (bit_count >= 8) then + irig_frame_state <= S_WAITMARKER; + end if; + end if; + + when S_WAITMARKER => if(marker = '1') then + irig_frame_state <= S_PARSE9B; + field(to_integer(field_cnt)) <= sreg; + field_cnt <= field_cnt + 1; + if(field_cnt >= c_NUM_FIELDS-1) then + irig_frame_state <= S_IDLE; + field_valid <= '1'; + end if; + elsif(smpl_err = '1') then + irig_frame_state <= S_IDLE; + end if; + + when S_PARSE9B => if(tick = '1') then + if (bit_count >= 9) then + irig_frame_state <= S_WAITMARKER; + end if; + end if; + + when others => irig_frame_state <= S_IDLE; + + end case; + end if; + end if; + end process; + + --generate pps on first edge of p0 marker + pps_o <= d_rising when tick_cnt = c_TICK_CNT_PREF and synced = '1' else '0'; + + p_bit_count: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if(rst_sys_n_i='0' or marker='1') then + bit_count <= (others => '0'); + elsif (d_valid = '1') then + bit_count <= bit_count+1; + end if; + end if; + end process; + + p_shift_reg: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if (marker = '1') then + sreg <= (others => '0'); + elsif (d_valid = '1') then + sreg <= irig_data & sreg(sreg'length-1 downto 1); + end if; + end if; + end process; + + p_outputs: process(clk_sys_i) is + begin + if rising_edge(clk_sys_i) then + if(rst_sys_n_i = '0') then + secs_o <= (others => '0'); + mins_o <= (others => '0'); + hrs_o <= (others => '0'); + days_o <= (others => '0'); + year_o <= (others => '0'); + ctrl0_o <= (others => '0'); + ctrl1_o <= (others => '0'); + sbs_o <= (others => '0'); + else + if(field_valid = '1') then + secs_o <= field(0)(8 downto 1); + mins_o <= field(1); + hrs_o <= field(2); + days_o <= field(4)(1 downto 0) & field(3); + year_o <= field(5); + ctrl0_o <= field(6); + ctrl1_o <= field(7); + sbs_o <= field(9) & field(8); + end if; + end if; + end if; + end process; + + valid_o <= synced; + +end architecture; diff --git a/modules/wr_irig/xwr_irig_slave.vhd b/modules/wr_irig/xwr_irig_slave.vhd new file mode 100644 index 0000000000000000000000000000000000000000..45abc065873385ff01f9b147899f32ec2072f184 --- /dev/null +++ b/modules/wr_irig/xwr_irig_slave.vhd @@ -0,0 +1,186 @@ +------------------------------------------------------------------------------- +-- Title : WR Switch IRIG slave module +-- Project : White Rabbit Switch +------------------------------------------------------------------------------- +-- File : xwr_irig_slave.vhd +-- Author : Harvey Leicester +-- Company : CERN BE-CEM-EDL +-- Created : 2024-10-23 +-- Last update: 2024-10-23 +-- Platform : FPGA-generic +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- IRIG-B004 slave interface wrapper +------------------------------------------------------------------------------- +-- +-- Copyright (c) 2012 - 2024 CERN / BE-CEM-EDL +-- +-- This source file is free software; you can redistribute it +-- and/or modify it under the terms of the GNU Lesser General +-- Public License as published by the Free Software Foundation; +-- either version 2.1 of the License, or (at your option) any +-- later version. +-- +-- This source is distributed in the hope that it will be +-- useful, but WITHOUT ANY WARRANTY; without even the implied +-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +-- PURPOSE. See the GNU Lesser General Public License for more +-- details. +-- +-- You should have received a copy of the GNU Lesser General +-- Public License along with this source; if not, download it +-- from http://www.gnu.org/licenses/lgpl-2.1.html +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.wishbone_pkg.all; +use work.gencores_pkg.all; +use work.irig_slave_regs_pkg.all; + +entity xwr_irig_slave is + generic + ( + g_interface_mode : t_wishbone_interface_mode := PIPELINED; + g_address_granularity : t_wishbone_address_granularity := BYTE; + g_clks_per_ms : integer := 62500 + ); + port + ( + clk_i : in std_logic; + rst_n_i : in std_logic; + + irig_i : in std_logic; + pps_o : out std_logic; + enable_o : out std_logic; --enable flag out, used for muxing pps in top level + + wb_i : in t_wishbone_slave_in; + wb_o : out t_wishbone_slave_out + ); +end entity xwr_irig_slave; + +architecture wrapper of xwr_irig_slave is + + component wr_irig_slave + generic ( + g_clks_per_ms : integer := 62500 + ); + port ( + clk_sys_i : in std_logic; --sys clock + rst_sys_n_i : in std_logic; --sys rst + irig_i : in std_logic; --irig data in + + secs_o : out std_logic_vector(7 downto 0); --seconds out, 0-59 + mins_o : out std_logic_vector(8 downto 0); --minutes out, 0-59 + hrs_o : out std_logic_vector(8 downto 0); --hours out, 0-23 + days_o : out std_logic_vector(10 downto 0); --day of year, 1-366 + year_o : out std_logic_vector(8 downto 0); --year, 0-99 + ctrl0_o : out std_logic_vector(8 downto 0); --control function 0 + ctrl1_o : out std_logic_vector(8 downto 0); --contorl function 1 + sbs_o : out std_logic_vector(17 downto 0); --straight binary seconds + valid_o : out std_logic; --output valid + pps_o : out std_logic --pps out, generated from start of irig frame + ); + end component; + + signal wb_in : t_wishbone_slave_in; + signal wb_out : t_wishbone_slave_out; + signal irig_regs_in : t_irig_regs_master_in; + signal irig_regs_out : t_irig_regs_master_out; + + signal secs : std_logic_vector(7 downto 0); + signal mins : std_logic_vector(8 downto 0); + signal hrs : std_logic_vector(8 downto 0); + signal days : std_logic_vector(10 downto 0); + signal tos : std_logic_vector(3 downto 0); + signal yrs : std_logic_vector(8 downto 0); + signal ctrl0 : std_logic_vector(8 downto 0); + signal ctrl1 : std_logic_vector(8 downto 0); + signal sbs : std_logic_vector(17 downto 0); + signal valid : std_logic; + +begin + + U_Adapter : wb_slave_adapter + generic map + ( + g_master_use_struct => true, + g_master_mode => CLASSIC, + g_master_granularity => WORD, + g_slave_use_struct => true, + g_slave_mode => g_interface_mode, + g_slave_granularity => g_address_granularity + ) + port map + ( + clk_sys_i => clk_i, + rst_n_i => rst_n_i, + slave_i => wb_i, + slave_o => wb_o, + master_i => wb_out, + master_o => wb_in + ); + + U_irig_slave_regs: entity work.irig_slave_regs + port map + ( + rst_n_i => rst_n_i, + clk_i => clk_i, + wb_cyc_i => wb_in.cyc, + wb_stb_i => wb_in.stb, + wb_adr_i => wb_in.adr(2 downto 0), + wb_sel_i => wb_in.sel, + wb_we_i => wb_in.we, + wb_dat_i => wb_in.dat, + wb_ack_o => wb_out.ack, + wb_err_o => wb_out.err, + wb_rty_o => wb_out.rty, + wb_stall_o => wb_out.stall, + wb_dat_o => wb_out.dat, + irig_regs_i => irig_regs_in + ); + + U_irig_slave: wr_irig_slave + generic map + ( + g_clks_per_ms => g_clks_per_ms + ) + port map + ( + clk_sys_i => clk_i, + rst_sys_n_i => rst_n_i, + irig_i => irig_i, + + secs_o => secs, + mins_o => mins, + hrs_o => hrs, + days_o => days, + year_o => yrs, + ctrl0_o => ctrl0, + ctrl1_o => ctrl1, + sbs_o => sbs, + valid_o => valid, + pps_o => pps_o + ); + + irig_regs_in.TOD_seconds <= secs; + irig_regs_in.TOD_minutes <= mins; + irig_regs_in.TOD_hours <= hrs; + irig_regs_in.TOD_valid <= valid; + irig_regs_in.DATE_days <= days; + irig_regs_in.DATE_years <= yrs; + irig_regs_in.DATE_valid <= valid; + irig_regs_in.CTRL_fcn0 <= ctrl0; + irig_regs_in.CTRL_fcn1 <= ctrl1; + irig_regs_in.CTRL_valid <= valid; + irig_regs_in.SBS_sbs <= sbs; + irig_regs_in.SBS_valid <= valid; + + enable_o <= irig_regs_out.CR_enable; + +end architecture; +