--- /dev/null
+library ieee;
+
+use ieee.std_logic_1164.all;
+
+USE ieee.std_logic_signed.ALL;
+
+USE ieee.std_logic_arith.ALL;
+
+USE std.textio.ALL;
+USE ieee.std_logic_textio.ALL;
+
+entity trb_net_obuf_testbench is
+
+end trb_net_obuf_testbench;
+
+architecture trb_net_obuf_testbench_arch of trb_net_obuf_testbench is
+
+ signal clk : std_logic := '0';
+ signal reset : std_logic := '1';
+
+ signal int_dataready_in: std_logic := '0';
+ signal int_data_in : std_logic_vector(50 downto 0) := (others => '0');
+ signal int_read_out : std_logic := '0';
+
+ signal med_dataready_out: std_logic := '0';
+ signal med_data_out : std_logic_vector(50 downto 0) := (others => '0');
+ signal med_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 read_ctrl : std_logic_vector(5 downto 0) := (others => '0');
+ signal stat_buffer : std_logic_vector(31 downto 0) := (others => '0');
+ signal ctrl_buffer : std_logic_vector(31 downto 0) := (others => '0');
+ signal stat_locked : std_logic_vector(15 downto 0) := (others => '0');
+
+ signal waiter : std_logic := '0';
+
+
+ component trb_net_obuf
+
+ 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_OUT: out STD_LOGIC;
+ MED_DATA_OUT: out STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ MED_READ_IN: in STD_LOGIC;
+ MED_ERROR_OUT: out STD_LOGIC_VECTOR (2 downto 0); -- Status bits
+ -- Internal direction port
+ INT_DATAREADY_IN: in STD_LOGIC;
+ INT_DATA_IN: in STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ INT_READ_OUT: out STD_LOGIC;
+ INT_ERROR_IN: in 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);
+ CTRL_BUFFER: in STD_LOGIC_VECTOR (31 downto 0)
+ );
+ end component;
+
+begin
+
+ OBUF : trb_net_obuf
+ port map (
+ CLK => clk,
+ RESET => reset,
+ CLK_EN => '1',
+
+ INT_DATAREADY_IN => int_dataready_in,
+ INT_DATA_IN => int_data_in,
+ INT_READ_OUT => int_read_out,
+ INT_ERROR_IN => (others => '0'),
+ MED_DATAREADY_OUT =>med_dataready_out,
+ MED_DATA_OUT => med_data_out,
+ MED_READ_IN => med_read_in,
+ CTRL_LOCKED => (others => '0'),
+ CTRL_BUFFER => ctrl_buffer,
+ STAT_BUFFER => stat_buffer,
+ STAT_LOCKED => stat_locked
+ );
+
+ clk <= not clk after 10ns;
+ --med_data_in <= (50 downto 48 => read_type, 35 downto 32 => read_f1, others => '0');
+ --med_data_in <= (others => '0');
+ int_data_in(50 downto 48) <= read_type;
+ int_data_in(19 downto 16) <= read_f2;
+ int_data_in(3 downto 0) <= read_f1;
+
+ ctrl_buffer(3 downto 0) <= "0010"; -- just something
+ ctrl_buffer(9 downto 4) <= read_ctrl; -- this is what ibuf provides
+
+
+ DO_RESET : process
+ begin
+ reset <= '1';
+ wait for 30ns;
+ reset <= '0';
+ wait;
+ end process DO_RESET;
+
+ STIMULI: process
+ file protokoll : text open read_mode is "in_obuf.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);
+ variable varx4 : std_logic_vector(5 downto 0);
+ begin
+ wait on CLK;
+
+ if falling_edge(CLK) then
+ wait for 5ns;
+ if (not endfile(protokoll)) then
+ readline(protokoll,myoutline);
+
+ read(myoutline,varx4);
+ read_ctrl <= varx4;
+ read(myoutline,leer);
+
+ read(myoutline,var1);
+ int_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,varx3);
+ read_f1 <= varx3;
+
+ if int_dataready_in = '1' then
+ if int_read_out = '0' then
+ waiter <= '1';
+ wait until int_read_out = '1';
+ wait on CLK;
+ waiter <= '0';
+ end if;
+ wait for 5ns;
+ end if;
+
+ end if;
+ end if;
+ end process STIMULI;
+
+-- int_read_in <= int_dataready_out after 5ns;
+
+READ_BUF: process
+ file protokoll : text open read_mode is "out_obuf.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);
+
+ if var1 = '1' then
+
+ if med_dataready_out = '0' then
+ med_read_in <= '0';
+-- waiter <= '1';
+ wait until med_dataready_out = '1';
+-- waiter <= '0';
+ end if;
+ wait for 5ns;
+ med_read_in <= '1';
+
+ else
+ med_read_in <= '0';
+
+ end if;
+
+ end if;
+ end if;
+ end process;
+
+
+ write_data_out(50 downto 0)<= med_data_out;
+ write_data_out(51) <= '0';
+
+ RESPONSE: process (clk)
+ file protokoll : text open write_mode is "result_out_obuf.txt";
+ variable myoutline : line;
+
+ begin -- process RESPONSE
+ if rising_edge(CLK) and med_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_obuf_testbench_arch;
+
+
+-- fuse -prj trb_net_fifo_testbench_beh.prj -top trb_net_fifo_testbench -o trb_net_fifo_testbench
+
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/trb_net_std.vhd"
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/trb_net_fifo.vhd"
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/xilinx/arch_trb_net_fifo.vhd"
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/xilinx/generic_fifo.vhd"
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/xilinx/generic_shift.vhd"
+-- vhdl work "/home/hadaq/acromag/design/DX2002test/trbnet/trb_net_fifo_testbench.vhd"
+
+-- trb_net_fifo_testbench -tclbatch testsim.tcl
+
+-- ntrace select -o on -m / -l this
+-- ntrace start
+-- run 1000 ns
+-- quit
+
+-- isimwave isimwavedata.xwv
+
--- /dev/null
+-- for a description see HADES wiki
+-- http://hades-wiki.gsi.de/cgi-bin/view/DaqSlowControl/TrbNetOBUF
+
+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_obuf 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_OUT: out STD_LOGIC;
+ MED_DATA_OUT: out STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ MED_READ_IN: in STD_LOGIC;
+ MED_ERROR_OUT: out STD_LOGIC_VECTOR (2 downto 0); -- Status bits
+ -- Internal direction port
+ INT_DATAREADY_IN: in STD_LOGIC;
+ INT_DATA_IN: in STD_LOGIC_VECTOR (50 downto 0); -- Data word
+ INT_READ_OUT: out STD_LOGIC;
+ INT_ERROR_IN: in 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);
+ CTRL_BUFFER: in STD_LOGIC_VECTOR (31 downto 0)
+ );
+END trb_net_obuf;
+
+architecture trb_net_obuf_arch of trb_net_obuf is
+
+ signal current_output_buffer, next_output_buffer : STD_LOGIC_VECTOR (53 downto 0);
+ signal current_ACK_word, current_EOB_word, current_DATA_word :
+ STD_LOGIC_VECTOR (53 downto 0);
+ signal current_DATAREADY_OUT, next_DATAREADY_OUT : STD_LOGIC;
+
+ signal next_SEND_ACK_IN, reg_SEND_ACK_IN : STD_LOGIC;
+ signal sent_ACK, sent_EOB, sent_DATA : STD_LOGIC;
+
+ signal CURRENT_DATA_COUNT, next_DATA_COUNT : STD_LOGIC_VECTOR (15 downto 0);
+ signal max_DATA_COUNT, next_max_DATA_COUNT : STD_LOGIC_VECTOR (15 downto 0);
+ signal TRANSMITTED_BUFFERS, next_TRANSMITTED_BUFFERS : STD_LOGIC_VECTOR (1 downto 0);
+ signal increase_TRANSMITTED_BUFFERS, decrease_TRANSMITTED_BUFFERS : STD_LOGIC;
+
+ signal SEND_BUFFER_SIZE_IN : STD_LOGIC_VECTOR (3 downto 0);
+ signal REC_BUFFER_SIZE_IN : STD_LOGIC_VECTOR (3 downto 0);
+ signal SEND_ACK_IN : STD_LOGIC;
+ signal GOT_ACK_IN : STD_LOGIC;
+
+ type BUFFER_STATE is (BUFFER_IDLE, BUFFER_SEND_ACK, BUFFER_SEND_EOB, BUFFER_SEND_DATA, BUFFER_BLOCKED);
+
+
+ begin
+
+ MED_DATAREADY_OUT <= current_DATAREADY_OUT;
+ MED_DATA_OUT <= current_output_buffer(50 downto 0);
+ MED_ERROR_OUT <= current_output_buffer(53 downto 51);
+
+ decrease_TRANSMITTED_BUFFERS <= '0';
+
+ COMB_NEXT_TRANSFER : process(current_output_buffer, current_DATAREADY_OUT, sent_DATA,
+ MED_READ_IN, current_DATA_word, sent_EOB)
+ begin -- process
+ next_DATAREADY_OUT <= current_DATAREADY_OUT;
+ next_output_buffer <= current_output_buffer;
+ INT_READ_OUT <= '0';
+ increase_TRANSMITTED_BUFFERS <= '0';
+ next_DATA_COUNT <= CURRENT_DATA_COUNT;
+-- EOB should go into the stream
+ if (current_DATAREADY_OUT = '0' and sent_EOB = '1')
+ or (current_DATAREADY_OUT = '1' and sent_EOB = '1' and MED_READ_IN = '1' ) then
+ next_DATAREADY_OUT <= '1';
+ next_output_buffer <= current_EOB_word;
+ next_DATA_COUNT <= (others => '0');
+-- we have something to offer
+ elsif (current_DATAREADY_OUT = '0' and sent_DATA = '1')
+ or (current_DATAREADY_OUT = '1' and sent_DATA = '1' and MED_READ_IN = '1' ) then
+ next_DATAREADY_OUT <= '1';
+ next_output_buffer <= current_DATA_word;
+ INT_READ_OUT <= '1';
+ next_DATA_COUNT <= CURRENT_DATA_COUNT +1;
+-- we will be empty in the next step
+ elsif (current_DATAREADY_OUT = '0' and sent_DATA = '0')
+ or (current_DATAREADY_OUT = '1' and sent_DATA = '0' and MED_READ_IN = '1' ) then
+ next_DATAREADY_OUT <= '0';
+ end if;
+ end process;
+
+
+ REG : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ reg_SEND_ACK_IN <= '0';
+ current_output_buffer <= (others => '0');
+ current_DATAREADY_OUT <= '0';
+ CURRENT_DATA_COUNT <= (others => '0');
+ elsif CLK_EN = '1' then
+ reg_SEND_ACK_IN <= next_SEND_ACK_IN;
+ current_output_buffer <= next_output_buffer;
+ current_DATAREADY_OUT <= next_DATAREADY_OUT;
+ CURRENT_DATA_COUNT <= next_DATA_COUNT;
+ else
+ reg_SEND_ACK_IN <= reg_SEND_ACK_IN;
+ current_output_buffer <= current_output_buffer;
+ current_DATAREADY_OUT <= current_DATAREADY_OUT;
+ CURRENT_DATA_COUNT <= CURRENT_DATA_COUNT;
+ end if;
+ end if;
+ end process;
+
+ -- buffer registers
+ STAT_BUFFER(1 downto 0) <= TRANSMITTED_BUFFERS;
+ STAT_BUFFER(15 downto 2) <= (others => '0');
+ STAT_BUFFER(31 downto 16) <= CURRENT_DATA_COUNT;
+ SEND_BUFFER_SIZE_IN <= CTRL_BUFFER(3 downto 0);
+ REC_BUFFER_SIZE_IN <= CTRL_BUFFER(7 downto 4);
+ SEND_ACK_IN <= CTRL_BUFFER(8);
+ GOT_ACK_IN <= CTRL_BUFFER(9);
+
+ -- build the words and the internal data readys
+ current_ACK_word(TYPE_POSITION) <= TYPE_ACK;
+ current_ACK_word(47 downto 20) <= (others => '0');
+ current_ACK_word(BUFFER_SIZE_POSITION) <= SEND_BUFFER_SIZE_IN;
+ current_ACK_word(15 downto 0) <= (others => '0');
+ current_ACK_word(53 downto 51) <= (others => '0');
+ sent_ACK <= SEND_ACK_IN or reg_SEND_ACK_IN;
+
+ current_EOB_word(TYPE_POSITION) <= TYPE_EOB;
+ current_EOB_word(47 downto 0) <= (others => '0');
+ current_EOB_word(53 downto 51) <= (others => '0');
+ gen_sent_EOB : process (CURRENT_DATA_COUNT, max_DATA_COUNT)
+ begin
+ if (CURRENT_DATA_COUNT = max_DATA_COUNT-1) then
+ sent_EOB <= '1';
+ else
+ sent_EOB <= '0';
+ end if;
+ end process;
+
+ current_DATA_word(50 downto 0) <= INT_DATA_IN;
+ current_DATA_word(53 downto 51) <= INT_ERROR_IN;
+ sent_DATA <= INT_DATAREADY_IN
+ and not TRANSMITTED_BUFFERS(1);
+
+-- generate max_DATA_COUNT, comb. operation which should be registered
+ next_max_DATA_COUNT <= "0000000000000100" when REC_BUFFER_SIZE_IN="0001" else
+ "0000000000001000" when REC_BUFFER_SIZE_IN="0010" else
+ "0000000000010000" when REC_BUFFER_SIZE_IN="0011" else
+ "0000000000100000" when REC_BUFFER_SIZE_IN="0100" else
+ "0000000000000010";
+-- next_max_DATA_COUNT <= 2 ** (REC_BUFFER_SIZE_IN + 1);
+
+ reg_max_DATA_COUNT : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ max_DATA_COUNT <= (1 => '1', others => '0');
+ elsif CLK_EN = '1' then
+ max_DATA_COUNT <= next_max_DATA_COUNT;
+ else
+ max_DATA_COUNT <= max_DATA_COUNT;
+ end if;
+ end if;
+ end process;
+
+
+-- increase and decrease transmitted buffers
+ comb_TRANSMITTED_BUFFERS : process (increase_TRANSMITTED_BUFFERS, decrease_TRANSMITTED_BUFFERS,TRANSMITTED_BUFFERS)
+ begin
+ if (increase_TRANSMITTED_BUFFERS = '1' and decrease_TRANSMITTED_BUFFERS = '0') then
+ next_TRANSMITTED_BUFFERS <= TRANSMITTED_BUFFERS +1;
+ elsif (increase_TRANSMITTED_BUFFERS = '0' and decrease_TRANSMITTED_BUFFERS = '1') then
+ next_TRANSMITTED_BUFFERS <= TRANSMITTED_BUFFERS -1;
+ else
+ next_TRANSMITTED_BUFFERS <= TRANSMITTED_BUFFERS;
+ end if;
+ end process;
+
+ reg_TRANSMITTED_BUFFERS : process(CLK)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ TRANSMITTED_BUFFERS <= "00";
+ elsif CLK_EN = '1' then
+ TRANSMITTED_BUFFERS <= next_TRANSMITTED_BUFFERS;
+ else
+ TRANSMITTED_BUFFERS <= TRANSMITTED_BUFFERS;
+ end if;
+ end if;
+ end process;
+
+end trb_net_obuf_arch;
+