signal int_data_out : std_logic_vector(50 downto 0) := (others => '0');
signal int_read_in : std_logic := '0';
+ signal write_data_out : std_logic_vector(51 downto 0) := (others => '0');
+
signal read_type : std_logic_vector(2 downto 0) := (others => '0');
signal read_f2 : std_logic_vector(3 downto 0) := (others => '0');
+ signal read_f1 : std_logic_vector(3 downto 0) := (others => '0');
signal stat_buffer : std_logic_vector(31 downto 0) := (others => '0');
+
+ signal waiter : std_logic := '0';
component trb_net_ibuf
--med_data_in <= (others => '0');
med_data_in(50 downto 48) <= read_type;
med_data_in(19 downto 16) <= read_f2;
+ med_data_in(3 downto 0) <= read_f1;
variable leer : character;
variable var1, var2 : std_logic;
variable varx1 : std_logic_vector(2 downto 0);
- variable varx2 : std_logic_vector(3 downto 0);
+ variable varx2, varx3 : std_logic_vector(3 downto 0);
begin
if falling_edge(CLK) then
if (not endfile(protokoll)) then
read(myoutline,var1);
med_dataready_in <= var1;
read(myoutline,leer);
-
+
read(myoutline,varx1);
read_type <= varx1;
read(myoutline,leer);
read(myoutline,varx2);
read_f2 <= varx2;
--- read(myoutline,leer);
+ read(myoutline,leer);
+
+ read(myoutline,varx3);
+ read_f1 <= varx3;
end if;
end if;
end process STIMULI;
-
-
--- RESPONSE: process (clk)
--- file protokoll : text open write_mode is "out_ibuf.txt";
--- variable myoutline : line;
+
+-- int_read_in <= int_dataready_out after 5ns;
--- begin -- process RESPONSE
--- if rising_edge(CLK) then -- rising clock edge
+READ_BUF: process
+ file protokoll : text open read_mode is "out_ibuf.txt";
+ variable myoutline : line;
+ variable leer : character;
+ variable var1, var2 : std_logic;
+ variable varx1 : std_logic_vector(2 downto 0);
+ variable varx2, varx3 : std_logic_vector(3 downto 0);
+ begin
+ wait on CLK;
+ if rising_edge(CLK) then
+ wait for 5ns;
+ if (not endfile(protokoll)) then
+ readline(protokoll,myoutline);
+ read(myoutline,var1);
+ read(myoutline,leer);
+ read(myoutline,var2);
+
+ if var1 = '1' and var2 = '0' then
+
+ if int_dataready_out = '0' then
+ int_read_in <= '0';
+ waiter <= '1';
+ wait until int_dataready_out = '1';
+ waiter <= '0';
+ end if;
+ wait for 5ns;
+ int_read_in <= '1';
+ int_header_in <= '0';
+
+ elsif var1 = '1' and var2 = '1' then
+ wait for 5ns;
+ int_read_in <= '1';
+ int_header_in <= '1';
+ else
+ int_read_in <= '0';
+ int_header_in <= '0';
+ end if;
+
+ end if;
+ end if;
+ end process;
--- hwrite (myoutline, mydepth);
--- writeline(protokoll, myoutline);
--- end if;
--- end process RESPONSE;
+
+ write_data_out(50 downto 0)<= int_data_out;
+ write_data_out(51) <= '0';
+
+ RESPONSE: process (clk)
+ file protokoll : text open write_mode is "result_out_ibuf.txt";
+ variable myoutline : line;
+
+ begin -- process RESPONSE
+ if rising_edge(CLK) and int_read_in='1' then -- rising clock edge and I'm
+ -- reading
+ hwrite (myoutline, write_data_out(51 downto 0));
+ writeline(protokoll, myoutline);
+ end if;
+ end process RESPONSE;
end trb_net_ibuf_testbench_arch;
--- /dev/null
+-- for a description see HADES wiki
+-- http://hades-wiki.gsi.de/cgi-bin/view/DaqSlowControl/TrbNetIBUF
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.STD_LOGIC_ARITH.ALL;
+USE IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+use work.trb_net_std.all;
+
+--Entity decalaration for clock generator
+entity trb_net_ibuf is
+
+ generic (DEPTH : integer := 3); -- Depth of the FIFO, 2^(n+1)
+
+ port(
+ -- Misc
+ CLK : in std_logic;
+ RESET : in std_logic;
+ CLK_EN : in std_logic;
+ -- Media direction port
+ MED_DATAREADY_IN: in STD_LOGIC; -- Data word is offered by the Media (the IOBUF MUST read)
+ MED_DATA_IN: in STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ MED_READ_OUT: out STD_LOGIC; -- buffer reads a word from media
+ MED_ERROR_IN: in STD_LOGIC_VECTOR (2 downto 0); -- Status bits
+ -- Internal direction port
+ INT_HEADER_IN: in STD_LOGIC; -- Concentrator kindly asks to resend the last header
+ INT_DATAREADY_OUT: out STD_LOGIC;
+ INT_DATA_OUT: out STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ INT_READ_IN: in STD_LOGIC;
+ INT_ERROR_OUT: out STD_LOGIC_VECTOR (2 downto 0); -- Status bits
+ -- Status and control port
+ STAT_LOCKED: out STD_LOGIC_VECTOR (15 downto 0);
+ CTRL_LOCKED: in STD_LOGIC_VECTOR (15 downto 0);
+ STAT_BUFFER: out STD_LOGIC_VECTOR (31 downto 0)
+ );
+END trb_net_ibuf;
+
+architecture trb_net_ibuf_arch of trb_net_ibuf is
+
+component trb_net_fifo is
+
+ generic (WIDTH : integer := 8; -- FIFO word width
+ DEPTH : integer := 4); -- Depth of the FIFO, 2^(n+1)
+
+ port (CLK : in std_logic;
+ RESET : in std_logic;
+ CLK_EN : in std_logic;
+
+ DATA_IN : in std_logic_vector(WIDTH - 1 downto 0); -- Input data
+ WRITE_ENABLE_IN : in std_logic;
+ DATA_OUT : out std_logic_vector(WIDTH - 1 downto 0); -- Output data
+ READ_ENABLE_IN : in std_logic;
+ FULL_OUT : out std_logic; -- Full Flag
+ EMPTY_OUT : out std_logic;
+ DEPTH_OUT : out std_logic_vector(7 downto 0)
+ );
+
+end component;
+
+signal fifo_data_in : std_logic_vector(50 downto 0);
+signal fifo_data_out : std_logic_vector(50 downto 0);
+signal fifo_write, fifo_read : std_logic;
+signal fifo_full, fifo_empty : std_logic;
+signal fifo_depth : std_logic_vector(7 downto 0);
+
+signal filtered_dataready : std_logic;
+signal filtered_read_out : std_logic;
+
+signal got_ack_internal, reg_ack_internal : std_logic; --should be raised for 1 cycle when ack
+ --arrived
+signal is_locked, got_locked : std_logic;
+signal got_eob_out, reg_eob_out: std_logic;
+signal tmp_INT_DATAREADY_OUT: std_logic;
+signal current_last_header, next_last_header : std_logic_vector(50 downto 0);
+
+type ERROR_STATE is (IDLE, GOT_OVERFLOW_ERROR, GOT_LOCKED_ERROR, GOT_UNDEFINED_ERROR);
+signal current_error_state, next_error_state : ERROR_STATE;
+
+signal next_rec_buffer_size_out, current_rec_buffer_size_out
+ : std_logic_vector(3 downto 0); -- buffer size control
+
+ begin
+
+ FIFO: trb_net_fifo
+ generic map (
+ WIDTH => 51,
+ DEPTH => DEPTH)
+ port map (
+ CLK => CLK,
+ RESET => RESET,
+ CLK_EN => CLK_EN,
+ DATA_IN => fifo_data_in,
+ WRITE_ENABLE_IN => fifo_write,
+ DATA_OUT => fifo_data_out,
+ READ_ENABLE_IN => fifo_read,
+ FULL_OUT => fifo_full,
+ EMPTY_OUT => fifo_empty,
+ DEPTH_OUT => fifo_depth
+ );
+
+ fifo_data_in <= MED_DATA_IN;
+
+-- this process controls the writing of the media into the fifo
+ FILTER_DATAREADY_IN : process(MED_DATA_IN, MED_DATAREADY_IN, MED_ERROR_IN,
+ fifo_full, is_locked, current_rec_buffer_size_out,
+ current_error_state)
+ begin -- process
+ filtered_dataready <= '0';
+ got_ack_internal <= '0';
+ filtered_read_out <= '0';
+ fifo_write <= '0';
+ next_rec_buffer_size_out <= current_rec_buffer_size_out;
+ next_error_state <= current_error_state;
+
+ if MED_DATAREADY_IN = '1' then
+ if MED_DATA_IN(TYPE_POSITION) = TYPE_ACK then
+ got_ack_internal <= '1';
+ filtered_read_out <= '1'; -- read from media in any case
+ if MED_DATA_IN(F1_POSITION) = F1_CHECK_ACK then
+ next_rec_buffer_size_out <= MED_DATA_IN(BUFFER_SIZE_POSITION);
+ end if;
+ elsif fifo_full = '0' and is_locked = '0' then
+ fifo_write <= '1';
+ elsif fifo_full = '1' then
+ next_error_state <= GOT_OVERFLOW_ERROR;
+ elsif is_locked = '1' then
+ next_error_state <= GOT_LOCKED_ERROR;
+ else
+ next_error_state <= GOT_UNDEFINED_ERROR;
+ end if; -- end TYPE
+
+ end if; -- end MED_DATAREADY_IN
+ end process;
+
+ -- unregistered reaction, because it has to be fast!!!
+ MED_READ_OUT <= filtered_read_out;
+
+reg_buffer: process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ current_rec_buffer_size_out <= (others => '0');
+ reg_ack_internal <='0';
+ current_error_state <= IDLE;
+ elsif CLK_EN = '1' then
+ current_rec_buffer_size_out <= next_rec_buffer_size_out;
+ reg_ack_internal <= got_ack_internal;
+ current_error_state <= next_error_state;
+ else
+ current_rec_buffer_size_out <= current_rec_buffer_size_out;
+ reg_ack_internal <= reg_ack_internal;
+ current_error_state <= current_error_state;
+ end if;
+ end if;
+ end process;
+
+-- this process controls what will be forwarded to the internal point
+ FILTER_DATA_OUT : process (INT_HEADER_IN, fifo_data_out,
+ current_last_header, tmp_INT_DATAREADY_OUT)
+ begin
+ INT_DATA_OUT <= (others => '0');
+ if INT_HEADER_IN = '1' then
+ INT_DATA_OUT <= current_last_header;
+ elsif tmp_INT_DATAREADY_OUT ='1' then
+ INT_DATA_OUT <= fifo_data_out;
+ else
+ INT_DATA_OUT(TYPE_POSITION) <= TYPE_ILLEGAL;
+ end if;
+ end process;
+
+-- calculate the INT_DATAREADY_OUT
+ CALC_INT_DATAREADY_OUT: process (fifo_empty, fifo_data_out)
+ begin
+ if fifo_empty = '0' and not (fifo_data_out(TYPE_POSITION) = TYPE_EOB) then
+ tmp_INT_DATAREADY_OUT <= '1';
+ else
+ tmp_INT_DATAREADY_OUT <= '0';
+ end if;
+ end process;
+
+INT_DATAREADY_OUT <= tmp_INT_DATAREADY_OUT;
+
+-- this process control the read of the internal point from the fifo
+ FILTER_OUT: process (INT_READ_IN, INT_HEADER_IN, fifo_data_out,
+ current_last_header)
+
+ begin -- process
+ got_locked <= '0';
+ fifo_read <= '0';
+ got_eob_out <= '0';
+ next_last_header <= current_last_header;
+
+ if INT_READ_IN = '1' then
+
+ if fifo_data_out(TYPE_POSITION) = TYPE_TRM then
+ got_eob_out <= '1';
+ fifo_read <= '1';
+
+ else -- no TRM, normal read
+ got_eob_out <= '0';
+ fifo_read <= '1';
+
+ if fifo_data_out(TYPE_POSITION) = TYPE_HDR then
+ next_last_header <= fifo_data_out;
+ end if;
+ end if;
+
+
+ else -- no external read
+ if fifo_data_out(TYPE_POSITION) = TYPE_EOB then
+ got_eob_out <= '1';
+ fifo_read <= '1'; -- autodestroy EOB
+ end if;
+ end if; -- INT_READ_IN
+ end process;
+
+
+
+
+
+reg_locked: process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ is_locked <= '0';
+ reg_eob_out <= '0';
+ current_last_header <= (others => '0');
+ elsif CLK_EN = '1' then
+ is_locked <= got_locked;
+ reg_eob_out <= got_eob_out;
+ current_last_header <= next_last_header;
+ else
+ is_locked <= is_locked;
+ reg_eob_out <= reg_eob_out;
+ current_last_header <= current_last_header;
+ end if;
+ end if;
+ end process;
+
+
+
+-- make STAT_BUFFER
+ STAT_BUFFER(3 downto 0) <= fifo_depth(3 downto 0);
+ STAT_BUFFER(7 downto 4) <= current_rec_buffer_size_out;
+ STAT_BUFFER(8) <= reg_eob_out;
+ STAT_BUFFER(9) <= reg_ack_internal;
+
+ MAKE_ERROR_BITS : process(current_error_state)
+ begin
+ if current_error_state = IDLE then
+ STAT_BUFFER(11 downto 10) <= "00";
+ elsif current_error_state = GOT_OVERFLOW_ERROR then
+ STAT_BUFFER(11 downto 10) <= "01";
+ elsif current_error_state = GOT_LOCKED_ERROR then
+ STAT_BUFFER(11 downto 10) <= "10";
+ else
+ STAT_BUFFER(11 downto 10) <= "11";
+ end if;
+ end process;
+
+ STAT_BUFFER(31 downto 12) <= (others => '0');
+
+end trb_net_ibuf_arch;
+