From c5a754a8e9c51c7b663896fda444ee3e2eabfaa3 Mon Sep 17 00:00:00 2001 From: hadaq Date: Fri, 25 Aug 2006 14:08:24 +0000 Subject: [PATCH] ibuf header retransmit and eob logic working, Ingo --- testbench/in_ibuf.txt | 14 ++ testbench/in_ibuf_overflow.txt | 24 ++ testbench/out_ibuf.txt | 12 + testbench/testbench_howto.txt | 21 ++ testbench/trb_net_fifo_testbench_beh.prj | 5 + testbench/trb_net_ibuf_testbench.vhd | 84 +++++-- testbench/trb_net_ibuf_testbench_beh.prj | 6 + trb_net_ibuf.vhd | 265 +++++++++++++++++++++++ trb_net_std.vhd | 6 +- xilinx/trb_net_fifo_arch.vhd | 4 +- 10 files changed, 423 insertions(+), 18 deletions(-) create mode 100644 testbench/in_ibuf.txt create mode 100644 testbench/in_ibuf_overflow.txt create mode 100644 testbench/out_ibuf.txt create mode 100644 testbench/testbench_howto.txt create mode 100644 testbench/trb_net_fifo_testbench_beh.prj create mode 100644 testbench/trb_net_ibuf_testbench_beh.prj create mode 100644 trb_net_ibuf.vhd diff --git a/testbench/in_ibuf.txt b/testbench/in_ibuf.txt new file mode 100644 index 0000000..6e47fed --- /dev/null +++ b/testbench/in_ibuf.txt @@ -0,0 +1,14 @@ +0:000:0000:0000 +0:000:0000:0000 +0:000:0000:0000 +0:000:0000:0000 +1:001:0000:0001 --hdr +1:000:0000:0010 --dat +1:000:0000:0011 --dat +1:000:0000:0100 --dat +1:011:0000:0000 --eob +1:000:0000:0001 --dat +1:000:0000:0010 --dat +1:000:0000:0011 --dat +1:010:0000:0000 --trm +0:000:0000:0000 \ No newline at end of file diff --git a/testbench/in_ibuf_overflow.txt b/testbench/in_ibuf_overflow.txt new file mode 100644 index 0000000..a376624 --- /dev/null +++ b/testbench/in_ibuf_overflow.txt @@ -0,0 +1,24 @@ +0:000:0000 +0:000:0000 +0:000:0000 +0:000:0000 +0:000:0000 +1:100:0000 -- 1:101:0111 -- send ack +1:100:0001 +1:100:0010 +1:100:0011 +1:100:0100 +1:100:0101 +1:100:0110 +1:100:0111 +1:100:1000 +1:100:1001 +1:100:1010 +1:100:1011 +1:100:1100 +1:100:1101 +1:100:1110 +1:100:1111 +1:000:0001 +0:000:0000 +0:000:0000 diff --git a/testbench/out_ibuf.txt b/testbench/out_ibuf.txt new file mode 100644 index 0000000..3841342 --- /dev/null +++ b/testbench/out_ibuf.txt @@ -0,0 +1,12 @@ +1:0 +1:0 +1:0 +1:0 +1:1 -- hdr retransmit +1:0 +1:0 +0:0 -- add waitstates +0:0 +1:0 +1:0 +0:0 \ No newline at end of file diff --git a/testbench/testbench_howto.txt b/testbench/testbench_howto.txt new file mode 100644 index 0000000..9961613 --- /dev/null +++ b/testbench/testbench_howto.txt @@ -0,0 +1,21 @@ +start fuse +fuse -prj trbnet/testbench/trb_net_ibuf_testbench_beh.prj -top trb_net_ibuf_testbench -o trb_net_ibuf_testbench + + +ln -s trbnet/testbench/in_ibuf.txt in_ibuf.txt + + +simulate +trb_net_ibuf_testbench -tclbatch testsim.tcl + +the tcl file could look like this: + +# ntrace select -o on -m /trb_net_ibuf_testbench/IBUF/ -l this +ntrace select -o on -m / -l this +ntrace start +run 500 ns +quit + +isimwave isimwavedata.xwv + +isimwave starts with the full length, change the time above to the ideal time... diff --git a/testbench/trb_net_fifo_testbench_beh.prj b/testbench/trb_net_fifo_testbench_beh.prj new file mode 100644 index 0000000..f4b4462 --- /dev/null +++ b/testbench/trb_net_fifo_testbench_beh.prj @@ -0,0 +1,5 @@ +vhdl work "../trb_net_std.vhd" +vhdl work "../trb_net_fifo.vhd" +vhdl work "../xilinx/trb_net_fifo_arch.vhd" +vhdl work "../xilinx/shift_lut_x16.vhd" +vhdl work "trb_net_fifo_testbench.vhd" diff --git a/testbench/trb_net_ibuf_testbench.vhd b/testbench/trb_net_ibuf_testbench.vhd index fb65f25..c07daa6 100644 --- a/testbench/trb_net_ibuf_testbench.vhd +++ b/testbench/trb_net_ibuf_testbench.vhd @@ -27,9 +27,14 @@ architecture trb_net_ibuf_testbench_arch of trb_net_ibuf_testbench is 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 @@ -84,6 +89,7 @@ begin --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; @@ -102,7 +108,7 @@ begin 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 @@ -111,31 +117,81 @@ begin 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; diff --git a/testbench/trb_net_ibuf_testbench_beh.prj b/testbench/trb_net_ibuf_testbench_beh.prj new file mode 100644 index 0000000..140c2e9 --- /dev/null +++ b/testbench/trb_net_ibuf_testbench_beh.prj @@ -0,0 +1,6 @@ +vhdl work "../trb_net_std.vhd" +vhdl work "../trb_net_fifo.vhd" +vhdl work "../xilinx/trb_net_fifo_arch.vhd" +vhdl work "../xilinx/shift_lut_x16.vhd" +vhdl work "../trb_net_ibuf.vhd" +vhdl work "trb_net_ibuf_testbench.vhd" diff --git a/trb_net_ibuf.vhd b/trb_net_ibuf.vhd new file mode 100644 index 0000000..bc0de5a --- /dev/null +++ b/trb_net_ibuf.vhd @@ -0,0 +1,265 @@ +-- 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; + diff --git a/trb_net_std.vhd b/trb_net_std.vhd index 1679b57..137d384 100644 --- a/trb_net_std.vhd +++ b/trb_net_std.vhd @@ -14,12 +14,14 @@ package trb_net_std is return std_logic; subtype TYPE_POSITION is integer range 50 downto 48; + constant TYPE_DAT : std_logic_vector(2 downto 0) := "000"; constant TYPE_HDR : std_logic_vector(2 downto 0) := "001"; constant TYPE_TRM : std_logic_vector(2 downto 0) := "010"; constant TYPE_EOB : std_logic_vector(2 downto 0) := "011"; - constant TYPE_DAT : std_logic_vector(2 downto 0) := "100"; constant TYPE_ACK : std_logic_vector(2 downto 0) := "101"; - + constant TYPE_ILLEGAL : std_logic_vector(2 downto 0) := "111"; + + subtype F1_POSITION is integer range 47 downto 32; subtype F2_POSITION is integer range 31 downto 16; subtype F3_POSITION is integer range 15 downto 0; diff --git a/xilinx/trb_net_fifo_arch.vhd b/xilinx/trb_net_fifo_arch.vhd index 06c2363..f768a65 100644 --- a/xilinx/trb_net_fifo_arch.vhd +++ b/xilinx/trb_net_fifo_arch.vhd @@ -93,7 +93,7 @@ begin elsif WRITE_ENABLE_IN = '1' and READ_ENABLE_IN = '1' then do_shift_internal <= '1'; next_ADDRESS_SRL <= current_ADDRESS_SRL; - real_ADDRESS_SRL <= current_ADDRESS_SRL - 1; + real_ADDRESS_SRL <= current_ADDRESS_SRL - 2; else do_shift_internal <= '0'; next_ADDRESS_SRL <= current_ADDRESS_SRL; @@ -108,7 +108,7 @@ begin if RESET = '1' then current_DOUT <= (others => '0'); elsif CLK_EN = '1' then - if current_EMPTY = '1' then + if current_EMPTY = '1' or real_ADDRESS_SRL(DEPTH+1) = '1' then current_DOUT <= DATA_IN; else current_DOUT <= next_DOUT; -- 2.43.0