OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.hwp.communication/] [hibi/] [2.0/] [vhd/] [tx_ctrl.vhd] - Rev 159

Go to most recent revision | Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
-- Funbase IP library Copyright (C) 2011 TUT Department of Computer Systems
--
-- This source file may be used and distributed without
-- restriction provided that this copyright statement is not
-- removed from the file and that any derivative work contains
-- the original copyright notice and the associated disclaimer.
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE.  See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.opencores.org/lgpl.shtml
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- File        : tx_control_addr_width_is_1_muxed_fifos.vhdl
-- Description : Control the transmitting of data. Includes
--               the priority arbitration. Config mem gives
--               the start and end times and owners  of time slots.
--
--               This version assumes, muxed fifos, i.e. FSM does no
--               separation between messages and data, it sees only one fifo.
-- Author      : Erno Salminen
-- e-mail      : erno.salminen@tut.fi
-- Project      huuhaa
-- Design      : Do not use term design when you mean system
-- Date        : 11.02.2003
-- Modified    :
--
-- 07.01.03     ES:  Next state of Re_tx_data is always idle!
--              This way there are less problems with reading the fifo
-- 17.03.03     ES: Idle->Write won't work if new addr is coming. Cannot assert
--              fifo read enable in time. consequently, tha same is written
--              twice on the bus
-- 12.04.03     ES: Total_amount, Addr_Amount input ports and Fifo_Depth generic removed
-- 13.04.03     ES: Message stuff removed
--              Constant print_debug added, selects wheteher assertions are
--              used or not
-- 04.03.04     ES: two bugs with target_fifo_full
--              1) target_fifo_full=1 when next addr coming from fifo
--                      => addr stored in data_reg2 and sent as if it was data
--                      => add extra reg for that addr and valid_reg for it
--                      => values stored in them state 'write'
--                      => values read from them when retransfer completes
--                      
--              2) next addr comes from fifo before retransfer is complete
--                      => retransfer goes to 'next addr'
--                      => add one confition to if clause in state idle
--                      (inside else clause 'not own turn')
-- 28.07.2004   ES: cleaning, addr_reg type changed to regular std_logic_vector
-- 03.08.2004   ES: Renamed some states to shorter names. New if-branch inside cfg_d
--                  Added debug_level and Rst_Value for wave form debugging.
--                  Set dbg_level=0 for synthesis.    
-- 13.09.2004   ES: Bug found. When target_fifo_full=1 and addr on the bus, the
--                  addr will be retransferred as addr (ok) and as data also (not
--                  ok). Check addr_valid on state write and assign data_r1 and
--                  data_r2 accordingly
--
-- 15.12.2004   ES names changed
--
-- 03.01.2005   ES retx_addr: check fo full=1 added
-- 14.01.2005      when idle and going to own_slot_reservation, check re
-- 15.01.2005   ES idle->own slot res: lock_out must be 1-
-- 03.02.05     ES  addr_width_g is now in BITS!
-- 07.02.05     ES new generic cfg_re_g
-- 15.05.05     AK A bug when writing every other clock cycle, the data after
--                 the address vanishes. suspicious state: idle 2d. and write_data 4).
--                 corrected, hopefully.
--
-- 13.07.05     AK A bug which reads out an address but doesn't send it when
--                 retransmitting. suspicious state: 1 (under 0a). more
--                 explanation there.
-- ?????????
-- 25.02.2005 Design compiler ei välttämättä syntesoi a_ext-funktiota oikein?
-- 2007/04/18   AK/ES Arbitration type voidaan asettaa ajonaikana 4:ään eri arvoon
-- 2009/07/31   JN Cleanups + keep_slot_g (lock_out = '1' trough whole time slot)
------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
 
 
entity tx_control is
 
  generic (
    counter_width_g : integer := 8;
    id_width_g      : integer := 4;
    id_g            : integer := 1;     -- not neede?
    data_width_g    : integer := 32;    -- in bits
    addr_width_g    : integer := 32;    -- in BITS!
    comm_width_g    : integer := 3;
    n_agents_g      : integer := 0;      -- 2009-04-08
    cfg_re_g        : integer := 0;
    keep_slot_g     : integer := 1      -- 2009-07-31
    );
  port (
    clk   : in std_logic;
    rst_n : in std_logic;
 
    lock_in : in std_logic;
    full_in : in std_logic;  --nyk. data/osoite ei mennyt perille!
 
    cfg_ret_addr_in : in std_logic_vector (addr_width_g-1 downto 0);
    cfg_data_in     : in std_logic_vector (data_width_g-1 downto 0);
    cfg_re_in       : in std_logic;
 
 
    curr_slot_own_in    : in std_logic;
    curr_slot_ends_in   : in std_logic;
    next_slot_own_in    : in std_logic;
    next_slot_starts_in : in std_logic;
    max_send_in         : in std_logic_vector (counter_width_g-1 downto 0);
    n_agents_in         : in std_logic_vector (id_width_g-1 downto 0);
    prior_in            : in std_logic_vector (id_width_g-1 downto 0);
    -- *********************************************************
    -- new ports: Power_Mode and Competition_Type must be added!
    -- *********************************************************
    -- 0 round-robin, 1 priority, 2 combined, 3 dyn_arb (rand)
    arb_type_in         :    std_logic_vector(1 downto 0);
 
    av_in    : in std_logic;
    data_in  : in std_logic_vector (data_width_g-1 downto 0);
    comm_in  : in std_logic_vector (comm_width_g-1 downto 0);
    one_d_in : in std_logic;
    empty_in : in std_logic;
 
    av_out         : out std_logic;
    data_out       : out std_logic_vector (data_width_g-1 downto 0);
    comm_out       : out std_logic_vector (comm_width_g-1 downto 0);
    lock_out       : out std_logic;
    cfg_rd_rdy_out : out std_logic;
    re_out         : out std_logic
    );
 
end tx_control;
 
 
 
 
 
 
architecture rtl of tx_control is
 
 
  constant write_command_c : std_logic_vector (2 downto 0) := "010";  -- 03.02.05
 
 
  -- Selects if debug prints are used ('1') or not ('0')
  constant dbg_level : integer range 0 to 3 := 0;  -- 0= no debug, use 0 for synthesis
 
  -- Registers may be reset to 'Z' to 'X' so that reset state is clearly
  -- distinguished from active state. Using dbg_level+rst_Value array, the rst value may
  -- be easily set to '0' for synthesis.
  constant rst_value_arr : std_logic_vector (6 downto 0) := 'X' & 'Z' & 'X' & 'Z' & 'X' & 'Z' & '0';
 
  -- Combinatorial signals
  -- Own_turn_ends is high when own turn ends, i.e.
  --  * maximum amount of data sent
  --  * own slot ends
  --  * other slot starts
  --  09.01.04: This seems to be in critical path.
  --  If this was register, critical path could be shortened.
  --  On the other hand comparison must be changed to drive register one cycle
  --  earlier than combinatorial signal. 
  signal own_turn_ends  : std_logic;
  signal prior_match    : std_logic;
  signal max_send_limit : std_logic;
 
 
  -- Define type and signals for state machine
  type state_vector is (Idle,
                        Own_Slot_Reservation,
                        Cfg_A, Cfg_D, Cfg_D_Last,
                        Retransfer_Addr, Retransfer_data, Retransfer_Data_Last,
                        Write_Data, Write_Last_Data, Error_State);  
  signal curr_state_r : state_vector;
 
  -- Counters and signals denoting start and end of the competition reservation
  -- Counters do not have to be as wide as data! They generate huge delays
  -- and slow down the whole unit if they are unnecessarily wide!
  signal prior_counter_r : std_logic_vector (id_width_g -1 downto 0);
  signal send_counter_r  : std_logic_vector (counter_width_g -1 downto 0);
 
 
  -- Register, this way the state of the signal 'read enable' can be read
  signal fifo_re_r : std_logic;
 
  signal addr1_r   : std_logic_vector (addr_width_g -1 downto 0);  -- 03.02.05
  signal comm_a1_r : std_logic_vector (comm_width_g -1 downto 0);
 
 
  -- Registers needed to continue interrupted transfer
  -- When transfer is interrupted, addr and either 1 or 2 data has be trasferred
  -- again.
  -- (Actually, only one data is retransferered, but have another may already
  -- been read from fifo but not transferred. This is data referred as
  -- retransferred because it is handled in the sama way as the actually
  -- retransferred. It is stored in data_reg2 )
  -- When state is write_data
  --  * Regular data goes from fifo to output registers
  --  * At the same, it is copied ro register data_Reg2
  --  * At he same time, previously sent data is copied from data2_r to data1_r
  --  data1_r is retransferred after addr (and after that data2_r if needed)
  signal data1_r       : std_logic_vector (data_width_g -1 downto 0);
  signal data2_r       : std_logic_vector (data_width_g -1 downto 0);
  signal comm_d1_r     : std_logic_vector (comm_width_g -1 downto 0);
  signal comm_d2_r     : std_logic_vector (comm_width_g -1 downto 0);
  signal retx_amount_r : integer range 0 to 2;
 
  signal addr_valid_r : std_logic;      -- 13.09.04
 
  -- For storing new addr that comes at the same with full_in=1
  signal addr2_r       : std_logic_vector (addr_width_g -1 downto 0);  -- 03.02.05
  signal comm_a2_r     : std_logic_vector (comm_width_g -1 downto 0);
  signal addr2_valid_r : std_logic;
 
  -- Signals for configuration read operation
  signal cfg_ret_addr_r      : std_logic_vector (addr_width_g-1 downto 0);  -- 03.02.05
  signal cfg_read_value_r    : std_logic_vector (data_width_g-1 downto 0);
  signal cfg_read_complete_r : std_logic;
 
 
 
  -- Muutetaan vertailun tulos reksiteriksi
  -- =>  lyhyempi kriittinen polku (toivottavasti)
  signal max_send_limit_r : std_logic;
 
 
  -- Katsotaan paljonko tulee viivett�t�� menness�
  signal own_turn_ends_r : std_logic;
 
  -- prior+round-robin countteri
  -- after this amount of clock cycles, change the arb type
  constant switch_arb_c    : integer := 4096;
  signal   switch_arb_r    : integer range 0 to switch_arb_c-1;
  signal   arb_type_r      : std_logic_vector(1 downto 0);
  signal   curr_arb_type_r : std_logic_vector(1 downto 0);
 
  -- dynamically adaptive arbitration, enable this for "random arb"
  signal   arb_agent_r      : std_logic_vector(id_width_g-1 downto 0);
--  constant dyn_arb_enable_c : integer := 0;
  constant dyn_arb_enable_c : integer := 1;  -- ES 2009-04-01
 
 
 
  signal dyn_arb_prior       : std_logic_vector(id_width_g-1 downto 0);
  signal prior_counter_arb_r : std_logic_vector(id_width_g-1 downto 0);
 
  component dyn_arb
    generic (
      id_width_g : integer;
      n_agents_g : integer
      );
    port (
      clk           : in  std_logic;
      rst_n         : in  std_logic;
      bus_lock_in   : in  std_logic;
      arb_agent_out : out std_logic_vector(id_width_g-1 downto 0));
  end component;
 
 
begin  -- rtl
 
 
 
  -- Continous assignments to outputs
  cfg_rd_rdy_out <= cfg_read_complete_r;
  re_out         <= fifo_re_r;
  av_out         <= addr_valid_r;       --13.09.04
 
  -- Sendcounterin vertialu on omalla kellojaksollaan
  -- => ei ole en� kriittisell�polulla
  -- Laskurin reset-arvosta riippuu mitk�send_maxit on laillisia
  -- ja l�etet�nk�tarkalleen se m�r�vai pari enemm�, ao. m�r� sis�t�
  -- ekan osoiteen
  -----------------------------------------------------------------------------
  --   Counterin arvot     L�. m�r�    Sallitus max-sendin arvot
  ------------------------------------------------------------------------------
  -- jos counter= 0,1,2  max_s+3 kpl      max_s= 2,3+
  -- jos counter= 1,2,3  max_s+2 kpl      max_s= 2,3+
  -- jos counter= 2,3,4  max_s+1 kpl      max_s= 3,4+
  -- jos counter= 3,4,5  max_s   kpl      max_s= 4,5+
  -- => ei kannata resetoida ainakaan nollaan!
 
 
  max_send_limit <= max_send_limit_r;
 
  check_max_send : process (clk, rst_n)
  begin  -- process check_max_send
    if rst_n = '0' then
      max_send_limit_r <= '0';
 
      own_turn_ends_r <= '0';
 
    elsif clk'event and clk = '1' then
 
      if (max_send_in (counter_width_g-1 downto 0) = send_counter_r
          or max_send_in = conv_std_logic_vector (0, data_width_g)
          or max_send_in = conv_std_logic_vector (1, data_width_g))
      then
 
        if (curr_slot_own_in = '1'
            or (next_slot_starts_in = '1' and next_slot_own_in = '1')) then
          max_send_limit_r <= '0';
        else
          max_send_limit_r <= '1';
        end if;
 
      else
        max_send_limit_r <= '0';
      end if;
 
      own_turn_ends_r <= own_turn_ends;
 
    end if;
  end process check_max_send;
 
 
 
  -- 2) COMB PROC
  -- Check if priority matches so that competition reservation may start
  Check_Prior : process (prior_in, prior_counter_r)
  begin  -- process Check_Send_Limit
    if prior_counter_r = prior_in (id_width_g-1 downto 0) then  --22.01.03
      prior_match <= '1';
    else
      prior_match <= '0';
    end if;
  end process Check_Prior;
 
 
 
  -- 3) PROC (ASYNC)
  -- Check if bus reservation must be ended
  -- Own turn ends, if
  -- * max amount data already transferred
  -- * or own slot ends
  -- * or some other wrapper's slot starts
  -- When Own_turn_ends=1, wrapper can transfer one value
  Check_Turn : process (max_send_limit,
                        curr_slot_own_in, curr_slot_ends_in,
                        next_slot_own_in, next_slot_starts_in)
  begin  -- process Check_Turn
    if max_send_limit = '1'
      or ((curr_slot_own_in = '1' and curr_slot_ends_in = '1')
          or (next_slot_own_in = '0' and next_slot_starts_in = '1'))then
      own_turn_ends <= '1';
    else
      own_turn_ends <= '0';
    end if;
  end process Check_Turn;
 
 
 
  -- 4) SEQ PROC
  -- Count how many data has been transferred
  -- Counter is not incremented, if
  -- * wrapper is not trasferring
  -- * wrapper has a time slot
  -- * wrapper is finishing transfer
  Count_Sent_Items : process (clk, rst_n)
  begin  -- process Count_Sent_Items
    if rst_n = '0' then                 -- asynchronous reset (active low)
      send_counter_r <= (others => '0');
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      if curr_state_r = Idle
        or curr_slot_own_in = '1'
        or curr_state_r = Write_Last_Data
        or curr_state_r = Retransfer_Data_Last
        or curr_state_r = Cfg_D_Last then
 
        send_counter_r <= (others => '0');
 
        send_counter_r(1) <= '1';       -- 12.12.05 reset to 0x002
        send_counter_r(0) <= '1';       -- 12.12.05 reset to 0x001
 
 
        -- Counter should be incremented already when moving from idle to
        -- some write state (Write_Data / Cfg_A / Retransfer_Addr)!
        -- At the moment, counter is started one clock cycle too late
        -- => send_max+1 data will be transferred
        -- 31.07 can this be fixed, if counter was reset to 1
 
        else
 
        if curr_slot_own_in = '1'
          or (next_slot_starts_in = '1' and next_slot_own_in = '1') then
          send_counter_r <= (others => '0');
        else
          send_counter_r <= send_counter_r +1;
        end if;  -- curr_slot_own_in
      end if;  -- Curr_State
    end if;  -- rst_n/clk'event
  end process Count_Sent_Items;
 
 
 
 
 
  -- 5) SEQ PROC
  Define_output : process (clk, rst_n)
    variable lock_v : std_logic;
  begin  -- process Define_output
 
    if rst_n = '0' then
      lock_out     <= '0';
      addr_valid_r <= '0';
      comm_out     <= (others => '0');
      data_out     <= (others => '0');
 
      data1_r       <= (others => rst_value_arr (dbg_level* 1));
      data2_r       <= (others => rst_value_arr (dbg_level* 1));
      comm_d1_r     <= (others => rst_value_arr (dbg_level* 1));
      comm_d2_r     <= (others => rst_value_arr (dbg_level* 1));
      addr1_r       <= (others => rst_value_arr (dbg_level* 1));
      addr2_r       <= (others => rst_value_arr (dbg_level* 1));
      comm_a1_r     <= (others => rst_value_arr (dbg_level* 1));
      comm_a2_r     <= (others => rst_value_arr (dbg_level* 1));
      addr2_valid_r <= '0';
 
      fifo_re_r           <= '0';
      cfg_read_complete_r <= '1';
      cfg_read_value_r    <= (others => rst_value_arr (dbg_level* 1));
      cfg_ret_addr_r      <= (others => rst_value_arr (dbg_level* 1));
 
      retx_amount_r <= 0;
      curr_state_r  <= Idle;
 
    elsif clk'event and clk = '1' then
      -- checks that the command is being fed with data.
      assert (empty_in = '1' or (empty_in = '0' and comm_in /= "000")) report "Comm warning! idle from FIFO" severity error;
 
 
      -- default value, just in case..
      lock_v := '0';
 
      -- Control the configuration registers
      -- Read conf value from conf mem to register
 
      if cfg_re_g = 1
        and cfg_re_in = '1' then
 
        cfg_ret_addr_r      <= cfg_ret_addr_in;
        cfg_read_value_r    <= cfg_data_in;
        cfg_read_complete_r <= '0';
      else
 
        if curr_state_r = Cfg_D_Last
          or curr_state_r = Cfg_D then
 
          if full_in = '0' then
            -- Answering to conf read succeeded
            cfg_read_complete_r <= '1';
          else
            -- Answering did not succeed
            cfg_read_complete_r <= '0';
 
            assert dbg_level < 2 report "Conf (Last) D : Ei onnistunut" severity note;
 
          end if;
        end if;
      end if;
 
 
 
 
      -- Control other registers
      -- Register values are updated when state changes
      -- (i.e. the assigment clause is in the previous state in the code)
      -- => e.g. addr is written when moving idle->Retransfer_Addr
      -- => when state=Retransfer_Addr :
      --    *  bus=addr and data_out_reg <= next data
      case curr_state_r is
 
 
 
        --++++++++++++++        
        when Idle =>
 
 
          -- (0a Something to transmit, own turn not ending
          --  0b Nothing to do)
 
          -- 1) Own time slot starts
          -- 2) Competition 
          --    2a) Re_transmit
          --    2b) Answer conf read
          --    2c) New addr+data
          --    2d) New addr but no data, stop. Remove this branch?
          --    2e) New data, use old addr
          --    2f) Illegal?
          -- 3) Not own turn
          --
 
          if own_turn_ends = '0'
            and (empty_in = '0'
                 or (cfg_re_g = 1 and cfg_read_complete_r = '0')
                 or retx_amount_r /= 0) then
            -- 0a)
 
            if next_slot_own_in = '1' and next_slot_starts_in = '1' then
              -- 1) Own time slot starts
              lock_v       := '1';
              addr_valid_r <= '0';
              addr_valid_r <= '0';
              data_out     <= (others => '0');
              comm_out     <= (others => '0');
 
              assert false report "????????????????????????????????????????" severity warning;
              assert false report "tx_ctrl/idle: Suspicious if-elsif branch (own slot starts)" severity warning;
 
              if (fifo_re_r = '0'
                  and retx_amount_r = 0
                  and empty_in = '0' and av_in = '1' and one_d_in = '1') then
                fifo_re_r    <= '1';            -- 02.06.06 es
                addr1_r      <= data_in (addr_width_g -1 downto 0);  -- 02.06.06 es
                comm_a1_r    <= comm_in;        -- 02.06.06 es
                curr_state_r <= idle;           -- 05.06.2006
                assert dbg_level < 1 report "idle : oma aikaslotti alkaa, mutta vain 1 osoite fifossa" severity note;
 
              elsif (fifo_re_r = '0'
                     and retx_amount_r = 0
                     and empty_in = '0' and av_in = '1' and one_d_in = '0') then
                -- 05.06.06 es
                fifo_re_r    <= '1';
                addr1_r      <= data_in (addr_width_g -1 downto 0);
                comm_a1_r    <= comm_in;
                curr_state_r <= Own_Slot_Reservation;
                assert dbg_level < 1 report "idle : oma aikaslotti alkaa, 05.06.2006 Brand new!" severity note;
 
              else
                fifo_re_r    <= '0';
                assert dbg_level < 1 report "idle : oma aikaslotti alkaa +re = 0" severity note;
                curr_state_r <= Own_Slot_Reservation;
              end if;
 
              -- Why did we read out the address? it wasn't even stored anywhere.
              -- It seems that address needs to be read in some cases, but in some
              -- it must not be! The bug can be seen in the tx control testbench.
              -- However, simply setting fifo_re_r <= '0'; doesn't solve the problems;
              -- it causes more.
              -- Bug was discovered with video system, where (erratically) n_time_slots
              -- was one although timeslots are not used.
              -- 13.7.05 AK
              assert false report "????????????????????????????????????????" severity warning;
 
 
            elsif (next_slot_starts_in = '0' and prior_match = '1'
              and (lock_in = '0')) or (keep_slot_g = 1 and curr_slot_own_in = '1')
            then
              -- 2) Competition
              -- Note: Order. 1) retx, 2) cfg and so on
 
              -- Note! 21.01.2003
              -- Comparison (lock_in = '1' and full_in = '1') caused
              -- problems, when receiver asserts full=1 during addr phase.
              -- (Receiver _should_ assert target_full only during data phase but
              -- you never know)
              -- Then trasmitter puts data on the bus but the next wrapper may
              -- put its own addr on the at same time => conflict
 
              assert dbg_level < 3 report "Kilpailuvuoro" severity note;
 
 
 
              if retx_amount_r /= 0 then
                -- 2a) Receiver got full last time
                curr_state_r                       <= Retransfer_Addr;
                addr_valid_r                       <= '1';
                data_out                           <= (others => '0');  -- 01.03.05
                data_out (addr_width_g-1 downto 0) <= addr1_r;  -- 01.03.05
                comm_out                           <= comm_a1_r;
                lock_v                             := '1';
                fifo_re_r                          <= '0';
 
                assert dbg_level < 3 report "Idle : uusiolahetys" severity note;
 
 
 
                -- 25.01.05 elsif cfg_read_complete_r = '0' then
              elsif cfg_re_g = 1 and cfg_read_complete_r = '0' then
                -- 2b) Conf read has not been yet answered
                -- Answered conf values don't have to be stored in addr_reg/data_reg
                curr_state_r                       <= Cfg_A;
                addr_valid_r                       <= '1';
                data_out                           <= (others => '0');  -- 01.03.05
                data_out (addr_width_g-1 downto 0) <= cfg_ret_addr_r;  -- 01.03.05
                comm_out                           <= write_command_c;  -- 03.02.05
                lock_v                             := '1';
                fifo_re_r                          <= '0';
 
                assert dbg_level < 3 report "idle : vastataan konf. lukuun" severity note;
 
 
--              elsif (empty_in = '0' and av_in = '1' and one_d_in = '0') then
                -- 2c) New addr and data
 
--                assert dbg_level < 3 report "idle : uusi osoite" severity note;
 
                -- Take the safe way, stay in idle until addr is read from the
                -- fifo 17.03.03
--                curr_state_r <= Idle;
--                addr_valid_r <= '0';
--                data_out     <= (others => '0');
--                comm_out     <= (others => '0');
--                lock_v       := '0';
 
--                fifo_re_r    <= '0';
 
                -- AK 12.05.05
              elsif (empty_in = '0' and av_in = '1') then -- and one_d_in = '1') then
                -- 2d) Only new addr but no data
                curr_state_r <= Idle;
                addr_valid_r <= '0';
                comm_out     <= (others => '0');
                data_out     <= (others => '0');
                lock_v       := '0';
 
                -- 13.05.2005 ES
                if fifo_re_r = '0' then
                  addr1_r   <= data_in (addr_width_g -1 downto 0);  -- 03.02.05
                  comm_a1_r <= comm_in;
                  fifo_re_r <= '1';
                else
                  fifo_re_r <= '0';
                end if;
 
 
 
                assert dbg_level < 3 report "idle : pelkastaan uusi osoite (ei laheteta)" severity note;
 
 
              elsif (empty_in = '0' and av_in = '0') then
                -- 2e) Data coming from fifo
                -- Transfer previous addr again
                curr_state_r                       <= Retransfer_Addr;
                addr_valid_r                       <= '1';
                data_out                           <= (others => '0');  -- 01.03.05
                data_out (addr_width_g-1 downto 0) <= addr1_r;  -- 01.03.05
                comm_out                           <= comm_a1_r;
                lock_v                             := '1';
                fifo_re_r                          <= '1';  
                assert dbg_level < 3 report "idle : ed data jatkuu" severity note;
 
 
              else
                -- 2f) Illegal (?) branch
                curr_state_r <= Error_State;
                -- 22.07 Actually this branch may be reached if fifo has one addr
                -- but no data
                addr_valid_r <= '0';
                data_out     <= (others => '0');
                comm_out     <= (others => '0');
                lock_v       := '0';
 
                assert false report "Idle => Error_state" severity error;
                assert av_in = '1' report "AV on 0" severity note;
                assert av_in = '0' report "AV on 1" severity note;
                assert empty_in = '1' report "empty_in on 0" severity note;
                assert empty_in = '0' report "empty_in on 1" severity note;
                assert one_d_in = '1' report "one_d_in on 0" severity note;
                assert one_d_in = '0' report "one_d_in on 1" severity note;
 
 
              end if;  -- re_tx_amount
 
            else
              -- 3) Not own turn
              curr_state_r <= Idle;
              addr_valid_r <= '0';
              data_out     <= (others => '0');
              comm_out     <= (others => '0');
              lock_v       := '0';
              assert dbg_level < 3 report "Idle : Odotetaan omaa vuoroa" severity note;
 
 
              -- Read addr already before own turn  19.07 es
              -- Keep RE=1 only for one cycle
              -- Assure that addr_reg is not reserved, i.e. retransfer is completed
              if empty_in = '0'
                and retx_amount_r = 0   -- 04.03.04
                and av_in = '1'
                and fifo_re_r = '0' then
 
                assert dbg_level < 3 report "Idle : luetaan datafifosta osoite valmiiksi" severity note;
 
 
                fifo_re_r <= '1';
                addr1_r   <= data_in (addr_width_g-1 downto 0);  -- 03.02.05
                comm_a1_r <= comm_in;
              else
                fifo_re_r <= '0';
              end if;
            end if;  --next_slot_own_in etc.
 
 
          else
            -- 0b) Nothing to do :
            -- * target did not get on previous transfer
            -- * conf read has been answered
            -- * no data to send
            -- * not possible to start on turn (e.g. send_max = 0)
 
            curr_state_r <= Idle;
            addr_valid_r <= '0';
            comm_out     <= (others => '0');
            data_out     <= (others => '0');
            fifo_re_r    <= '0';
            lock_v       := '0';
 
            assert dbg_level < 3 report "Ei ole mitaan sanottavaa kenellekaan" severity note;
 
          end if;  --own_turn & (empty_in or Cfg_Read or Re_tx_Amount)
 
 
 
 
 
          --++++++++++++++
        when Own_Slot_Reservation =>
          -- Always move forward from this state. This state lasts only for one cycle
          -- By default, reserve bus and write addr
          lock_v       := '1';
          addr_valid_r <= '1';
 
          -- Note: Order
          -- 0. Own turn ends before it starts. Aargh.
          -- 1. retransfer
          -- 2. answering conf read
          -- 3. data
          --  3a) New addr and data
          --  3b) New data, use old addr
          -- 4) 
 
          if own_turn_ends = '1' then
            -- 0) Own turn ends before it starts. Aargh.
            curr_state_r <= Idle;
            addr_valid_r <= '0';
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            lock_v       := '0';
            fifo_re_r    <= '0';
 
            assert dbg_level < 1 report "Own slot : VUORO LOPPUU ENNEN KUIN ALKAAKAAN!" severity note;
 
          elsif retx_amount_r /= 0 then
            -- 1) Receiver got full on previous transfer, try again
            curr_state_r                       <= Retransfer_Addr;
            data_out                           <= (others => '0');  -- 01.03.05
            data_out (addr_width_g-1 downto 0) <= addr1_r;          -- 01.03.05
            comm_out                           <= comm_a1_r;
            fifo_re_r                          <= '0';
            assert dbg_level < 3 report "Own slot : uusiolahetys" severity note;
 
 
          elsif cfg_re_g = 1 and cfg_read_complete_r = '0' then
            -- 2) Not yet answered to conf read 
            curr_state_r                       <= Cfg_A;
            data_out                           <= (others => '0');  -- 01.03.05
            data_out (addr_width_g-1 downto 0) <= cfg_ret_addr_r;   -- 01.03.05
            comm_out                           <= write_command_c;  -- 03.02.05 
            fifo_re_r                          <= '0';
            assert dbg_level < 3 report "Own slot : conf return addr" severity note;
 
          elsif (empty_in = '0' and av_in = '1' and one_d_in = '0') then
            -- 3a) New addr and data
            curr_state_r <= Write_Data;
            data_out     <= data_in;
            comm_out     <= comm_in;
            addr1_r      <= data_in(addr_width_g-1 downto 0);  -- 17.02
            comm_a1_r    <= comm_in;
            fifo_re_r    <= '1';
 
            assert dbg_level < 1 report "Own slot : uusi osoite+dataa." severity note;
 
 
          elsif av_in = '0' and empty_in = '0' then
            -- 3b) New data, use old addr
            curr_state_r                       <= Retransfer_Addr;
            data_out                           <= (others => '0');  -- 01.03.05
            data_out (addr_width_g-1 downto 0) <= addr1_r;          -- 01.03.05
            comm_out                           <= comm_a1_r;
            fifo_re_r                          <= '1';
 
            assert dbg_level < 1 report "Own slot : Ed data jatkuu" severity note;
 
 
          else
            -- 4) Illegal branch
            assert false report "Own slot => Error_state" severity error;
 
 
            curr_state_r <= Error_State;
            addr_valid_r <= '0';
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            lock_v       := '0';
            fifo_re_r    <= '0';
          end if;  --retx_amount_r /= 0
 
 
 
          --++++++++++++++
 
        when Cfg_A =>
          -- Return addr of conf read already transferred, write conf value now
          -- It is not possible to have Target_Full=1, is it?
          -- HUOM! 25.11.04 TK: ainakin mina sain alla olevan tulostuksen
          -- tb_tx_rx -testipenkilla aikaiseksi... 
 
          if cfg_re_g = 1 then
            -- if added 25.01.05
 
            assert not(dbg_level > 0 and full_in = '1') report "tx_ctrl:cfg_a TargetFull=1 unexpectedly" severity warning;
 
 
            if own_turn_ends = '1' or empty_in = '1' then
              curr_state_r <= Cfg_D_Last;
              lock_v       := '0';
              assert dbg_level < 3 report "Conf A : Lopetellaan, (seur Last Conf D)" severity note;
            else
              curr_state_r <= Cfg_D;
              lock_v       := '1';
              assert dbg_level < 3 report "Conf A : Jatketaan, (seur Conf D)" severity note;
            end if;
 
            --!!!!!!!!!
            -- 19.12.2005
            -- Data_out comes from cfg_mem
            --!!!!!!!!!
 
 
            addr_valid_r <= '0';
            data_out     <= cfg_read_value_r;  -- 19.12.2005 
            comm_out     <= write_command_c;
            fifo_re_r    <= '0';
 
            if (empty_in = '0' and av_in = '1') then  -- and one_d_in = '0') then
              fifo_re_r <= '1';
              addr1_r   <= data_in (addr_width_g -1 downto 0);
              comm_a1_r <= comm_in;
            else
              fifo_re_r <= '0';
            end if;
            -- else not needed ?            
          end if;  --cfg_re_g = 1
          --++++++++++++++
 
 
        when Cfg_D =>
          -- Conf read answered
          -- 1) Not success
          -- 2) Success but own turn ends
          -- 3) Success + own turn continues
          --  3a) New addr+data
          --  3b) Only new addr, no data, This added 03.08.2004
          --  3c) New data (use old addr)
          -- 4)
 
          if cfg_re_g = 1 then
            -- if added 25.01.05
 
 
            if full_in = '1' then
              -- 1) Answering to conf read did not succeed because receiver got full
              -- Config registers are controlled outside of "switch Curr_State"
              -- so nothing has to be done here
              curr_state_r <= Idle;
              lock_v       := '0';
              addr_valid_r <= '0';
              data_out     <= (others => '0');
              comm_out     <= (others => '0');
              fifo_re_r    <= '0';
              assert dbg_level < 3 report "Conf D : Lopetellaan koska kohde taysi, (seur idle)" severity note;
 
 
            elsif own_turn_ends = '1' then
              -- 2) Cannot continue transferring data after conf value
              curr_state_r <= Idle;
              lock_v       := '0';
              addr_valid_r <= '0';
              data_out     <= (others => '0');
              comm_out     <= (others => '0');
              fifo_re_r    <= '0';
              assert dbg_level < 3 report "Conf D : Oma vuoro loppuu, (seur idle)" severity note;
 
            else
              -- 3) Answering conf read succeeded and own turn continues
 
 
              -- If-structure totally new 03.08.2004
              if empty_in = '0' then
                if av_in = '1' then
                  -- New addr
                  if one_d_in = '0' then
                    -- 3a) Also new data                  
                    curr_state_r <= Write_Data;
                    addr_valid_r <= '1';
                    data_out     <= data_in;
                    comm_out     <= comm_in;
                    lock_v       := '1';
                    addr1_r      <= data_in (addr_width_g -1 downto 0);
                    comm_a1_r    <= comm_in;
                    fifo_re_r    <= '1';
                    assert dbg_level < 1 report "Conf D   : Valmis. Seur uuden datan osoite" severity note;
                    assert dbg_level < 2 report "31.03.03 : Tuleeko osoite yhden kerran vai kahdesti vaylalle??" severity note;
 
                  else
                    -- 3b) Addr only, stop tx                  
                    curr_state_r <= Idle;
                    addr_valid_r <= '0';
                    data_out     <= (others => '0');
                    comm_out     <= (others => '0');
                    lock_v       := '0';
                    fifo_re_r    <= '0';
                  end if;  -- one_d
 
                else
                  -- 3c) New data, use old addr
                  -- i.e. empty=0 and av=0 
                  curr_state_r                       <= Retransfer_Addr;
                  addr_valid_r                       <= '1';
                  data_out                           <= (others => '0');  -- 01.03.05
                  data_out (addr_width_g-1 downto 0) <= addr1_r;  -- 01.03.05
                  comm_out                           <= comm_a1_r;
                  lock_v                             := '1';
                  fifo_re_r                          <= '1';
                  assert dbg_level < 3 report "Conf D                : Valmis. Ed datan osoite uudestaan" severity note;
                  assert dbg_level < 0 report "Conf D - > retx_a     : re = 1. Correct? " severity note;
                  assert retx_amount_r < 1 report "Conf D - > retx_a : retx_amount_r > 0 " severity note;
 
 
                end if;  -- av
 
              else
                -- 4) No data, stop tx
                curr_state_r <= Idle;
                addr_valid_r <= '0';
                data_out     <= (others => '0');
                comm_out     <= (others => '0');
                lock_v       := '0';
                fifo_re_r    <= '0';
              end if;  -- empty
            end if;  -- target_Fifo_Full
          end if;  -- cfg_re_g=1?           
 
 
 
          --++++++++++++++
        when Cfg_D_Last =>
          -- Last cycle of own turn.
          -- Checking whether the conf read answer succeeded is
          -- done elsewhere
 
          if cfg_re_g = 1 then
 
 
            curr_state_r <= Idle;
            addr_valid_r <= '0';
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            lock_v       := '0';
            addr1_r      <= addr1_r;
            comm_a1_r    <= comm_a1_r;
            fifo_re_r    <= '0';
          end if;  -- cfg_re_g=1?           
 
 
 
 
          --++++++++++++++
        when Retransfer_Addr =>
          -- At the moment, retransferred addr is on the bus
          -- write data now
 
          -- 1) Addr retransferrred, next data comes from fifo
          --    1a) Own turn ends, write one data
          --    1b) Own turn continues
          --        1ba) Only data in fifo
          --        1bb) ??? 
          -- 2) At least 1 data must be retransferred
          --    2a) Own turn ends, write r1 and stop
          --    2b) Own turn continues, write r1
 
          addr_valid_r <= '0';
 
          -- Check for full=1 added 03.01.2005, ES
          -- This probably caused the Stratix problem with 2*Nios+Sdram
          if full_in = '1' then
 
            curr_state_r <= Idle;
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            lock_v       := '0';
            fifo_re_r    <= '0';
 
            if fifo_re_r = '1' then
              -- better condition would be retx_amount_r /= 0, perhaps, 28.02.2006
              retx_amount_r <= 1;
              data1_r       <= data_in;
              comm_d1_r     <= comm_in;
            end if;  -- fifo_re_r
 
 
 
 
          else
            -- code inside thi else-branch is the original code (before 03.01.2005)
 
            if retx_amount_r = 0 then
              -- 1) No data has to be retransferred, next data comes from fifo
              retx_amount_r <= 0;
              addr_valid_r  <= '0';
 
              if own_turn_ends = '1' then
                -- 1a) Own turn ends, write one data and then stop
                curr_state_r <= Write_Last_Data;
                data_out     <= data_in;
                comm_out     <= comm_in;
                lock_v       := '0';
                fifo_re_r    <= '0';
                assert dbg_level < 3 report "re tx A : 1 data ja lopetetaan" severity note;
 
                data2_r   <= data_in;
                comm_d2_r <= comm_in;
 
              else
                -- 1b) Own turn continues
                data_out  <= data_in;
                comm_out  <= comm_in;
                data2_r   <= data_in;
                comm_d2_r <= comm_in;
                assert dbg_level < 3 report "re tx A : Jatketaan datalla" severity note;
 
                if one_d_in = '1' and av_in = '0' then
                  -- 1ba) One data left in the fifo, write that and stop
                  curr_state_r <= Write_Last_Data;
                  lock_v       := '0';
                  fifo_re_r    <= '0';  --'1' 31.03.03
 
                  assert dbg_level < 3 report "ReTx_A => Write_last_Data, re <= 0" severity note;
 
 
                else
                  -- 1bb) More than one data (or data+addr etc) in fifo
                  curr_state_r <= Write_Data;
                  lock_v       := '1';
                  fifo_re_r    <= '1';
 
                  assert empty_in = '0' report "ReTx_A : fifossa ei lahetettavaa! APUVA" severity error;
                end if;  -- end 1_d && av
 
              end if;  --own_turn_ends =1
 
            else
              -- 2) At the moment retx_amount_r /= 0
              -- Has to transfer at least one data again
              -- retx_amount_r = 1 or 2
 
              -- send data from reg1 first
              addr_valid_r <= '0';
              data_out     <= data1_r;
              comm_out     <= comm_d1_r;
              fifo_re_r    <= '0';
 
              -- 'Decrement' retx_amount_r
              if retx_amount_r = 1 then
                retx_amount_r <= 0;
              else
                retx_amount_r <= 1;
              end if;
 
 
              if own_turn_ends = '1' then
                -- 2a) Write one data and stop
                curr_state_r <= Retransfer_Data_Last;
                lock_v       := '0';
                assert dbg_level < 3 report "re tx A => re tx D last" severity note;
              else
                -- 2b) Own turn continues
                curr_state_r <= Retransfer_Data;
                lock_v       := '1';
                assert dbg_level < 3 report "re tx A => re tx D" severity note;
              end if;
 
            end if;  --retx_amount_r
 
 
 
          end if;
 
 
          -- State Retransfer_Addr ends ------------------------------------
 
 
 
 
 
          --++++++++++++++
        when Retransfer_Data =>
          -- At the moment, bus data equals to
          --  * reg1, if prev state was ReTx_Addr
          --  * reg2, if prev state was ReTx_Data
 
          -- If writing succeeded, then
          -- max. 1 data (=reg2) has to be retransferred
 
 
          -- 1) target_Full
          -- 2) target not full
          --   2a) Own turn ends
          --       2aa) Retransfer complete, end turn
          --       2ab) Still r2 to retransfer and then end turn
          --   2b) Own turn continues
          --       2ba) Retransfer complete
          --            2baa) Answer cfg read
          --            2bab) Safe way: go to idle
          --       2bb) Retransfer r2    
 
          if full_in = '1' then
            -- 2) Retransfer did not succeed
            curr_state_r <= Idle;
            addr_valid_r <= '0';
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            lock_v       := '0';
            fifo_re_r    <= '0';
 
            -- 'increment' retx_amount_r back to previous value
            -- No other action is needed, because re_transfer registers
            -- keep their values
            if retx_amount_r = 1 then
              retx_amount_r <= 2;
              assert dbg_level < 2 report "ReTxD : Target full. Retransmit 2" severity note;
            else
              retx_amount_r <= 1;
              assert dbg_level < 2 report "ReTxD : Target full. Retransmit 1" severity note;
            end if;
 
 
          else
            -- Retransfer success
            -- => data2_r has be retransferred if anything
            retx_amount_r <= 0;
 
            if own_turn_ends = '1' then
              -- 2a) Retransfer succes but cannot continue
              lock_v := '0';
 
              if retx_amount_r = 0 then
                -- 2aa) Data currently on the bus was the last one to retransfer
                -- Cannot do anything because own turn ends
                curr_state_r <= Idle;
                addr_valid_r <= '0';
                data_out     <= (others => '0');
                comm_out     <= (others => '0');
 
                assert dbg_level < 3 report "ReTxD =>  idle: Turn ends" severity note;
 
 
                -- 04.03.04             --------------------------------------------------
                if addr2_valid_r = '1' then
                  -- Take addr from extrapextra register into use
                  addr1_r       <= addr2_r;
                  comm_a1_r     <= comm_a2_r;
                  addr2_valid_r <= '0';
                end if;
                -- 04.03.04 ends        ----------------------------------------------
 
              else
                -- 2ab) Still data2_r to retransfer and after that own turn is ends
                curr_state_r <= Retransfer_Data_Last;
                addr_valid_r <= '0';
                data_out     <= data2_r;
                comm_out     <= comm_d2_r;
                data1_r      <= data2_r;
                comm_d1_r    <= comm_d2_r;
 
 
                assert dbg_level < 3 report "ReTxD => ReTx_D_Last : Turn ends" severity note;
 
              end if;  --retx_amount_r
 
 
            else
              -- 2b) This else branch Belongs to "if own_turn_ends = '1'"
              -- Retransfer success and own turn continues
 
              if retx_amount_r = 0 then
                -- 2ba) Data currently on the bus was the last one to retransfer
 
                -- Orig     : Select next state: either Write_D or Conf_A
                -- 07.01.03 : Always go to idle because it simplifies things.
                --            Performance loss is considered negligible (es) 
 
 
                -- 04.03.04             ---------------------------------------------------
                if addr2_valid_r = '1' then
                  -- Take addr from extrapextra register into use
                  addr1_r       <= addr2_r;
                  comm_a1_r     <= comm_a2_r;
                  addr2_valid_r <= '0';
                end if;
 
                -- 04.03.04 ends        ----------------------------------------------
 
 
                -- 25.01.05 if cfg_read_complete_r = '0' then
                if cfg_re_g = 1 and cfg_read_complete_r = '0' then
                  -- 2baa) Nothing to retransfer, but conf read is not yet answered
 
                  -- 07.01.03 Take the safe way, go to Idle
                  curr_state_r <= Idle;
                  lock_v       := '0';
                  fifo_re_r    <= '0';
                  addr_valid_r <= '0';
                  data_out     <= (others => '0');
                  comm_out     <= (others => '0');
 
                  assert dbg_level < 3 report "ReTxD =>  (Conf_Read_A) _idle_" severity note;
 
 
                else
                  -- 2bab) nothing to retransfer and conf read is answered
 
                  -- 07.01.03  Take the safe way, go to Idle
                  curr_state_r <= Idle;
                  lock_v       := '0';
                  data_out     <= (others => '0');
                  comm_out     <= (others => '0');
                  fifo_re_r    <= '0';
 
                  assert dbg_level < 3 report "ReTxD => (write) _idle_" severity note;
 
                end if;  -- cfg_read_complete_r
 
              else
                -- 2bb) Else branch to "if retx_amount_r = 0 then"
                -- means that retx_amount_r > 0
                -- => data2_r has to be retransferred
                -- 31.03.03
                curr_state_r <= Retransfer_Data;  --keep this state for one more cycle
                addr_valid_r <= '0';
                data_out     <= data2_r;
                comm_out     <= comm_d2_r;
                lock_v       := '1';
 
                data1_r   <= data2_r;
                comm_d1_r <= comm_d2_r;
                fifo_re_r <= '0';       -- vaihdettu 07.01.03 oli '1';
 
                assert dbg_level < 3 report "ReTxD => ReTx_D, write reg2 to bus" severity note;
 
 
              end if;  -- retx_amount_r = 0
            end if;  -- own_turn_ends
          end if;  -- full_in
          -- State Retransfer_Data ends --------------------------------------
 
 
 
 
          --++++++++++++++
        when Retransfer_Data_Last =>
          -- Last cycle of own turn
          -- Currently, bus data = retransferred data
          --  a) data1_r, (amount=1)
          --  b) data2_r, (amount=0)
 
          curr_state_r <= Idle;
          addr_valid_r <= '0';
          data_out     <= (others => '0');
          comm_out     <= (others => '0');
          lock_v       := '0';
 
          -- Check if the receiver accepted data
          if full_in = '1' then
            -- 'increment' retx_amount_r back to prev values
            -- No other action needed, because of separate retx registers
            if retx_amount_r = 1 then
              retx_amount_r <= 2;
            else
              retx_amount_r <= 1;
            end if;
 
          else
            -- Retransfer success
 
            -- data1_register succesfully transmitted,
            -- still, value of data2 has to be retrasmitted later
            data1_r   <= data2_r;
            comm_d1_r <= comm_d2_r;
 
            -- Take addr from extrapextra register into use
            -- NOTE: additional condition for amount
            if addr2_valid_r = '1' and retx_amount_r = 0 then
              addr1_r       <= addr2_r;
              comm_a1_r     <= comm_a2_r;
              addr2_valid_r <= '0';
            end if;
 
 
 
          end if;
          -- State Retransfer_Data_Last ends --------------------------------------
 
 
 
 
 
 
 
          --++++++++++++++  
        when Write_Data =>
          -- Regular data goes from fifo to output registers
          -- At the same, the data is copied to register data2_r
          -- At the same, time, previously sent data is copied from data2_r to data1_r
          -- If target got full, the data that was on the bus can be returned
          -- from reg1 and the next data taken away from fifo is in reg2.
 
          -- 1) Receiver got full
          --    1a) tx was reading fifo
          --        1aa) addr coming from fifo, re_tx 1 data
          --        1ab) data coming from fifo, re_tx 2 data
          --    1b) tx was not reading fifo, re_tx 1 data
          --    
          -- 2) Tx success but own turn ends
          --    2a) One can be written, then stop tx
          --    2b) New addr canot be written, stop tx
          --    
          -- 3) Tx success and own turn continues
          --    3a) Finish regular write before conf
          --    3b) Answer conf read
          -- 4)
          --    4a) New addr but no data, stop tx
          --    4b) One data, write it and stop tx
          --    4c) At least one data, continue
          -- 
 
 
          -- Default assignments
          data1_r   <= data2_r;         -- equals to current bus data
          comm_d1_r <= comm_d2_r;
          data2_r   <= data_in;         -- equals to data on the bus on next cycle
          comm_d2_r <= comm_in;
 
 
 
          if full_in = '1' then
            -- 1) Receiver got full, stop
            curr_state_r <= Idle;
            lock_v       := '0';
            addr_valid_r <= '0';
            data_out     <= (others => '0');
            comm_out     <= (others => '0');
            fifo_re_r    <= '0';
 
            -- Transfer did not succeed
            if fifo_re_r = '1' then
              -- 1a) FSM was reading fifo
              -- => has to retransfer data on the bus and the data that came
              -- from fifo
 
              -- 04.03.04 contents 'if fifo_re_r = '1" changed
              -- Originally addr and data from fifo were treated in a same
              -- manner
              -- Now if-else clause is added to make a distinction
              -- Original behavior is now locates inside else-branch
 
              if av_in = '1' then
                -- 1aa) New addr from fifo, that goes to addr_2r
                retx_amount_r <= 1;
                data1_r       <= data2_r;
                comm_d1_r     <= comm_d2_r;
                addr2_r       <= data_in (addr_width_g -1 downto 0);  -- 03.02.05;
                comm_a2_r     <= comm_in;
                addr2_valid_r <= '1';
                assert dbg_level < 2 report "Write_D : target full, re = 1, av_f = 1, av_hibi = ?, retransmit 1" severity note;
 
              else
                -- 1ab) New data from fifo
 
                -- 13.09.04 If clause added to check if addr is currently on the bus
                if addr_valid_r = '0' then
                  -- Data on the bus. 'normal' case
                  retx_amount_r <= 2;
                  data1_r       <= data2_r;
                  comm_d1_r     <= comm_d2_r;
                  data2_r       <= data_in;
                  comm_d2_r     <= comm_in;
                  assert dbg_level < 2 report "Write_D : target full, re = 1, av_f = ?, av_hibi = 0, retransmit 2" severity note;
                else
                  -- Addr on the bus
                  retx_amount_r <= 1;
                  data1_r       <= data_in;
                  comm_d1_r     <= comm_in;
                  assert dbg_level < 2 report "Write_D : target full, re = 1, av_f = ?, av_hibi = 1, retransmit 1" severity note;
                end if;  --addr_valid_r
 
              end if;  -- av_from_fifo
 
 
 
            else
              -- 1b) FSM was not reading fifo
              -- => only one data (=data on the bus) has to retransferred
              retx_amount_r <= 1;
              assert dbg_level < 1 report "Write_D     : target full, retransmit 1. Correct??" severity note;
              assert addr_valid_r = '0' report "WriteD : Propably not correct, av_hibi = 1 - > re_tx_amount should be 0" severity warning;
 
            end if;  -- fifo_re
 
 
 
          elsif own_turn_ends = '1' then
            -- 2) Previous transfer success, but own turn ends
            -- One data can still be written but no new addr
 
            curr_state_r <= Write_Last_Data;
            addr_valid_r <= '0';
            lock_v       := '0';
            fifo_re_r    <= '0';
            assert dbg_level < 3 report "Write : Oma vuoro loppuu" severity note;
 
            -- Siirretaan viim data. Jos fifossa osoite seur, ei siirreta mit'n
            if av_in = '0' and empty_in = '0' then
              -- 2a) Data from coming fifo => write it to bus
              data_out <= data_in;
              comm_out <= comm_in;
            else
              -- 2b) Addr coming from fifo => write nothing
              data_out <= (others => '0');
              comm_out <= (others => '0');
            end if;
 
            --  Addr coming from fifo => store it into register
            if empty_in = '0' and av_in = '1' then
              addr1_r   <= data_in (addr_width_g -1 downto 0);  --03.02.05 
              comm_a1_r <= comm_in;
            end if;
 
 
 
          elsif cfg_re_g = 1 and cfg_read_complete_r = '0' then
            -- 3) Own turn continues, answer conf read. Finish the reading of fifo first.
 
            if (fifo_re_r = '1' and av_in = '0' and empty_in = '0') then
              -- 3a) FSM is reading fifo and data coming from fifo
              -- Transfer that data before answering conf read
              curr_state_r <= Write_Data;
              addr_valid_r <= '0';
              data_out     <= data_in;
              comm_out     <= comm_in;
              lock_v       := '1';
              fifo_re_r    <= '0';
              assert dbg_level < 3 report "Write : viim data ennen kuin => conf return addr" severity note;
 
            else
              -- 3b) Answer conf read
              curr_state_r                       <= Cfg_A;
              addr_valid_r                       <= '1';
              data_out                           <= (others => '0');  -- 01.03.05
              data_out (addr_width_g-1 downto 0) <= cfg_ret_addr_r;  -- 01.03.05
              -- data_out     <= a_ext (cfg_ret_addr_r, data_width_g);  --03.02.05cfg_ret_addr_r;
              comm_out                           <= write_command_c;  -- 03.02.05 "010";
              lock_v                             := '1';
              fifo_re_r                          <= '0';
 
              -- Store addr
              if empty_in = '0' and av_in = '1' then
                addr1_r   <= data_in (addr_width_g-1 downto 0);  -- 03.02.05
                comm_a1_r <= comm_in;
              end if;
 
              assert dbg_level < 3 report "Write => conf return addr" severity note;
            end if;  --(re=1&av=0) || (msg_Re=1&msg_av=0)
 
 
 
 
 
          else
            -- 4) Retransfer ready
            -- Answering conf read complete
            -- Own turn continues
            -- => Transfer data
 
            if empty_in = '0' and av_in = '1' and one_d_in = '1' then
              -- 4a) Stop writing, because only one addr left but no data
              curr_state_r <= Idle;
              lock_v       := '0';
              addr_valid_r <= '0';
              data_out     <= (others => '0');
              comm_out     <= (others => '0');
              fifo_re_r    <= '0';
              assert dbg_level < 3 report "Write (d) : Data loppu" severity note;
              -- 13.05.05 AK The read address have to be stored here! if re = '1'
              if fifo_re_r = '1' then
                addr1_r   <= data_in (addr_width_g -1 downto 0);
                comm_a1_r <= comm_in;  -- 25.02.2006 AK comm has to be stored also..
              end if;
 
            elsif av_in = '0' and one_d_in = '1' then
              -- 4b) One data left in the fifo, write it and stop
              curr_state_r <= Write_Last_Data;
              lock_v       := '0';
              addr_valid_r <= '0';
              data_out     <= data_in;
              comm_out     <= comm_in;
              fifo_re_r    <= '0';
              assert dbg_level < 3 report "Write (d) : Data loppumassa. Viim data kirj" severity note;
 
 
            else
              -- 4c)Continue writing data
              curr_state_r <= Write_Data;
              lock_v       := '1';
              data_out     <= data_in;
              comm_out     <= comm_in;
              fifo_re_r    <= '1';
 
              assert empty_in = '0' report "WriteD -> WriteD: empty_in=1. How can this continue?" severity warning;
 
              if empty_in = '0' and av_in = '1' then
                -- New addr coming from fifo
                -- Store it into addr_reg
                addr1_r      <= data_in (addr_width_g -1 downto 0);  -- 03.02.05
                comm_a1_r    <= comm_in;
                addr_valid_r <= '1';
              else
                -- Data coming from fifo, addr_reg keeps its old value
                addr_valid_r <= '0';
              end if;
            end if;  -- empty & av & one_d            
 
          end if;  -- full_in
          -- State Write_Data ends here----------------------------------------
 
 
 
 
 
 
 
 
 
 
 
          --++++++++++++++
        when Write_Last_Data =>
          -- Last cycle of own turn
          curr_state_r <= Idle;
          data_out     <= (others => '0');
          comm_out     <= (others => '0');
          addr_valid_r <= '0';
          lock_v       := '0';
          fifo_re_r    <= '0';
 
 
          if full_in = '0' then
            -- Last tranfer succeeded, nothing has to be retransferred
            retx_amount_r <= 0;
 
            assert dbg_level < 3 report "Write_D_Last : OK" severity note;
          else
            -- Last transfer did not succeed, have to try again on next turn
            -- Re=0 when coming here => only one data has to be retransferred
            retx_amount_r <= 1;         -- 17.01.03 oli 2;
            data1_r       <= data2_r;
            comm_d1_r     <= comm_d2_r;
 
            assert dbg_level < 2 report "Write_D_Last        : target full, retransmit 1" severity note;
            assert fifo_re_r = '0' report "W_last_D : re should be 0" severity warning;
          end if;
 
 
          --++++++++++++++
        when Error_State =>
          assert false report "INVALid STATE IN TX_CONTROL" severity error;
          curr_state_r <= Error_State;
 
 
        when others =>
          -- Do not write to bus
          lock_v       := '0';
          addr_valid_r <= '0';
          comm_out     <= (others => '0');
          data_out     <= (others => '0');
          fifo_re_r    <= '0';
 
      end case;
 
      if keep_slot_g = 1 then
        -- we keep the slot even if we have nothing to send
        lock_out <= lock_v or (curr_slot_own_in and not curr_slot_ends_in) or next_slot_own_in;
      else
        lock_out <= lock_v;
      end if;
 
 
    end if;  --rst_n
  end process Define_output;
 
 
 
  -- 5) PROC
  Count_Priorities : process (clk, rst_n)
  begin  -- process Count_Priorities
    if rst_n = '0' then                 -- asynchronous reset (active low)
      prior_counter_arb_r <= (others => '0');
      switch_arb_r        <= 0;
      arb_type_r          <= (others => '0');
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      -- Assign internal arb_type-register according to ctrl-signal coming from cfg_mem
      if arb_type_in = "00" then
        -- round-robin
        arb_type_r <= "00";
 
      elsif arb_type_in = "01" then
        -- priority, actually 01
        arb_type_r <= "01";
 
      elsif arb_type_in = "10" then
        -- prior+roundrob, "10"
        if switch_arb_r = switch_arb_c-1 then
          switch_arb_r <= 0;
          arb_type_r   <= "0" & not arb_type_r(0);  -- !!!! only when 2 types
 
          else
            switch_arb_r <= switch_arb_r+1;
          arb_type_r <= arb_type_r;
        end if;
 
      else
        arb_type_r <= "11";        
      end if;                           -- arb_type_in
 
 
      -- Update priority_counter according to current arb_type
      if lock_in = '0' and arb_type_r /= "11" then
        -- Bus is idle
 
        if prior_counter_arb_r = n_agents_in (id_width_g-1 downto 0) then
          -- Priorities start from 1 (zero is not allowed)
          prior_counter_arb_r <= conv_std_logic_vector (1, id_width_g);
        else
          -- Bus idle, increase current priority
          prior_counter_arb_r <= prior_counter_arb_r +1;
        end if;
 
 
      else
        -- real arbitration types. now only prior + round rob
        if arb_type_r = "00" then
          -- round-robin
          -- Bus reserved, priority remains the same
          prior_counter_arb_r <= prior_counter_arb_r;
 
        elsif arb_type_r = "01" then
          -- priority, actually 01
          prior_counter_arb_r <= conv_std_logic_vector (1, id_width_g);
 
        else
          -- "lottery"
          -- counter is assigned below in separate process (inside if-generate)
          --          prior_counter_arb_r <= arb_agent_r;
        end if;
 
      end if;                           -- lock & arb_type
    end if;  --rst_n      
 
  end process Count_Priorities;
 
  dyn : if dyn_arb_enable_c = 1 generate
    dyn_arb_1 : dyn_arb
      generic map (
        id_width_g => id_width_g,
--        n_agents_g => 22 --6
        n_agents_g => n_agents_g        -- 2009-04-08
        )                --signaali!
      port map (
        clk           => clk,
        rst_n         => rst_n,
        bus_lock_in   => lock_in,
        arb_agent_out => dyn_arb_prior
        );
 
    assign_priocount: process (dyn_arb_prior, arb_type_in, prior_counter_arb_r)
    begin  -- process assign priocount
      if arb_type_in = "11" then
        prior_counter_r <= dyn_arb_prior;
      else
        prior_counter_r <= prior_counter_arb_r;                
      end if;  
    end process assign_priocount;    
  end generate dyn;
 
  notdyn: if dyn_arb_enable_c /= 1 generate
    assert arb_type_in /= "11" report "ERROR! ARB TYPE RANDOM BUT DYN ARB ENABLE = 0" severity failure;
    prior_counter_r <= prior_counter_arb_r;
  end generate notdyn;
 
end rtl;
 
 
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.