From bd985861647ea88636da74c3913faaae9dcc7bb8 Mon Sep 17 00:00:00 2001 From: Peter Lemmens Date: Wed, 4 Sep 2013 08:22:58 +0200 Subject: [PATCH] Source files added for a complete (?) soda-chain comprised of source, hub and client Source is tested in test-benches (functional tests) --- source/TB_soda_chain.vhd | 203 +++++++++++++++++++ source/TB_soda_source.vhd | 139 +++++++++++++ source/soda_calibration_timer.vhd | 63 ++++++ source/soda_client.vhd | 188 +++++++++++++++++ source/soda_hub.vhd | 325 ++++++++++++++++++++++++++++++ source/soda_reply_handler.vhd | 75 +++++++ source/soda_reply_pkt_builder.vhd | 77 +++++++ 7 files changed, 1070 insertions(+) create mode 100644 source/TB_soda_chain.vhd create mode 100644 source/TB_soda_source.vhd create mode 100644 source/soda_calibration_timer.vhd create mode 100644 source/soda_client.vhd create mode 100644 source/soda_hub.vhd create mode 100644 source/soda_reply_handler.vhd create mode 100644 source/soda_reply_pkt_builder.vhd 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 -- 2.43.0