From: Peter Lemmens
Date: Wed, 4 Sep 2013 06:22:58 +0000 (+0200)
Subject: Source files added for a complete (?) soda-chain comprised of source, hub and client
X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=bd985861647ea88636da74c3913faaae9dcc7bb8;p=soda.git
Source files added for a complete (?) soda-chain comprised of source, hub and client
Source is tested in test-benches (functional tests)
---
diff --git a/source/TB_soda_chain.vhd b/source/TB_soda_chain.vhd
new file mode 100644
index 0000000..8190462
--- /dev/null
+++ b/source/TB_soda_chain.vhd
@@ -0,0 +1,203 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+-- use work.trb_net_std.all;
+-- use work.trb_net_components.all;
+-- use work.trb_net16_hub_func.all;
+-- use work.trb3_components.all;
+-- use work.med_sync_define.all;
+-- use work.version.all;
+use work.soda_components.all;
+
+
+entity TB_soda_chain is
+end entity;
+
+architecture TestBench of TB_soda_chain is
+
+ -- Clock period definitions
+ constant clk_period: time:= 4ns;
+
+
+--Inputs
+ signal rst_S : std_logic;
+ signal clk_S : std_logic;
+ signal enable_S : std_logic := '0';
+ signal SOB_S : std_logic := '0';
+ signal src_dnstream_dlm_word_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal src_dnstream_dlm_valid_S : std_logic;
+ signal src_upstream_dlm_word_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal src_upstream_dlm_valid_S : std_logic;
+
+ signal hub_dnstream_dlm_word_S : t_HUB_DLM_WORD;
+ signal hub_dnstream_dlm_valid_S : t_HUB_DLM;
+ signal hub_upstream_dlm_word_S : t_HUB_DLM_WORD;
+ signal hub_upstream_dlm_valid_S : t_HUB_DLM;
+
+ --SODA
+ signal soda_ack : std_logic;
+ signal soda_write : std_logic := '0';
+ signal soda_read : std_logic := '0';
+ signal soda_data_in : std_logic_vector(31 downto 0) := (others => '0');
+ signal soda_src_data_out : std_logic_vector(31 downto 0);
+ signal soda_hub_data_out : std_logic_vector(31 downto 0);
+ signal soda_clt_data_out : std_logic_vector(31 downto 0);
+ signal soda_addr : std_logic_vector(3 downto 0) := (others => '0');
+ signal soda_leds : std_logic_vector(3 downto 0);
+begin
+
+ THE_SODA_SOURCE : soda_source
+ port map(
+ SYSCLK => clk_S,
+ RESET => rst_S,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ SODA_BURST_PULSE_IN => SOB_S,
+ RX_DLM_WORD_IN => src_upstream_dlm_word_S,
+ RX_DLM_IN => src_upstream_dlm_valid_S,
+ TX_DLM_OUT => src_dnstream_dlm_valid_S,
+ TX_DLM_WORD_OUT => src_dnstream_dlm_word_S,
+
+ SODA_DATA_IN => soda_data_in,
+ SODA_DATA_OUT => soda_src_data_out,
+ SODA_ADDR_IN => soda_addr,
+ SODA_READ_IN => soda_read,
+ SODA_WRITE_IN => soda_write,
+ SODA_ACK_OUT => soda_ack,
+ LEDS_OUT => soda_leds,
+ TEST_LINE => open,
+ STAT => open
+ );
+
+ A_SODA_HUB : soda_hub
+ port map(
+ SYSCLK => clk_S,
+ RESET => rst_S,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ RXTOP_DLM_WORD_IN => src_dnstream_dlm_word_S,
+ RXTOP_DLM_IN => src_dnstream_dlm_valid_S,
+ TXTOP_DLM_OUT => src_upstream_dlm_valid_S,
+ TXTOP_DLM_WORD_OUT => src_upstream_dlm_word_S,
+
+ RXBTM_DLM_WORD_IN => hub_upstream_dlm_word_S,
+ RXBTM_DLM_IN => hub_upstream_dlm_valid_S,
+ TXBTM_DLM_OUT => hub_dnstream_dlm_valid_S,
+ TXBTM_DLM_WORD_OUT => hub_dnstream_dlm_word_S,
+
+ SODA_DATA_IN => soda_data_in,
+ SODA_DATA_OUT => soda_hub_data_out,
+ SODA_ADDR_IN => soda_addr,
+ SODA_READ_IN => soda_read,
+ SODA_WRITE_IN => soda_write,
+ SODA_ACK_OUT => soda_ack,
+ STAT => open
+ );
+
+ channel : for i in c_HUB_CHILDREN-1 downto 0 generate
+
+ A_SODA_CLIENT : soda_client
+ port map(
+ SYSCLK => clk_S,
+ RESET => rst_S,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ RX_DLM_WORD_IN => hub_dnstream_dlm_word_S(i),
+ RX_DLM_IN => hub_dnstream_dlm_valid_S(i),
+ TX_DLM_OUT => hub_upstream_dlm_valid_S(i),
+ TX_DLM_WORD_OUT => hub_upstream_dlm_word_S(i),
+
+ SODA_DATA_IN => soda_data_in,
+ SODA_DATA_OUT => soda_clt_data_out,
+ SODA_ADDR_IN => soda_addr,
+ SODA_READ_IN => soda_read,
+ SODA_WRITE_IN => soda_write,
+ SODA_ACK_OUT => soda_ack,
+ STAT => open
+ );
+
+ end generate;
+
+
+------------------------------------------------------------------------------------------------------------
+ -- SODA command packet
+------------------------------------------------------------------------------------------------------------
+ cmd_proc :process
+ begin
+ wait for 2us;
+ soda_addr <= "0000";
+ soda_data_in <= x"08000000"; -- soda_reset
+ soda_write <= '1';
+ wait for clk_period;
+ soda_write <= '0';
+ wait for clk_period;
+ soda_addr <= "0000";
+ soda_data_in <= x"00000000"; -- soda_reset
+ soda_write <= '1';
+ wait for clk_period;
+ soda_write <= '0';
+------------------------------------------------------------------------------------------------------------
+ wait for 2us;
+ soda_addr <= "0100";
+ soda_data_in <= x"FFFFFFFD"; --
+ soda_write <= '1';
+ wait for clk_period;
+ soda_write <= '0';
+------------------------------------------------------------------------------------------------------------
+ wait for 700us;
+ soda_addr <= "0000";
+ soda_data_in <= x"40000000"; -- time_calibration
+ soda_write <= '1';
+ wait for clk_period;
+ soda_write <= '0';
+------------------------------------------------------------------------------------------------------------
+ wait for 700us;
+ soda_addr <= "0100";
+ soda_data_in <= x"FFFFFFFE"; -- time_calibration
+ soda_write <= '1';
+ wait for clk_period;
+ soda_write <= '0';
+------------------------------------------------------------------------------------------------------------
+ wait for 100us;
+ soda_addr <= "1001";
+ soda_read <= '1';
+ wait for clk_period;
+ soda_read <= '0';
+ end process;
+
+------------------------------------------------------------------------------------------------------------
+ -- Clock process definitions
+------------------------------------------------------------------------------------------------------------
+ clk_proc :process
+ begin
+ clk_S <= '0';
+ wait for clk_period/2;
+ clk_S <= '1';
+ wait for clk_period/2;
+ end process;
+
+ -- reset process
+ reset_proc: process
+ begin
+rst_S <= '1';
+wait for clk_period * 5;
+rst_S <= '0';
+wait;
+ end process;
+
+ burst_proc :process
+ begin
+SOB_S <= '0';
+wait for 2.35us;
+SOB_S <= '1';
+wait for 50ns;
+ end process;
+
+
+end TestBench;
+
diff --git a/source/TB_soda_source.vhd b/source/TB_soda_source.vhd
new file mode 100644
index 0000000..6b7c6dd
--- /dev/null
+++ b/source/TB_soda_source.vhd
@@ -0,0 +1,139 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+-- use work.trb_net_std.all;
+-- use work.trb_net_components.all;
+-- use work.trb_net16_hub_func.all;
+-- use work.trb3_components.all;
+-- use work.med_sync_define.all;
+-- use work.version.all;
+use work.soda_components.all;
+
+
+entity TB_soda_source_child is
+end entity;
+
+architecture TestBench of TB_soda_source_child is
+
+ -- Clock period definitions
+ constant clk_period: time:= 4ns;
+
+
+--Inputs
+ signal rst_S : std_logic;
+ signal clk_S : std_logic;
+ signal enable_S : std_logic := '0';
+ signal SOB_S : std_logic := '0';
+ signal src_dnstream_dlm_word_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal src_dnstream_dlm_valid_S : std_logic;
+ signal src_upstream_dlm_word_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal src_upstream_dlm_valid_S : std_logic;
+
+ --SODA
+ signal soda_ack : std_logic;
+ signal soda_write : std_logic := '0';
+ signal soda_read : std_logic := '0';
+ signal soda_data_in : std_logic_vector(31 downto 0) := (others => '0');
+ signal soda_data_out : std_logic_vector(31 downto 0);
+ signal soda_addr : std_logic_vector(3 downto 0) := (others => '0');
+ signal soda_leds : std_logic_vector(3 downto 0);
+begin
+
+ THE_SODA_SOURCE : soda_source
+ port map(
+ SYSCLK => clk_S,
+ RESET => rst_S,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ SODA_BURST_PULSE_IN => SOB_S,
+ RX_DLM_WORD_IN => src_upstream_dlm_word_S,
+ RX_DLM_IN => src_upstream_dlm_valid_S,
+ TX_DLM_OUT => src_dnstream_dlm_valid_S,
+ TX_DLM_WORD_OUT => src_dnstream_dlm_word_S,
+
+ SODA_DATA_IN => soda_data_in,
+ SODA_DATA_OUT => soda_data_out,
+ SODA_ADDR_IN => soda_addr,
+ SODA_READ_IN => soda_read,
+ SODA_WRITE_IN => soda_write,
+ SODA_ACK_OUT => soda_ack,
+ LEDS_OUT => soda_leds,
+ TEST_LINE => open,
+ STAT => open
+ );
+
+
+ A_SODA_CLIENT : soda_client
+ port map(
+ SYSCLK => clk_S,
+ RESET => rst_S,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ RX_DLM_WORD_IN => src_dnstream_dlm_word_S,
+ RX_DLM_IN => src_dnstream_dlm_valid_S,
+ TX_DLM_OUT => src_upstream_dlm_valid_S,
+ TX_DLM_WORD_OUT => src_upstream_dlm_word_S,
+
+ SODA_DATA_IN => soda_data_in,
+ SODA_DATA_OUT => soda_data_out,
+ SODA_ADDR_IN => soda_addr,
+ SODA_READ_IN => soda_read,
+ SODA_WRITE_IN => soda_write,
+ SODA_ACK_OUT => soda_ack,
+ STAT => open
+ );
+
+------------------------------------------------------------------------------------------------------------
+ -- SODA command packet
+------------------------------------------------------------------------------------------------------------
+ cmd_proc :process
+ begin
+wait for 2us;
+ soda_addr <= "0000";
+ soda_data_in <= x"08000000"; -- soda_reset
+ soda_write <= '1';
+wait for clk_period;
+ soda_write <= '0';
+wait for 700us;
+ soda_data_in <= x"40000000"; -- time_calibration
+ soda_write <= '1';
+wait for clk_period;
+ soda_write <= '0';
+
+ end process;
+
+------------------------------------------------------------------------------------------------------------
+ -- Clock process definitions
+------------------------------------------------------------------------------------------------------------
+clk_proc :process
+ begin
+ clk_S <= '0';
+ wait for clk_period/2;
+ clk_S <= '1';
+ wait for clk_period/2;
+ end process;
+
+-- reset process
+reset_proc: process
+ begin
+ rst_S <= '1';
+ wait for clk_period * 5;
+ rst_S <= '0';
+ wait;
+ end process;
+
+burst_proc :process
+ begin
+ SOB_S <= '0';
+ wait for 2.35us;
+ SOB_S <= '1';
+ wait for 50ns;
+ end process;
+
+
+end TestBench;
+
diff --git a/source/soda_calibration_timer.vhd b/source/soda_calibration_timer.vhd
new file mode 100644
index 0000000..658a53f
--- /dev/null
+++ b/source/soda_calibration_timer.vhd
@@ -0,0 +1,63 @@
+library ieee;
+use ieee.std_logic_1164.all;
+--use ieee.numeric_std.all;
+--use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net16_hub_func.all;
+use work.soda_components.all;
+
+entity soda_calibration_timer is
+ port(
+ SYSCLK : in std_logic; -- fabric clock
+ RESET : in std_logic; -- synchronous reset
+ CLEAR : in std_logic; -- asynchronous reset
+ CLK_EN : in std_logic;
+ --Internal Connection
+ START_CALIBRATION : in std_logic := '0';
+ END_CALIBRATION : in std_logic := '0';
+ CALIB_VALID_OUT : out std_logic := '0'; --
+ CALIB_TIME_OUT : out std_logic_vector(7 downto 0) := (others => '0')
+ );
+end soda_calibration_timer;
+
+architecture Behavioral of soda_calibration_timer is
+
+ signal calibration_running_S : std_logic := '0';
+ signal calibration_timer_S : std_logic_vector(7 downto 0) := (others => '0'); -- from super-burst-nr-generator
+
+begin
+
+ packet_fsm_proc : process(SYSCLK)--, RESET, packet_state_S, crc_valid_S, START_OF_SUPERBURST, soda_cmd_strobe_S)
+ begin
+ if rising_edge(SYSCLK) then
+ if (RESET='1') then
+ CALIB_VALID_OUT <= '0';
+ CALIB_TIME_OUT <= (others => '0');
+ calibration_running_S <= '0';
+ calibration_timer_S <= (others => '0');
+ else
+ if (START_CALIBRATION='1') then
+ calibration_running_S <= '1';
+ calibration_timer_S <= (others => '0');
+ CALIB_VALID_OUT <= '0';
+ CALIB_TIME_OUT <= (others => '0');
+ elsif (END_CALIBRATION='1') then
+ calibration_running_S <= '0';
+ CALIB_VALID_OUT <= '1';
+ CALIB_TIME_OUT <= calibration_timer_S;
+ elsif (calibration_timer_S= 255) then
+ calibration_running_S <= '0';
+ CALIB_VALID_OUT <= '1';
+ CALIB_TIME_OUT <= calibration_timer_S;
+ elsif (calibration_running_S='1') then
+ calibration_timer_S <= calibration_timer_S + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+end architecture;
\ No newline at end of file
diff --git a/source/soda_client.vhd b/source/soda_client.vhd
new file mode 100644
index 0000000..20c4762
--- /dev/null
+++ b/source/soda_client.vhd
@@ -0,0 +1,188 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net16_hub_func.all;
+use work.soda_components.all;
+
+entity soda_client is
+ port(
+ SYSCLK : in std_logic; -- fabric clock
+ RESET : in std_logic; -- synchronous reset
+ CLEAR : in std_logic; -- asynchronous reset
+ CLK_EN : in std_logic;
+
+ RX_DLM_WORD_IN : in std_logic_vector(7 downto 0) := (others => '0');
+ RX_DLM_IN : in std_logic;
+ TX_DLM_OUT : out std_logic;
+ TX_DLM_WORD_OUT : out std_logic_vector(7 downto 0) := (others => '0');
+
+ SODA_DATA_IN : in std_logic_vector(31 downto 0) := (others => '0');
+ SODA_DATA_OUT : out std_logic_vector(31 downto 0) := (others => '0');
+ SODA_ADDR_IN : in std_logic_vector(3 downto 0) := (others => '0');
+ SODA_READ_IN : in std_logic := '0';
+ SODA_WRITE_IN : in std_logic := '0';
+ SODA_ACK_OUT : out std_logic := '0';
+ STAT : out std_logic_vector(31 downto 0) := (others => '0') -- DEBUG
+ );
+end soda_client;
+
+architecture Behavioral of soda_client is
+
+ --SODA
+
+ signal enable_S : std_logic := '0';
+ signal soda_cmd_word_S : std_logic_vector(30 downto 0) := (others => '0');
+ signal soda_cmd_valid_S : std_logic := '0';
+ signal start_of_superburst_S : std_logic := '0';
+ signal super_burst_nr_S : std_logic_vector(30 downto 0) := (others => '0'); -- from super-burst-nr-generator
+ signal crc_data_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal crc_valid_S : std_logic := '0';
+
+-- Signals
+ type STATES is (SLEEP,RD_RDY,WR_RDY,RD_ACK,WR_ACK,DONE);
+ signal CURRENT_STATE, NEXT_STATE: STATES;
+
+ -- slave bus signals
+ signal bus_ack_x : std_logic;
+ signal bus_ack : std_logic;
+ signal store_wr_x : std_logic;
+ signal store_wr : std_logic;
+ signal store_rd_x : std_logic;
+ signal store_rd : std_logic;
+ signal buf_bus_data_out : std_logic_vector(31 downto 0);
+
+begin
+
+ packet_handler : soda_packet_handler
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ START_OF_SUPERBURST => start_of_superburst_S,
+ SUPER_BURST_NR => super_burst_nr_S,
+ SODA_CMD_VALID_S => soda_cmd_valid_S,
+ SODA_CMD_WORD_S => soda_cmd_word_S,
+ CRC_VALID_OUT => crc_valid_S,
+ CRC_DATA_OUT => crc_data_S,
+ RX_DLM_IN => RX_DLM_IN,
+ RX_DLM_WORD_IN => RX_DLM_WORD_IN
+ );
+
+ reply_packet_builder : soda_reply_pkt_builder
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => CLK_EN,
+ --Internal Connection
+ START_OF_SUPERBURST => start_of_superburst_S,
+ SUPER_BURST_NR_IN => super_burst_nr_S,
+ SODA_CMD_STROBE_IN => soda_cmd_valid_S,
+ SODA_CMD_WORD_IN => soda_cmd_word_S,
+ TX_DLM_OUT => TX_DLM_OUT,
+ TX_DLM_WORD_OUT => TX_DLM_WORD_OUT
+ );
+
+---------------------------------------------------------
+-- RegIO Statemachine
+---------------------------------------------------------
+ STATE_MEM: process( SYSCLK)
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if( RESET = '1' ) then
+ CURRENT_STATE <= SLEEP;
+ bus_ack <= '0';
+ store_wr <= '0';
+ store_rd <= '0';
+ else
+ CURRENT_STATE <= NEXT_STATE;
+ bus_ack <= bus_ack_x;
+ store_wr <= store_wr_x;
+ store_rd <= store_rd_x;
+ end if;
+ end if;
+ end process STATE_MEM;
+
+-- Transition matrix
+ TRANSFORM: process(CURRENT_STATE, SODA_READ_IN, SODA_WRITE_IN )
+ begin
+ NEXT_STATE <= SLEEP;
+ bus_ack_x <= '0';
+ store_wr_x <= '0';
+ store_rd_x <= '0';
+ case CURRENT_STATE is
+ when SLEEP =>
+ if ( (SODA_READ_IN = '1') ) then
+ NEXT_STATE <= RD_RDY;
+ store_rd_x <= '1';
+ elsif( (SODA_WRITE_IN = '1') ) then
+ NEXT_STATE <= WR_RDY;
+ store_wr_x <= '1';
+ else
+ NEXT_STATE <= SLEEP;
+ end if;
+ when RD_RDY =>
+ NEXT_STATE <= RD_ACK;
+ when WR_RDY =>
+ NEXT_STATE <= WR_ACK;
+ when RD_ACK =>
+ if( SODA_READ_IN = '0' ) then
+ NEXT_STATE <= DONE;
+ bus_ack_x <= '1';
+ else
+ NEXT_STATE <= RD_ACK;
+ bus_ack_x <= '1';
+ end if;
+ when WR_ACK =>
+ if( SODA_WRITE_IN = '0' ) then
+ NEXT_STATE <= DONE;
+ bus_ack_x <= '1';
+ else
+ NEXT_STATE <= WR_ACK;
+ bus_ack_x <= '1';
+ end if;
+ when DONE =>
+ NEXT_STATE <= SLEEP;
+ when others =>
+ NEXT_STATE <= SLEEP;
+ end case;
+end process TRANSFORM;
+
+
+---------------------------------------------------------
+-- data handling --
+---------------------------------------------------------
+-- For sim purposes the CLIENT gets addresses 11XX
+-- register write
+ THE_WRITE_REG_PROC: process( SYSCLK )
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if ( RESET = '1' ) then
+ elsif( (store_wr = '1') and (SODA_ADDR_IN = B"1100") ) then
+ end if;
+ end if;
+ end process THE_WRITE_REG_PROC;
+
+-- register read
+ THE_READ_REG_PROC: process( SYSCLK )
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if ( RESET = '1' ) then
+ buf_bus_data_out <= (others => '0');
+ elsif( (store_rd = '1') and (SODA_ADDR_IN = B"1100") ) then
+ buf_bus_data_out <= '0' & soda_cmd_word_S;
+ end if;
+ end if;
+ end process THE_READ_REG_PROC;
+
+-- output signals
+ SODA_DATA_OUT <= buf_bus_data_out;
+ SODA_ACK_OUT <= bus_ack;
+
+end architecture;
\ No newline at end of file
diff --git a/source/soda_hub.vhd b/source/soda_hub.vhd
new file mode 100644
index 0000000..d8b6a6d
--- /dev/null
+++ b/source/soda_hub.vhd
@@ -0,0 +1,325 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use ieee.std_logic_unsigned.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net16_hub_func.all;
+use work.soda_components.all;
+
+entity soda_hub is
+ port(
+ SYSCLK : in std_logic; -- fabric clock
+ RESET : in std_logic; -- synchronous reset
+ CLEAR : in std_logic; -- asynchronous reset
+ CLK_EN : in std_logic;
+ -- SINGLE DUBPLEX LINK TO THE TOP
+ RXTOP_DLM_IN : in std_logic;
+ RXTOP_DLM_WORD_IN : in std_logic_vector(7 downto 0) := (others => '0');
+ TXTOP_DLM_OUT : out std_logic;
+ TXTOP_DLM_WORD_OUT : out std_logic_vector(7 downto 0) := (others => '0');
+ -- MULTIPLE DUPLEX LINKS TO THE BOTTOM
+ RXBTM_DLM_IN : in t_HUB_DLM; -- typedef in soda_components.vhd
+ RXBTM_DLM_WORD_IN : in t_HUB_DLM_WORD; -- typedef in soda_components.vhd
+ TXBTM_DLM_OUT : out t_HUB_DLM; -- typedef in soda_components.vhd
+ TXBTM_DLM_WORD_OUT : out t_HUB_DLM_WORD; -- typedef in soda_components.vhd
+
+ SODA_DATA_IN : in std_logic_vector(31 downto 0) := (others => '0');
+ SODA_DATA_OUT : out std_logic_vector(31 downto 0) := (others => '0');
+ SODA_ADDR_IN : in std_logic_vector(3 downto 0) := (others => '0');
+ SODA_READ_IN : in std_logic := '0';
+ SODA_WRITE_IN : in std_logic := '0';
+ SODA_ACK_OUT : out std_logic := '0';
+ STAT : out std_logic_vector(31 downto 0) := (others => '0') -- DEBUG
+ );
+end soda_hub;
+
+architecture Behavioral of soda_hub is
+
+ --SODA
+ signal enable_S : std_logic := '0';
+ signal soda_cmd_word_S : std_logic_vector(30 downto 0) := (others => '0');
+ signal soda_cmd_valid_S : std_logic := '0';
+ signal start_of_superburst_S : std_logic := '0';
+ signal super_burst_nr_S : std_logic_vector(30 downto 0) := (others => '0'); -- from super-burst-nr-generator
+ signal crc_data_S : std_logic_vector(7 downto 0) := (others => '0');
+ signal crc_valid_S : std_logic := '0';
+
+-- Signals
+ type STATES is (SLEEP,RD_RDY,WR_RDY,RD_ACK,WR_ACK,DONE);
+ signal CURRENT_STATE, NEXT_STATE: STATES;
+
+ signal last_packet_sent_S : t_PACKET_TYPE_SENT;
+ signal expected_reply_S : std_logic_vector(7 downto 0);
+ signal reply_valid_S : t_HUB_BIT_ARRAY;
+ signal reply_OK_S : t_HUB_BIT_ARRAY;
+ signal start_calibration_S : std_logic;
+ signal calibration_valid_S : t_HUB_BIT_ARRAY;
+ signal calibration_time_S : t_HUB_BYTE_ARRAY;
+
+
+-- slave bus signals
+ signal bus_ack_x : std_logic;
+ signal bus_ack : std_logic;
+ signal store_wr_x : std_logic;
+ signal store_wr : std_logic;
+ signal store_rd_x : std_logic;
+ signal store_rd : std_logic;
+ signal buf_bus_data_out : std_logic_vector(31 downto 0);
+
+ signal dead_channels_S : std_logic_vector(31 downto 0) := (others => '0');
+ signal channel_status_S : std_logic_vector(31 downto 0) := (others => '0');
+ signal calib_register_S : t_HUB_WORD_ARRAY;
+
+ begin
+
+ hub_packet_handler : soda_packet_handler
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ START_OF_SUPERBURST => start_of_superburst_S,
+ SUPER_BURST_NR => super_burst_nr_S,
+ SODA_CMD_VALID_S => soda_cmd_valid_S,
+ SODA_CMD_WORD_S => soda_cmd_word_S,
+ EXPECTED_REPLY_OUT => expected_reply_S,
+ CRC_VALID_OUT => crc_valid_S,
+ CRC_DATA_OUT => crc_data_S,
+ RX_DLM_IN => RXTOP_DLM_IN,
+ RX_DLM_WORD_IN => RXTOP_DLM_WORD_IN
+ );
+
+ reply_packet_builder : soda_reply_pkt_builder
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => CLK_EN,
+ --Internal Connection
+ START_OF_SUPERBURST => start_of_superburst_S,
+ SUPER_BURST_NR_IN => super_burst_nr_S,
+ SODA_CMD_STROBE_IN => soda_cmd_valid_S,
+ SODA_CMD_WORD_IN => soda_cmd_word_S,
+ TX_DLM_OUT => TXTOP_DLM_OUT,
+ TX_DLM_WORD_OUT => TXTOP_DLM_WORD_OUT
+ );
+
+ channel :for i in c_HUB_CHILDREN-1 downto 0 generate
+
+ packet_builder : soda_packet_builder
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => CLK_EN,
+ --Internal Connection
+ SODA_CMD_STROBE_IN => soda_cmd_valid_S,
+ START_OF_SUPERBURST => start_of_superburst_S,
+ SUPER_BURST_NR_IN => super_burst_nr_S,
+ SODA_CMD_WORD_IN => soda_cmd_word_S,
+ EXPECTED_REPLY_OUT => open,
+ TIME_CAL_OUT => start_calibration_S,
+ TX_DLM_OUT => TXBTM_DLM_OUT(i),
+ TX_DLM_WORD_OUT => TXBTM_DLM_WORD_OUT(i)
+ );
+
+ hub_reply_handler : soda_reply_handler
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ LAST_PACKET => last_packet_sent_S,
+ EXPECTED_REPLY_IN => expected_reply_S,
+ RX_DLM_IN => RXBTM_DLM_IN(i),
+ RX_DLM_WORD_IN => RXBTM_DLM_WORD_IN(i),
+ REPLY_VALID_OUT => reply_valid_S(i),
+ REPLY_OK_OUT => reply_OK_S(i)
+ );
+
+ hub_calibration_timer : soda_calibration_timer
+ port map(
+ SYSCLK => SYSCLK,
+ RESET => RESET,
+ CLEAR => '0',
+ CLK_EN => '1',
+ --Internal Connection
+ START_CALIBRATION => start_calibration_S,
+ END_CALIBRATION => reply_valid_S(i),
+ CALIB_VALID_OUT => calibration_valid_S(i),
+ CALIB_TIME_OUT => calibration_time_S(i)
+ );
+
+ hub_store_calib_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if( RESET = '1' ) then
+ calib_register_S(i) <= (others => '0');
+ else
+ calib_register_S(i)(7 downto 0) <= calibration_time_S(i);
+ end if;
+ end if;
+ end process;
+
+ -----------------------------------------------------------
+ -- Reply status report --
+ -----------------------------------------------------------
+ reply_report_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if( RESET = '1' ) then
+ channel_status_S(i) <= '0';
+ elsif (reply_valid_S(i)='1') then
+ channel_status_S(i) <= reply_OK_S(i) or dead_channels_S(i);
+ else
+ channel_status_S(i) <= '0';
+ end if;
+ end if;
+ end process;
+
+ end generate;
+
+-----------------------------------------------------------
+-- Reset the unused bits of channel_status_S --
+-----------------------------------------------------------
+ other_bits :for j in 31 downto c_HUB_CHILDREN generate
+ init_unused_bits_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if( RESET = '1' ) then
+ channel_status_S(j) <= '0'; -- reset status bits
+ end if;
+ end if;
+ end process;
+ end generate;
+
+-----------------------------------------------------------
+-- Transmission history for reply-checking --
+-----------------------------------------------------------
+ packet_history_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if( RESET = '1' ) then
+ last_packet_sent_S <= c_NO_PACKET;
+ elsif (start_of_superburst_S='1') then
+ last_packet_sent_S <= c_BST_PACKET;
+ elsif (soda_cmd_valid_S='1') then
+ last_packet_sent_S <= c_CMD_PACKET;
+ end if;
+ end if;
+ end process;
+
+---------------------------------------------------------
+-- RegIO Statemachine
+---------------------------------------------------------
+ STATE_MEM: process( SYSCLK)
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if( RESET = '1' ) then
+ CURRENT_STATE <= SLEEP;
+ bus_ack <= '0';
+ store_wr<= '0';
+ store_rd<= '0';
+ else
+ CURRENT_STATE <= NEXT_STATE;
+ bus_ack <= bus_ack_x;
+ store_wr<= store_wr_x;
+ store_rd<= store_rd_x;
+ end if;
+ end if;
+ end process STATE_MEM;
+
+-- Transition matrix
+ TRANSFORM: process(CURRENT_STATE, SODA_READ_IN, SODA_WRITE_IN )
+ begin
+ NEXT_STATE <= SLEEP;
+ bus_ack_x<= '0';
+ store_wr_x <= '0';
+ store_rd_x <= '0';
+ case CURRENT_STATE is
+ when SLEEP =>
+ if ( (SODA_READ_IN = '1') ) then
+ NEXT_STATE <= RD_RDY;
+ store_rd_x <= '1';
+ elsif( (SODA_WRITE_IN = '1') ) then
+ NEXT_STATE <= WR_RDY;
+ store_wr_x <= '1';
+ else
+ NEXT_STATE <= SLEEP;
+ end if;
+ when RD_RDY =>
+ NEXT_STATE <= RD_ACK;
+ when WR_RDY =>
+ NEXT_STATE <= WR_ACK;
+ when RD_ACK =>
+ if( SODA_READ_IN = '0' ) then
+ NEXT_STATE <= DONE;
+ bus_ack_x <= '1';
+ else
+ NEXT_STATE <= RD_ACK;
+ bus_ack_x <= '1';
+ end if;
+ when WR_ACK =>
+ if( SODA_WRITE_IN = '0' ) then
+ NEXT_STATE <= DONE;
+ bus_ack_x <= '1';
+ else
+ NEXT_STATE <= WR_ACK;
+ bus_ack_x <= '1';
+ end if;
+ when DONE =>
+ NEXT_STATE <= SLEEP;
+ when others =>
+ NEXT_STATE <= SLEEP;
+ end case;
+end process TRANSFORM;
+
+
+---------------------------------------------------------
+-- data handling --
+---------------------------------------------------------
+-- For sim purposes the HUB gets addresses 01XX
+-- register write
+ THE_WRITE_REG_PROC: process( SYSCLK )
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if ( RESET = '1' ) then
+ -- do NOT reset dead_channels; This is a task for slow-control ONLY
+ elsif( (store_wr = '1') and (SODA_ADDR_IN = "0100") ) then --
+ dead_channels_S <= SODA_DATA_IN(31 downto 0);
+ end if;
+ end if;
+ end process THE_WRITE_REG_PROC;
+
+-- register read
+ THE_READ_REG_PROC: process( SYSCLK )
+ begin
+ if( rising_edge(SYSCLK) ) then
+ if ( RESET = '1' ) then
+ buf_bus_data_out <= (others => '0');
+ elsif( (store_rd = '1') and (SODA_ADDR_IN = B"0100") ) then
+ buf_bus_data_out <= '0' & soda_cmd_word_S;
+ elsif( (store_rd = '1') and (SODA_ADDR_IN = B"0101") ) then
+ buf_bus_data_out <= channel_status_S;
+ elsif( (store_rd = '1') and (SODA_ADDR_IN = B"0110") ) then
+ buf_bus_data_out <= dead_channels_S;
+ elsif( (store_rd = '1') and (SODA_ADDR_IN(3 downto 2) = "10") ) then
+ for j in 0 to c_HUB_CHILDREN-1 loop
+ if (j=conv_integer(SODA_ADDR_IN(1 downto 0))) then
+ buf_bus_data_out <= calib_register_S(j);
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process THE_READ_REG_PROC;
+
+-- output signals
+ SODA_DATA_OUT <= buf_bus_data_out;
+ SODA_ACK_OUT <= bus_ack;
+
+end architecture;
\ No newline at end of file
diff --git a/source/soda_reply_handler.vhd b/source/soda_reply_handler.vhd
new file mode 100644
index 0000000..4d33d05
--- /dev/null
+++ b/source/soda_reply_handler.vhd
@@ -0,0 +1,75 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net16_hub_func.all;
+use work.soda_components.all;
+
+entity soda_reply_handler is
+ port(
+ SYSCLK : in std_logic; -- fabric clock
+ RESET : in std_logic; -- synchronous reset
+ CLEAR : in std_logic; -- asynchronous reset
+ CLK_EN : in std_logic;
+ --Internal Connection
+ LAST_PACKET : in t_PACKET_TYPE_SENT := c_NO_PACKET;
+ EXPECTED_REPLY_IN : in std_logic_vector(7 downto 0) := (others => '0');
+ RX_DLM_IN : in std_logic := '0';
+ RX_DLM_WORD_IN : in std_logic_vector(7 downto 0) := (others => '0');
+ REPLY_VALID_OUT : out std_logic := '0';
+-- SUPERBURST_ERROR_OUT : out std_logic := '0';
+-- CRC_ERROR_OUT : out std_logic := '0';
+ REPLY_OK_OUT : out std_logic := '0'
+ );
+end soda_reply_handler;
+
+architecture Behavioral of soda_reply_handler is
+
+ type packet_state_type is ( c_RST, c_IDLE, c_ERROR, c_REPLY, c_DONE);
+ signal packet_state_S : packet_state_type := c_IDLE;
+
+begin
+
+ reply_fsm_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if (RESET='1') then
+ REPLY_VALID_OUT <= '0';
+ REPLY_OK_OUT <= '0';
+ packet_state_S <= c_IDLE;
+ else
+ REPLY_VALID_OUT <= '0';
+ case packet_state_S is
+ when c_IDLE =>
+ if (RX_DLM_IN='1') then
+ packet_state_S <= c_REPLY;
+ REPLY_VALID_OUT <= '1';
+ if (EXPECTED_REPLY_IN = RX_DLM_WORD_IN) then
+ REPLY_OK_OUT <= '1';
+ else
+ REPLY_OK_OUT <= '0';
+ end if;
+ end if;
+ when c_REPLY =>
+ if (RX_DLM_IN='0') then
+ REPLY_VALID_OUT <= '1';
+ packet_state_S <= c_IDLE;
+ else
+ packet_state_S <= c_ERROR;
+ end if;
+ when c_ERROR =>
+ packet_state_S <= c_IDLE;
+ REPLY_OK_OUT <= '0';
+ REPLY_OK_OUT <= '0';
+ when others =>
+ packet_state_S <= c_IDLE;
+ REPLY_OK_OUT <= '0';
+ end case;
+ end if;
+ end if;
+ end process;
+
+end architecture;
\ No newline at end of file
diff --git a/source/soda_reply_pkt_builder.vhd b/source/soda_reply_pkt_builder.vhd
new file mode 100644
index 0000000..ccb1349
--- /dev/null
+++ b/source/soda_reply_pkt_builder.vhd
@@ -0,0 +1,77 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.trb_net_components.all;
+use work.trb_net16_hub_func.all;
+use work.soda_components.all;
+
+entity soda_reply_pkt_builder is
+ port(
+ SYSCLK : in std_logic; -- fabric clock
+ RESET : in std_logic; -- synchronous reset
+ CLEAR : in std_logic; -- asynchronous reset
+ CLK_EN : in std_logic;
+ --Internal Connection
+ START_OF_SUPERBURST : in std_logic := '0';
+ SUPER_BURST_NR_IN : in std_logic_vector(30 downto 0) := (others => '0');
+ SODA_CMD_STROBE_IN : in std_logic := '0'; --
+ SODA_CMD_WORD_IN : in std_logic_vector(30 downto 0) := (others => '0'); --REGIO_CTRL_REG in trbnet handler is 32 bit
+ TX_DLM_OUT : out std_logic := '0'; --
+ TX_DLM_WORD_OUT : out std_logic_vector(7 downto 0) := (others => '0')
+ );
+end soda_reply_pkt_builder;
+
+architecture Behavioral of soda_reply_pkt_builder is
+
+ type packet_state_type is ( c_IDLE, c_PKT1, c_PKT2 );
+ signal packet_state_S : packet_state_type := c_IDLE;
+
+begin
+
+ reply_fsm_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if (RESET='1') then
+ packet_state_S <= c_IDLE;
+ else
+ case packet_state_S is
+ when c_IDLE =>
+ if (START_OF_SUPERBURST='1') or (SODA_CMD_STROBE_IN='1') then
+ packet_state_S <= c_PKT1;
+ end if;
+ when c_PKT1 =>
+ packet_state_S <= c_PKT2;
+ when c_PKT2 =>
+ packet_state_S <= c_IDLE;
+ when others =>
+ packet_state_S <= c_IDLE;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ collect_reply_proc : process(SYSCLK)
+ begin
+ if rising_edge(SYSCLK) then
+ if (RESET='1') then
+ TX_DLM_OUT <= '0';
+ TX_DLM_WORD_OUT <= (others=>'0');
+ elsif (START_OF_SUPERBURST='1') then
+ TX_DLM_OUT <= '1';
+ TX_DLM_WORD_OUT <= SUPER_BURST_NR_IN(7 downto 0);
+ elsif (SODA_CMD_STROBE_IN='1') then
+ TX_DLM_OUT <= '1';
+ TX_DLM_WORD_OUT <= SODA_CMD_WORD_IN(7 downto 0);
+ elsif (packet_state_S=c_PKT1) then
+ TX_DLM_OUT <= '0';
+ elsif (packet_state_S=c_PKT2) then
+ TX_DLM_WORD_OUT <= (others=>'0');
+ end if;
+ end if;
+ end process;
+
+
+end architecture;
\ No newline at end of file