From: hadaq Date: Thu, 31 Aug 2006 12:10:46 +0000 (+0000) Subject: basic obuf working, Ingo X-Git-Tag: oldGBE~781 X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=1761cd1a7565719c953591474c11fbf228cf292f;p=trbnet.git basic obuf working, Ingo --- diff --git a/testbench/trb_net_obuf_testbench.vhd b/testbench/trb_net_obuf_testbench.vhd new file mode 100644 index 0000000..791d4b4 --- /dev/null +++ b/testbench/trb_net_obuf_testbench.vhd @@ -0,0 +1,232 @@ +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 + diff --git a/testbench/trb_net_obuf_testbench_beh.prj b/testbench/trb_net_obuf_testbench_beh.prj new file mode 100644 index 0000000..252339a --- /dev/null +++ b/testbench/trb_net_obuf_testbench_beh.prj @@ -0,0 +1,4 @@ +vhdl work "../trb_net_std.vhd" +vhdl work "../trb_net_fifo.vhd" +vhdl work "../trb_net_obuf.vhd" +vhdl work "trb_net_obuf_testbench.vhd" diff --git a/trb_net_ibuf.vhd b/trb_net_ibuf.vhd index 1f3a69a..cb85a77 100644 --- a/trb_net_ibuf.vhd +++ b/trb_net_ibuf.vhd @@ -249,7 +249,8 @@ reg_locked: process(CLK) -- make STAT_BUFFER - STAT_BUFFER(3 downto 0) <= fifo_depth(3 downto 0); + STAT_BUFFER(3 downto 0) <= fifo_depth(4 downto 1); --divide by 2, since 2 + --buffers have to be stored STAT_BUFFER(7 downto 4) <= current_rec_buffer_size_out; STAT_BUFFER(8) <= reg_eob_out; STAT_BUFFER(9) <= reg_ack_internal; diff --git a/trb_net_obuf.vhd b/trb_net_obuf.vhd new file mode 100644 index 0000000..bf1d38d --- /dev/null +++ b/trb_net_obuf.vhd @@ -0,0 +1,203 @@ +-- 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; +