From bdeb615408a1a90a3aa8326ffeb8b4ddab32fdf8 Mon Sep 17 00:00:00 2001 From: hadeshyp Date: Wed, 28 Nov 2007 14:06:31 +0000 Subject: [PATCH] update regIO, not tested yet, Jan --- trb_net16_regIO.vhd | 340 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 299 insertions(+), 41 deletions(-) diff --git a/trb_net16_regIO.vhd b/trb_net16_regIO.vhd index ac0dae3..f6e1087 100644 --- a/trb_net16_regIO.vhd +++ b/trb_net16_regIO.vhd @@ -5,27 +5,22 @@ USE IEEE.std_logic_UNSIGNED.ALL; 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 @@ -51,12 +46,12 @@ entity trb_net16_regIO is 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); @@ -67,34 +62,297 @@ entity trb_net16_regIO is --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; -- 2.43.0