use work.trb_net_std.all;
---REGISTERS within 0..REGISTER_COUNT are handled internally, while all other r/w requests are offered to the parent
---REGISTERS with Bit 7 set are writeable (CTRL), with Bit 7 unset are readonly (STAT) from outside and vice versa from inside
+--REGISTERS within 0..2**(ADDRESS_USED_WIDTH) are handled internally, while all other r/w requests are offered to the parent
+--REGISTERS with highest bit set are writeable (CTRL), with highest bit unset are readonly (STAT) from outside and vice versa from inside
+--the highest address bit is not used to determine the data position inside REGISTER IN/OUT
+--REGISTER_IN is not registered again
+--if DAT-Port is not used, set DAT_DATAREADY_IN to '1'
+
+--APL-Port NOT implemented yet
entity trb_net16_regIO is
generic (
- MY_ADDRESS : std_logic_vector(15 downto 0);
+ MY_ADDRESS : std_logic_vector(15 downto 0) := x"F001";
REGISTER_WIDTH : integer range 32 to 32 := 32;
ADDRESS_WIDTH : integer range 8 to 16 := 16;
- REGISTER_COUNT : integer range 255 to 255 := 255;
- REGISTER_WRITEABLE : std_logic_vector(255 downto 0) := "1111111111111111" & "1111111111111111" &
- "1111111111111111" & "1111111111111111" &
- "1111111111111111" & "1111111111111111" &
- "1111111111111111" & "1111111111111111" &
- "0000000000000000" & "0000000000000000" &
- "0000000000000000" & "0000000000000000" &
- "0000000000000000" & "0000000000000000" &
- "0000000000000000" & "0000000000000000";
+ ADDRESS_USED_WIDTH : integer range 1 to 16 := 3;
--no data / address out?
- NO_DAT_PORT : std_logic := '0';
- --no APL out?
- NO_APL_PORT : std_logic := '0';
+ NO_DAT_PORT : std_logic := '0'
);
port(
-- Misc
API_READ_OUT: out std_logic;
-- APL Control port
API_RUN_IN: in std_logic;
- API_MY_ADDRESS_OUT: in std_logic_vector (15 downto 0);
- API_SEQNR_IN: in std_logic_vector (7 downto 0)
+ API_MY_ADDRESS_OUT: out std_logic_vector (15 downto 0);
+ API_SEQNR_IN: in std_logic_vector (7 downto 0);
--Register in / outside
- REGISTERS_IN : in std_logic_vector(REGISTER_WIDTH*REGISTER_COUNT-1 downto 0);
- REGISTERS_OUT : out std_logic_vector(REGISTER_WIDTH*REGISTER_COUNT-1 downto 0);
+ REGISTERS_IN : in std_logic_vector(REGISTER_WIDTH*2**(ADDRESS_USED_WIDTH-1)-1 downto 0);
+ REGISTERS_OUT : out std_logic_vector(REGISTER_WIDTH*2**(ADDRESS_USED_WIDTH-1)-1 downto 0);
--following ports only used when no internal register is accessed
DAT_ADDR_OUT : out std_logic_vector(ADDRESS_WIDTH-1 downto 0);
--Data input can only be used as reaction on read or write access. write operation should return data
--if successful
DAT_DATA_IN : in std_logic_vector(REGISTER_WIDTH-1 downto 0);
- DAT_DATAREADY_IN : in std_logic;
-
- --all other dtype beside register read/write are directly passed to APL
- -- APL Transmitter port
- APL_DATA_IN : in std_logic_vector (15 downto 0);
- APL_PACKET_NUM_IN : in std_logic_vector (1 downto 0);
- APL_WRITE_IN : in std_logic;
- APL_FIFO_FULL_OUT : out std_logic;
- APL_SHORT_TRANSFER_IN : in std_logic;
- APL_DTYPE_IN : in std_logic_vector (3 downto 0);
- APL_ERROR_PATTERN_IN : in std_logic_vector (31 downto 0);
- APL_SEND_IN : in std_logic;
- APL_TARGET_ADDRESS_IN : in std_logic_vector (15 downto 0);
- -- Receiver port
- APL_DATA_OUT : out std_logic_vector (15 downto 0);
- APL_PACKET_NUM_OUT : out std_logic_vector (1 downto 0);
- APL_TYP_OUT : out std_logic_vector (2 downto 0);
- APL_DATAREADY_OUT : out std_logic;
- APL_READ_IN : in std_logic;
- -- APL Control port
- APL_RUN_OUT : out std_logic;
- APL_SEQNR_OUT : out std_logic_vector (7 downto 0)
+ DAT_DATAREADY_IN : in std_logic
+
);
end entity;
architecture trb_net16_regIO_arch of trb_net16_regIO is
+ component trb_net_pattern_gen is
+ generic (MULT_WIDTH : integer := ADDRESS_USED_WIDTH-1);
+ port(
+ INPUT_IN : in STD_LOGIC_VECTOR (ADDRESS_USED_WIDTH-2 downto 0);
+ RESULT_OUT: out STD_LOGIC_VECTOR (2**(ADDRESS_USED_WIDTH-1)-1 downto 0)
+ );
+ end component;
+
+ type fsm_state_t is (IDLE, HEADER_RECV, REG_READ, REG_WRITE,
+ SEND_REPLY_DATA_finish, SEND_REPLY_SHORT_TRANSFER, SEND_REPLY_DATA,
+ DAT_INT, DAT_WAIT);
+ signal current_state, next_state : fsm_state_t;
+ signal HDR_F1, HDR_F2, HDR_F3 : std_logic_vector(15 downto 0);
+ signal next_HDR_F1, next_HDR_F2, next_HDR_F3 : std_logic_vector(15 downto 0);
+ signal next_Reg_high, saved_Reg_high : std_logic_vector(15 downto 0);
+ signal next_Reg_low, saved_Reg_low : std_logic_vector(15 downto 0);
+ signal next_address, address : std_logic_vector(15 downto 0);
+ signal next_operation, saved_operation : std_logic_vector(3 downto 0);
+
+ signal buf_API_READ_OUT, next_API_READ_OUT : std_logic;
+ signal buf_API_SEND_OUT, next_API_SEND_OUT : std_logic;
+ signal buf_API_PACKET_NUM_OUT, next_API_PACKET_NUM_OUT : std_logic_vector(1 downto 0);
+ signal buf_API_DATA_OUT, next_API_DATA_OUT : std_logic_vector(15 downto 0);
+ signal buf_API_SHORT_TRANSFER_OUT, next_API_SHORT_TRANSFER_OUT : std_logic;
+ signal buf_API_WRITE_OUT, next_API_WRITE_OUT : std_logic;
+
+ signal buf_DAT_DATA_OUT, next_DAT_DATA_OUT : std_logic_vector(REGISTER_WIDTH-1 downto 0);
+ signal buf_DAT_READ_ENABLE_OUT, next_DAT_READ_ENABLE_OUT : std_logic;
+ signal buf_DAT_WRITE_ENABLE_OUT, next_DAT_WRITE_ENABLE_OUT : std_logic;
+ signal buf_DAT_ADDR_OUT, next_DAT_ADDR_OUT : std_logic_vector(ADDRESS_WIDTH-1 downto 0);
+
+ signal buf_REGISTERS_OUT : std_logic_vector(REGISTER_WIDTH*2**(ADDRESS_USED_WIDTH-1)-1 downto 0);
+ signal REGISTERS_OUT_write_enable : std_logic_vector(2**(ADDRESS_USED_WIDTH-1)-1 downto 0);
+ signal reg_enable_pattern : std_logic_vector(2**(ADDRESS_USED_WIDTH-1)-1 downto 0);
+
+
begin
+ pattern_gen_inst : trb_net_pattern_gen port map(address(ADDRESS_USED_WIDTH-2 downto 0), reg_enable_pattern);
+
+
+ fsm : process(current_state,
+ API_DATA_IN, API_PACKET_NUM_IN, API_TYP_IN, API_DATAREADY_IN, API_FIFO_FULL_IN, API_RUN_IN,
+ HDR_F1, HDR_F2, HDR_F3, address, saved_Reg_high,
+ buf_API_SEND_OUT, buf_API_PACKET_NUM_OUT, buf_API_DATA_OUT, buf_API_SHORT_TRANSFER_OUT,
+ REGISTERS_IN, buf_REGISTERS_OUT, reg_enable_pattern
+ )
+ begin
+ next_state <= current_state;
+ next_HDR_F1 <= HDR_F1;
+ next_HDR_F2 <= HDR_F2;
+ next_HDR_F3 <= HDR_F3;
+ next_address <= address;
+ next_Reg_high <= saved_Reg_high;
+ next_Reg_low <= saved_Reg_low;
+ next_API_READ_OUT <= '1';
+ next_API_SEND_OUT <= buf_API_SEND_OUT;
+ next_API_WRITE_OUT <= '0';
+ next_API_PACKET_NUM_OUT <= buf_API_PACKET_NUM_OUT;
+ next_API_DATA_OUT <= buf_API_DATA_OUT;
+ next_API_SHORT_TRANSFER_OUT <= buf_API_SHORT_TRANSFER_OUT;
+ next_operation <= saved_operation;
+ REGISTERS_OUT_write_enable <= (others => '0');
+ next_DAT_DATA_OUT <= buf_DAT_DATA_OUT;
+ next_DAT_READ_ENABLE_OUT <= '0';
+ next_DAT_WRITE_ENABLE_OUT <= '0';
+ next_DAT_ADDR_OUT <= buf_DAT_ADDR_OUT;
+
+ case current_state is
+ when IDLE =>
+ next_API_SEND_OUT <= '0';
+ next_API_SHORT_TRANSFER_OUT <= '0';
+ if API_TYP_IN = TYPE_HDR then
+ next_state <= HEADER_RECV;
+ end if;
+
+ --read and save HDR, then decide what to do by dtype
+ when HEADER_RECV =>
+ if API_DATAREADY_IN = '1' then
+ if API_PACKET_NUM_IN = "01" then
+ next_HDR_F1 <= API_DATA_IN;
+ end if;
+ if API_PACKET_NUM_IN = "10" then
+ next_HDR_F2 <= API_DATA_IN;
+ end if;
+ if API_PACKET_NUM_IN = "11" then
+ next_HDR_F3 <= API_DATA_IN;
+ case API_DATA_IN(3 downto 0) is
+ when "1000" => next_state <= REG_READ;
+ when "1001" => next_state <= REG_WRITE;
+ when others => next_state <= SEND_REPLY_SHORT_TRANSFER;
+ end case;
+ next_operation <= API_DATA_IN(3 downto 0);
+ end if;
+ end if;
+
+ --writing register operation
+ when REG_WRITE =>
+ if API_TYP_IN = TYPE_DAT then
+ case API_PACKET_NUM_IN is
+ when "01" =>
+ next_address <= API_DATA_IN;
+ when "10" =>
+ next_Reg_high <= API_DATA_IN;
+ when "11" =>
+ next_Reg_low <= API_DATA_IN;
+ REGISTERS_OUT_write_enable <= reg_enable_pattern;
+ next_state <= SEND_REPLY_DATA;
+ if or_all(address(ADDRESS_WIDTH-1 downto ADDRESS_USED_WIDTH)) = '1' then
+ if NO_DAT_PORT = '0' then
+ next_state <= DAT_INT;
+ else
+ next_state <= SEND_REPLY_SHORT_TRANSFER;
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ when REG_READ =>
+ if API_TYP_IN = TYPE_DAT and API_PACKET_NUM_IN = "01" and API_DATAREADY_IN = '1' then
+ next_address <= API_DATA_IN;
+ next_state <= SEND_REPLY_DATA;
+ if or_all(API_DATA_IN(ADDRESS_WIDTH-1 downto ADDRESS_USED_WIDTH)) = '1' then
+ if NO_DAT_PORT = '0' then
+ next_state <= DAT_INT;
+ else
+ next_state <= SEND_REPLY_SHORT_TRANSFER;
+ end if;
+ end if;
+ end if;
+ when SEND_REPLY_DATA =>
+ next_API_SEND_OUT <= '1';
+
+ if API_FIFO_FULL_IN = '1' then
+ next_API_WRITE_OUT <= '0';
+ else
+ next_API_WRITE_OUT <= '1';
+ if buf_API_PACKET_NUM_OUT = "11" then
+ next_API_PACKET_NUM_OUT <= "01";
+ next_API_DATA_OUT <= address;
+ elsif buf_API_PACKET_NUM_OUT = "01" then
+ next_API_PACKET_NUM_OUT <= "10";
+ if address(ADDRESS_USED_WIDTH-1) = '0' then
+ next_API_DATA_OUT <= REGISTERS_IN
+ (conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+31 downto
+ conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+16);
+ else
+ next_API_DATA_OUT <= buf_REGISTERS_OUT
+ (conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+31 downto
+ conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+16);
+ end if;
+ elsif buf_API_PACKET_NUM_OUT = "10" then
+ next_API_PACKET_NUM_OUT <= "11";
+ if address(ADDRESS_USED_WIDTH-1) = '0' then
+ next_API_DATA_OUT <= REGISTERS_IN
+ (conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+15 downto
+ conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH);
+ else
+ next_API_DATA_OUT <= buf_REGISTERS_OUT
+ (conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH+15 downto
+ conv_integer(address(ADDRESS_USED_WIDTH-2 downto 0))*REGISTER_WIDTH);
+ end if;
+ next_state <= SEND_REPLY_DATA_finish;
+ end if;
+ end if;
+ when SEND_REPLY_DATA_finish =>
+ next_API_SEND_OUT <= '0';
+ next_state <= IDLE;
+
+
+ when SEND_REPLY_SHORT_TRANSFER =>
+ next_API_SHORT_TRANSFER_OUT <= '1';
+ next_API_SEND_OUT <= '1';
+ next_state <= SEND_REPLY_DATA_finish;
+
+ when DAT_INT =>
+ next_DAT_DATA_OUT <= saved_Reg_high & saved_Reg_low;
+ next_DAT_ADDR_OUT <= address;
+ if saved_operation = "1000" then
+ next_DAT_READ_ENABLE_OUT <= '1';
+ elsif saved_operation = "1001" then
+ next_DAT_WRITE_ENABLE_OUT <= '1';
+ end if;
+ next_state <= DAT_WAIT;
+
+ when DAT_WAIT =>
+ if DAT_DATAREADY_IN = '1' then
+ next_API_PACKET_NUM_OUT <= "01";
+ next_API_DATA_OUT <= address;
+ next_API_SEND_OUT <= '1';
+ next_API_WRITE_OUT <= '1';
+ elsif buf_API_PACKET_NUM_OUT = "01" then
+ next_API_PACKET_NUM_OUT <= "10";
+ next_API_DATA_OUT <= DAT_DATA_IN(31 downto 16);
+ next_API_WRITE_OUT <= '1';
+ elsif buf_API_PACKET_NUM_OUT = "10" then
+ next_API_PACKET_NUM_OUT <= "11";
+ next_API_DATA_OUT <= DAT_DATA_IN(15 downto 0);
+ next_API_WRITE_OUT <= '1';
+ next_state <= SEND_REPLY_DATA_finish;
+ end if;
+ when others =>
+ next_state <= IDLE;
+ end case;
+ end process;
+
+
+ reg_fsm : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ current_state <= IDLE;
+ HDR_F1 <= (others => '0');
+ HDR_F2 <= (others => '0');
+ HDR_F3 <= (others => '0');
+ buf_API_READ_OUT <= '0';
+ buf_API_READ_OUT <= '0';
+ buf_API_SEND_OUT <= '0';
+ buf_API_WRITE_OUT <= '0';
+ buf_API_PACKET_NUM_OUT <= "11";
+ buf_API_DATA_OUT <= (others => '0');
+ buf_API_SHORT_TRANSFER_OUT <= '0';
+ address <= (others => '0');
+ saved_Reg_high <= (others => '0');
+ saved_Reg_low <= (others => '0');
+ saved_operation <= (others => '0');
+ buf_DAT_DATA_OUT <= (others => '0');
+ buf_DAT_READ_ENABLE_OUT <= '0';
+ buf_DAT_WRITE_ENABLE_OUT <= '0';
+ buf_DAT_ADDR_OUT <= (others => '0');
+ else
+ current_state <= next_state;
+ HDR_F1 <= next_HDR_F1;
+ HDR_F2 <= next_HDR_F2;
+ HDR_F3 <= next_HDR_F3;
+ buf_API_READ_OUT <= next_API_READ_OUT;
+ buf_API_SEND_OUT <= next_API_SEND_OUT;
+ buf_API_WRITE_OUT <= next_API_WRITE_OUT;
+ buf_API_PACKET_NUM_OUT <= next_API_PACKET_NUM_OUT;
+ buf_API_DATA_OUT <= next_API_DATA_OUT;
+ buf_API_SHORT_TRANSFER_OUT <= next_API_SHORT_TRANSFER_OUT;
+ address <= next_address;
+ saved_Reg_high <= next_Reg_high;
+ saved_Reg_low <= next_Reg_low;
+ saved_operation <= next_operation;
+ buf_DAT_DATA_OUT <= next_DAT_DATA_OUT;
+ buf_DAT_READ_ENABLE_OUT <= next_DAT_READ_ENABLE_OUT;
+ buf_DAT_WRITE_ENABLE_OUT <= next_DAT_WRITE_ENABLE_OUT;
+ buf_DAT_ADDR_OUT <= next_DAT_ADDR_OUT;
+ end if;
+ end if;
+ end process;
+
+ gen_regout : for i in 0 to 2**(ADDRESS_USED_WIDTH-1)-1 generate
+ process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ buf_REGISTERS_OUT((i+1)*REGISTER_WIDTH-1 downto i*REGISTER_WIDTH) <= (others => '0');
+ elsif REGISTERS_OUT_write_enable(i) = '1' then
+ buf_REGISTERS_OUT((i+1)*REGISTER_WIDTH-1 downto i*REGISTER_WIDTH) <= saved_Reg_high & API_DATA_IN;
+ end if;
+ end if;
+ end process;
+ end generate;
+
+ API_READ_OUT <= buf_API_READ_OUT;
+ API_SEND_OUT <= buf_API_SEND_OUT;
+ API_WRITE_OUT <= buf_API_WRITE_OUT;
+ API_PACKET_NUM_OUT <= buf_API_PACKET_NUM_OUT;
+ API_DATA_OUT <= buf_API_DATA_OUT;
+ API_SHORT_TRANSFER_OUT <= buf_API_SHORT_TRANSFER_OUT;
+ API_DTYPE_OUT <= (others => '0');
+ API_MY_ADDRESS_OUT <= MY_ADDRESS;
+ API_ERROR_PATTERN_OUT <= (others => '0');
+ API_TARGET_ADDRESS_OUT <= (others => '0');
+ DAT_DATA_OUT <= buf_DAT_DATA_OUT;
+ DAT_READ_ENABLE_OUT <= buf_DAT_READ_ENABLE_OUT;
+ DAT_WRITE_ENABLE_OUT <= buf_DAT_WRITE_ENABLE_OUT;
+ DAT_ADDR_OUT <= buf_DAT_ADDR_OUT;
+
+
+
+ REGISTERS_OUT <= buf_REGISTERS_OUT;
end architecture;