]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
basic obuf working, Ingo
authorhadaq <hadaq>
Thu, 31 Aug 2006 12:10:46 +0000 (12:10 +0000)
committerhadaq <hadaq>
Thu, 31 Aug 2006 12:10:46 +0000 (12:10 +0000)
testbench/trb_net_obuf_testbench.vhd [new file with mode: 0644]
testbench/trb_net_obuf_testbench_beh.prj [new file with mode: 0644]
trb_net_ibuf.vhd
trb_net_obuf.vhd [new file with mode: 0644]

diff --git a/testbench/trb_net_obuf_testbench.vhd b/testbench/trb_net_obuf_testbench.vhd
new file mode 100644 (file)
index 0000000..791d4b4
--- /dev/null
@@ -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 (file)
index 0000000..252339a
--- /dev/null
@@ -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"
index 1f3a69aa3a967500ea1d05fa17915a4b04f832be..cb85a77466cd901d2791765a8531238d4ba5f796 100644 (file)
@@ -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 (file)
index 0000000..bf1d38d
--- /dev/null
@@ -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;
+