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/] [rx_ctrl.vhd] - Rev 145

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        : rx_control_addr_width_is_1.vhdl
-- Description : Control of the receiver for only one cycle long addresses
--               Includes two state machines: one for configuration
--               one for regular data. No distinction made between data and messages.
--
--               Needs one_place signal from fifo. Probably this could be
--               avoided by having two addr registers. One for decoding and one
--               for storing. Store reg  would be used only fifo gets full
--
-- Author       : Erno Salminen
-- e-mail       : erno.salminen@tut.fi
-- Date         : 16.12.2002
-- Project      
-- Design       : Do not use term design when you mean system
-- Modified
--
-- 16.12.02     The earlier versions did not fully work when FIFO got full.
--              This is somewhat better.
-- 01.04.03     New state Two_Data_Full_New_Addr added
-- 13.04.03     message stuff removed, es
-- 16.05.03     Config receiving added
-- 24.07.03     Target_full logic changed, cleaning
-- 07.02.05     ES new generics
-- 04.03.05     ES new generics id_width_g and cfg_addr_width_g
-- 15.12.05     ES Commented out all (others => rst_valu_arra(dbg_level)
--                 => registers keep their old values
--                 => 16% reduction in area for 32b rx_ctrl (ST 0.13um)
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.hibiv2_pkg.all;
 
entity rx_control is
  generic (
    data_width_g     :    integer := 32;
    addr_width_g     :    integer := 25;  -- in bits!
    id_width_g       :    integer := 5;   -- 04.03.2005
    cfg_addr_width_g :    integer := 16;  -- in bits, smaller than addr_w,  04.03.2005
    cfg_re_g         :    integer := 1;   -- 07.02.05
    cfg_we_g         :    integer := 1    -- 07.02.05
    );
  port (
    clk              : in std_logic;
    rst_n            : in std_logic;
 
    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_c-1 downto 0);
    full_in          : in  std_logic;
    one_p_in         : in  std_logic;
    cfg_rd_rdy_in    : in  std_logic;   --16.05
 
    addr_match_in   : in  std_logic;
    decode_addr_out : out std_logic_vector ( addr_width_g -1 downto 0);
    decode_comm_out : out std_logic_vector ( comm_width_c-1 downto 0);
    decode_en_out   : out std_logic;
 
    data_out         : out std_logic_vector ( data_width_g-1 downto 0);
    comm_out         : out std_logic_vector ( comm_width_c-1 downto 0);
    av_out           : out std_logic;
    we_out           : out std_logic;
    full_out         : out std_logic;
 
    cfg_we_out       : out std_logic;
    cfg_re_out       : out std_logic;
    cfg_addr_out     : out std_logic_vector ( cfg_addr_width_g -1 downto 0);
    cfg_data_out     : out std_logic_vector ( data_width_g -1 downto 0);
    cfg_ret_addr_out : out std_logic_vector ( addr_width_g -1 downto 0)
    );
 
end rx_control;
 
 
architecture rtl of rx_control is
 
  -- Selects if debug prints are used (1-3) 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_arr array, the rst value may
  -- be easily set to '0' for synthesis.
  -- 16.12.05 try if "don't care" could reduce area
  constant rst_value_arr : std_logic_vector ( 6 downto 0) := 'X' & 'Z' & 'X' & 'Z' & 'X' & 'Z' & '0';
 
 
 
  -- Controller has two state machines
  --  fsm1 receives redular data (and messages) and requests
  --  fsm2 receives configuration data and requests
  -- Fsm2 is simpler because confmemory cannot be full like fifo 
  type state_type is (Wait_Addr,
                      One_Addr, One_Data, One_Data_New_Addr, One_Addr_One_Data,
                      Two_Data, Two_Data_Full, Two_Data_Full_New_Addr,
                      Reconfiguration);
  signal curr_state_r, next_state       : state_type;
 
  -- attribute enum_encoding : string;
  -- attribute enum_encoding of state_type: type is "000000001 000000010 000000100 000001000 000010000 000100000 001000000 010000000 100000000";
 
 
  type conf_state_type is (Conf_Idle, Conf_One_Addr, Conf_Addr_Data);
  -- attribute enum_encoding : string;
  -- attribute enum_encoding of conf_state_type: type is "001 010 100";
 
 
  signal cfg_curr_state_r, cfg_next_state : conf_state_type;
 
  -- Registers for receiving data
  signal enable_decode_r : std_logic;   -- 04.08.2004
  signal addr_r          : std_logic_vector ( addr_width_g-1 downto 0);
  signal data_r          : std_logic_vector ( data_width_g-1 downto 0);
  signal data_to_fifo_r  : std_logic_vector ( data_width_g-1 downto 0);
  signal comm_to_fifo_r  : std_logic_vector ( comm_width_c-1 downto 0);
  signal comm_a_r        : std_logic_vector ( comm_width_c-1 downto 0);
  signal comm_d_r        : std_logic_vector ( comm_width_c-1 downto 0);
  signal av_to_fifo_r    : std_logic;
  signal we_to_fifo_r    : std_logic;
 
  -- Registers for receiving configuration
  signal cfg_write_enable_r : std_logic;
  signal cfg_read_enable_r  : std_logic;
  signal cfg_new_value_r    : std_logic_vector ( data_width_g -1 downto 0);
  -- cfg osoitteesta tarvitaan id osoitteen vertailua varten ja cfg_addr_w
  -- muistia varten. Addr_w lienee kuitenkin leveämpi kuin id_w + cfg_a_w
  -- yhteensä 04.03.05
  signal cfg_id_r           : std_logic_vector ( id_width_g -1 downto 0);  -- 04.03.05
  signal cfg_addr_r         : std_logic_vector ( cfg_addr_width_g -1 downto 0);  -- 04.03.05
  signal cfg_return_addr_r  : std_logic_vector ( addr_width_g -1 downto 0);
  signal cfg_comm_r         : std_logic_vector ( comm_width_c -1 downto 0);  -- 15.05
 
begin
 
 
 
  -- Continuous assignments             ---------------------------------------------------
  decode_en_out <= enable_decode_r;     -- 04.08.2004
  data_out      <= data_to_fifo_r;
  comm_out      <= comm_to_fifo_r;
  av_out        <= av_to_fifo_r;
  we_out        <= we_to_fifo_r;
 
  cfg_we_out       <= cfg_write_enable_r;
  cfg_re_out       <= cfg_read_enable_r;
  cfg_data_out     <= cfg_new_value_r;
  cfg_addr_out     <= cfg_addr_r;       -- 04.03.05
  cfg_ret_addr_out <= cfg_return_addr_r;
 
 
  -----------------------------------------------------------------------------
  -- PROCESSES ----------------------------------------------------------------
  -----------------------------------------------------------------------------
 
  -- 04.03.05
  assert cfg_addr_width_g < (addr_width_g+1) report "Cfg_addr_w must be smaller than addr_w" severity ERROR;
 
  -- 1) PROC
  -- Synchronous process for state transitions
  Sync : process (clk, rst_n)
  begin  -- process
    if rst_n = '0' then
      curr_state_r     <= Wait_Addr;
      cfg_curr_state_r <= Conf_Idle;
    elsif clk'event and clk = '1' then
      curr_state_r     <= next_state;
      cfg_curr_state_r <= cfg_next_state;
    end if;
  end process;
 
 
 
 
 
  -- 2) PROC (ASYNC)
  -- Selects which address register is fed to addr decoder 
  Select_Decoded_Addr : process (addr_r, comm_a_r, -- cfg_addr_r,
                                 cfg_comm_r, cfg_curr_state_r, cfg_id_r)
  begin  -- process Select_Decoded_Addr
    assert addr_width_g < data_width_g+1 report "addr_width_g must be smaller than data_width_g" severity FAILURE;
 
    -- modified 2007/04/17
    if (cfg_re_g=1 
	or cfg_we_g=1) 
	and cfg_curr_state_r = Conf_One_Addr then
 
      -- Conf addr received
      decode_addr_out                                                     <= (others => '0');  --04.03.05
      decode_addr_out (addr_width_g -1 downto addr_width_g - id_width_g ) <= cfg_id_r;  -- 04.03.05;
      decode_comm_out                                                     <= cfg_comm_r;
    else
      -- Regular addr received
      decode_addr_out                                                     <= addr_r;
      decode_comm_out                                                     <= comm_a_r;
    end if;  --cfg_curr_state_r
  end process Select_Decoded_Addr;
 
 
  -- 3) PROC (ASYNC)
  -- Assign output full_out when needed
  ControlTargetFull : process (full_in, one_p_in,
                               addr_match_in, comm_in,
                               curr_state_r)
  begin  -- process ControlTargetFull
 
    -- New version 24.07.03 es
    if comm_in /= idle_c then
      -- Bus is reserved = some agent is transmitting
 
 
      if full_in = '1' then
        -- Fifo full
 
        if curr_state_r = Wait_Addr
          or curr_state_r = One_Data
          or curr_state_r = Two_Data_Full
        then
          -- Some other wrapper is the current receiver
          full_out <=  '0';
 
        elsif curr_state_r = One_Addr
          or curr_state_r = One_Data_New_Addr
          or curr_state_r = Two_Data_Full_New_Addr
        then
          -- Addr received and fifo is full
          -- Assert target_full only if this wrapper is the receiver (=addr matches)
          full_out <= addr_match_in;
 
        else
          -- This wrapper is receiving data and fifo is full
          full_out <= '1';
        end if;
 
 
      else
        if one_p_in = '1' then
          -- In some case, there has to be at least two fifo places empty
 
 
          if curr_state_r = One_Addr
            or curr_state_r = One_Data_New_Addr
            or curr_state_r = Two_Data_Full_New_Addr
          then 
            -- Addr received and only one place left in the fifo
            -- Assert target_full only if this wrapper is the receiver (=addr matches)
            full_out <=  addr_match_in;
            -- This ensures that fifo=1 cannot happen in these states
            -- (FSM stays only one cycle in this states)
 
          else
            -- In other FSM states, no need to do anything, one place is enough
            full_out <= '0';
          end if;                       -- curr_state_r
 
        elsif curr_state_r = Two_Data_Full_New_Addr then
          -- elsif added 2009-07-28, JN
          -- Before this fix, in cases where hibi frequency was lower than
          -- IP frequency, one_p_in went up and down again within one clk cycle
          -- causing full_out to be 0 (the else branch below). This made sender
          -- continue transferring even though we didn't have enough space to
          -- store the data. This lead to address not being written to the fifo
          -- at all. Now we reject the transfer until we have succesfully
          -- written old data from data_r to the fifo.
          full_out <= addr_match_in;
 
        else
          -- At least two places in the fifo
          full_out <= '0';      
        end if;                         -- one_p_in
      end if;                           -- full_in
 
    else
      -- Bus is idle
      full_out <= '0';      
    end if;                             -- comm_in
 
 
  end process ControlTargetFull;
 
 
 
 
 
  -- 4) PROC (ASYNC)
  -- Defines the next state of state machine for regular data
  -- 
  DefNextState : process (curr_state_r, addr_match_in,
                          av_in, comm_in,
                          full_in, one_p_in)
  begin  -- process DefNextState
 
    case curr_state_r is
 
      when  Wait_Addr =>       
        if comm_in /= idle_c and av_in = '1' then
          -- There is an addr on the bus
 
          if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
            -- New conf addr, handled elsewhere (see below)
            next_state <= curr_state_r; --Wait_Addr;
          else
            -- New data transfer begins
            next_state <= One_Addr;
          end if;                       --comm          
 
        else
          next_state <= Wait_Addr;
        end if;                         -- comm_in&av_in
 
 
 
      when One_Addr =>
 
        if comm_in /= idle_c
          and addr_match_in = '1'
          and full_in = '0'
          and one_p_in = '0'   -- 1_place added 23.07.03
        then
          -- Matching addr read on prev cycle.
          -- Corresponding data is read to register on this cycle
          -- If next_state will be 1a_1d, it is propably necessary to check 1_place_left
          -- ( to ensure that it is not possible to have fulll=1 in that state
          -- => addr register is freed to be used with next addr on the bus)
          next_state <= One_Addr_One_Data;
 
          -- 24.07 : If it is ensured that addr fits into fifo, it would be
          -- possible to have next_state= one_data.
          -- However, in other cases that state reached only when transfer has
          -- ended. Therefore, it seems safer to go state 1a_1d (if there are
          -- at least two places int he fifo) to keep state
          -- one_data untouched.
 
        else
          -- Addr does not match or no data after addr
          next_state <= Wait_Addr;
        end if;                         -- comm_in&full_in
 
 
 
      when One_Data =>
        if full_in = '1' then
          -- Data does not fit into fifo
 
          if av_in = '1' then
            -- New addr on the bus
              if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
                -- New conf addr, handled elsewhere (see below)
                next_state <= curr_state_r;
              else
                -- New data transfer begins
                next_state <= One_Data_New_Addr;
              end if;                       -- comm_in          
 
          else
            -- Data that is currently on the bus has to be retransferred by the
            -- tx_ctrl
            next_state <= One_Data;
          end if;                       -- AV
 
 
        else
          -- Data goes into fifo i.e. fifo not full          
          if av_in = '1'  then
 
            if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
              -- New conf addr, handled elsewhere (see below)
              next_state <= curr_state_r;
            else
              -- New data transfer begins
              next_state <= One_Addr;   -- ES 22.7.2003
            end if;                     -- comm_in          
 
          else
            next_state <= Wait_Addr;
          end if;                       -- AV
         end if;                        -- full_in
 
 
 
      when One_Addr_One_Data =>
 
        if full_in = '1' then
          -- 23.07.03 This branch should be impossible to reach
          -- Otherwise the addr register stays reserved and it is not possible
          -- to store next addr on the bus anywhere
          next_state <= One_Addr_One_Data;
          assert false report "Rec-1d1a Fifo full. Illegal condition, possible deadlock!" severity warning;
 
        else
          -- Addr goes to fifo
 
          if comm_in = idle_c then
            -- Tx ends after first data
            next_state <= One_Data;
          else
            if av_in = '1' then
              -- New addr on the bus
 
              if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
                -- New conf addr, handled elsewhere (see below)                
                next_state <= One_Data;
              else
                -- New data transfer begins
                next_state <= One_Data_New_Addr;
              end if;                       --comm          
 
            else
              -- New data
              next_state <= Two_Data;
            end if;                     -- AV
          end if;                       -- comm_in
        end if;                         -- full_in
 
 
 
      when One_Data_New_Addr =>
        if full_in = '1' then
          -- Fifof full, do not accept any new data
          -- Store addr so that target_full can be asserted if addr matches
          next_state <= One_Data;
 
        else
          -- Data goes into fifo
 
          if one_p_in = '1' then
            -- Only data fits into fifo, do not accept addr or
            -- data following it
            next_state <= Wait_Addr;
 
          elsif comm_in = idle_c or addr_match_in = '0' then
            -- Addr does not match or transfer ends after the addr
            next_state <= Wait_Addr;
 
          else
 
            if av_in = '1' then  
              -- Addr 
 
              if comm_in = w_cfg_c or comm_in = r_cfg_c then --15.05
                -- New conf addr, handled elsewhere (see below)
                next_state <= Wait_Addr;
              else
                -- New data transfer begins
                next_state <= One_Addr;
              end if;                       --comm          
 
            else
              -- New data
              next_state <= One_Addr_One_Data;
            end if;  -- AV
          end if;  -- comm_in
        end if;  -- full_in
 
 
 
      when Two_Data =>
        if full_in = '1' then
          next_state <= Two_Data_Full; 
        else
          -- Another data goes into fifo
 
          if comm_in = idle_c then
            -- Transfer ends
            next_state <= One_Data;
 
          else
            if av_in = '1' then
 
              if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
                -- New conf addr, handled elsewhere (see below)
                next_state <= One_Data;
              else
                -- New data transfer begins
                next_state <= One_Data_New_Addr;
              end if;                       --comm          
 
            else
              -- More data
              next_state <= Two_Data;
            end if;                     -- AV
          end if;                       -- comm_in
        end if;                         -- full_in
 
 
 
      when Two_Data_Full =>
        -- updated 01.04.03
        if full_in = '1' then
          -- No data can be written to fifo
 
          if av_in = '1' then
            -- New addr = new transfer
 
            if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
              -- New conf addr, handled elsewhere (see below)
              next_state <= Two_Data_Full;
            else
              -- New data transger begins
              -- Addr is stored and compared so that target_full can be
              -- asserted if needed
              next_state <= Two_Data_Full_New_Addr;
            end if;                       -- comm_in          
 
          else
            -- Data that is currently on the bus has to be retransferred by the
            -- tx_ctrl
            next_state <= Two_Data_Full;
          end if;                       -- AV
 
        else
          -- Another data goes to fifo
 
          if av_in = '1' then
            -- New addr = new transfer
            if comm_in = w_cfg_c or comm_in = r_cfg_c then  --15.05
              -- New conf addr, handled elsewhere (see below)
              next_state <= curr_state_r;
            else
              -- Uusi siirto alkaa
              next_state <= One_Data_New_Addr;
            end if;  -- comm_in          
 
          else
            -- Data that is currently on the bus has to be retransferred by the
            -- tx_ctrl
            next_state <= One_Data;
          end if;                       -- AV
        end if;                         -- full_in
 
 
 
      when Two_Data_Full_New_Addr =>
        -- New state 01.04.03
 
        if full_in = '1' then
          -- Fifo is full, do not accept addr regardless if it matches or not
          next_state <= Two_Data_Full;
        else
 
          -- another data went into fifo
          -- (Earlier here were all kinds of if clauses, but they all led to
          -- state One_Data, so they are removed. In Two_Data_Full_New_Addr
          -- nothing can be read, so there is no other state to go.)
          next_state <= One_Data;
 
        end if;         -- full_in
 
 
      when others =>
        assert false report "Illegal curr state in rx fsm" severity warning;
        next_state <= Wait_Addr;        --12.-4.03
    end case;
 
 
  end process DefNextState;
 
 
 
 
  -- 5) PROC
  ControlRegisters : process (clk, rst_n)
  begin  -- process ControlRegisters
    if rst_n = '0' then                 -- asynchronous reset (active low)
      addr_r          <= (others => rst_value_arr (dbg_level* 1));
      data_r          <= (others => rst_value_arr (dbg_level* 1));
      data_to_fifo_r  <= (others => rst_value_arr (dbg_level* 1));
      comm_to_fifo_r  <= (others => rst_value_arr (dbg_level* 1));
      av_to_fifo_r    <= '0';
      comm_a_r        <= (others => rst_value_arr (dbg_level* 1));
      comm_d_r        <= (others => rst_value_arr (dbg_level* 1));
      we_to_fifo_r    <= '0';
      enable_decode_r <= '1';
 
 
    elsif clk'event and clk = '1' then          -- rising clock edge
 
      enable_decode_r <= '1';
      we_to_fifo_r    <= '0';
 
 
      case curr_state_r is
 
 
        when Wait_Addr              =>
          av_to_fifo_r   <= '0';
          we_to_fifo_r   <= '0';
 
          -- 15.05 es
          if next_state = One_Addr then
            addr_r   <= data_in ( addr_width_g -1 downto 0);  -- 31.01.05
            comm_a_r <= comm_in;
          end if;
 
 
        when One_Addr                 =>
          if next_state = Wait_Addr then
            av_to_fifo_r   <= '0';
            we_to_fifo_r   <= '0';
 
          else
            -- i.e. next_state = One_Addr_One_Data
            data_r                                  <= data_in;
            data_to_fifo_r                          <= (others => '0');  -- 31.01.05 jos osoite kapea, nollataan ylimmät bitit
            data_to_fifo_r(addr_width_g-1 downto 0) <= addr_r;  --osoite fifolle
            comm_to_fifo_r                          <= comm_a_r;
            av_to_fifo_r                            <= '1';
            comm_d_r                                <= comm_in;
            we_to_fifo_r                            <= '1';
          end if;
 
        when One_Data                 =>
          if next_state = One_Data then
            we_to_fifo_r   <= '1';
 
          elsif next_state = One_Data_New_Addr then
            -- 22.7.2003 : Registers going to fifo cannot reset to zero
            -- because fifo is full at the moment. ES
            addr_r         <= data_in ( addr_width_g -1 downto 0);  -- 31.01.05  --new addr on bus
            comm_a_r       <= comm_in;
 
            we_to_fifo_r   <= '1';
 
 
          elsif next_state = Wait_Addr then
            av_to_fifo_r   <= '0';
            we_to_fifo_r   <= '0';
 
          elsif next_state = One_Addr then
            addr_r         <= data_in ( addr_width_g -1 downto 0);  -- 31.01.05;  --new addr on bus
            av_to_fifo_r   <= '0';
            comm_a_r       <= comm_in;
            we_to_fifo_r   <= '0';
          else
            assert false report "Illegal next state in rx fsm (1D)" severity warning;
          end if;
 
 
        when One_Addr_One_Data =>
          data_to_fifo_r <= data_r;
          comm_to_fifo_r <= comm_d_r;
          av_to_fifo_r   <= '0';
          we_to_fifo_r <= '1';
 
          if next_state = One_Data_New_Addr then
            addr_r   <= data_in ( addr_width_g -1 downto 0);  -- 31.01.05;        --new addr on bus
            comm_a_r <= comm_in;
 
          elsif next_state = One_Addr_One_Data then
            -- Fifo full, cannot receive anything
            -- 23.07 This should be impossible branch
            assert false report "Rx : 1a1d - > 1a1d, Illegal?" severity warning;
 
          elsif next_state = Two_Data then
            data_r   <= data_in;
            comm_d_r <= comm_in;
 
          elsif next_state /= One_Data then
            assert false report "Illegal next state in rx fsm (1A_1D)" severity warning;             
          end if;
 
 
 
        when Two_Data =>
          we_to_fifo_r <= '1';
 
          if next_state = Two_Data then
 
            if full_in = '1' then
              -- 31.03.03 Is this branch ever reached??
              -- This may be the same as if the next state is 2d_full
              assert dbg_level < 1 report "huhuu? two_d - > two_d?" severity note;
 
            else
              data_r         <= data_in;
              data_to_fifo_r <= data_r;
              comm_to_fifo_r <= comm_d_r;
              av_to_fifo_r   <= '0';
              comm_d_r       <= comm_in;
            end if;
 
          elsif next_state = One_Data_New_Addr then
            addr_r         <= data_in (addr_width_g-1 downto 0);  -- 31.01.05 --new addr on bus
            data_to_fifo_r <= data_r;
            comm_to_fifo_r <= comm_d_r;
            av_to_fifo_r   <= '0';
            comm_a_r       <= comm_in;
 
          elsif next_state = One_Data then
            data_to_fifo_r <= data_r;
            comm_to_fifo_r <= comm_d_r;
            av_to_fifo_r   <= '0';
 
          elsif next_state /= Two_Data_Full then
            assert false report "Illegal next state in rx fsm (2D)" severity warning;
          end if;
 
 
        when One_Data_New_Addr =>
 
          if next_state = Wait_Addr then
            av_to_fifo_r   <= '0';
            we_to_fifo_r   <= '0';
 
          elsif next_state = One_Addr then
            addr_r         <= data_in (addr_width_g -1 downto 0); -- 31.01.05  --new addr on bus
            av_to_fifo_r   <= '0';
            comm_a_r       <= comm_in;
            we_to_fifo_r   <= '0';
 
          elsif next_state = One_Addr_One_Data then
            data_r         <= data_in;
            data_to_fifo_r <= (others => '0');  -- 31.01.05 jos osoite kapea, nollataan ylimmät bitit
            data_to_fifo_r(addr_width_g-1 downto 0) <= addr_r;    -- osoite fifolle
            comm_to_fifo_r <= comm_a_r;
            av_to_fifo_r   <= '1';
            comm_d_r       <= comm_in;
            we_to_fifo_r   <= '1';
 
          elsif next_state = One_Data then
            we_to_fifo_r   <= '1';
 
          else
            assert false report "Illegal next state in rx fsm (1D_nA)" severity warning;             
          end if;
 
 
       when Two_Data_Full =>
 
          if next_state = Two_Data_Full_New_Addr then
            addr_r   <= data_in (addr_width_g -1 downto 0);  -- 31.01.05  --new addr on bus
            comm_a_r <= comm_in;
            we_to_fifo_r   <= '1';
 
          elsif next_state = One_Data then
            data_to_fifo_r <= data_r;
            comm_to_fifo_r <= comm_d_r;
            we_to_fifo_r   <= '1';
 
          elsif next_state = One_Data_New_Addr then
            addr_r   <= data_in (addr_width_g -1 downto 0);  --31.01.05  --new addr on bus
            comm_a_r <= comm_in;
 
            data_to_fifo_r <= data_r;
            comm_to_fifo_r <= comm_d_r;
            we_to_fifo_r   <= '1';
 
          else
            we_to_fifo_r   <= '1';
          end if;
 
 
 
 
      when Two_Data_Full_New_Addr =>
        -- New state 01.04.03
          if next_state = Two_Data_Full then
            -- Fifo still full, everything stays the same
            addr_r   <= (others   => '0');  --'Z'); --addr_r;  -- reseting possible ?
            we_to_fifo_r   <= '1';
 
          elsif next_state = One_Data then
            -- Another data went into fifo, but the addr cannot be accepted yet
            -- due to lack of fifo space
            data_to_fifo_r <= data_r;
            comm_to_fifo_r <= comm_d_r;
            we_to_fifo_r   <= '1';
 
          else
 
            assert false report "TwoData -> ?? : Haloo?" severity note;
          end if;
 
 
        when others =>
          null;
      end case;
    end if;
  end process ControlRegisters;
 
 
 
 
 
  -- 6) PROC (ASYNC)
  Def_Conf_next_state : process (cfg_curr_state_r, av_in, comm_in, addr_match_in, cfg_rd_rdy_in)
  begin  -- process Def_Conf_next_state
      -- if modified 2007/04/17
      if cfg_re_g = 1 or cfg_we_g = 1 then
 
        case cfg_curr_state_r is
 
          when Conf_Idle =>
 
            if av_in = '1' then
 
              if  (comm_in = w_cfg_c or comm_in = r_cfg_c) then
                -- New conf addr
                cfg_next_state <= Conf_One_Addr;
                assert false report "New conf" severity note;
              else
                cfg_next_state <= Conf_Idle;
              end if;
            else
              cfg_next_state <= Conf_Idle;
            end if;                         -- av & comm
 
 
          when Conf_One_Addr =>
            if addr_match_in = '1'
              and (comm_in = w_cfg_c or comm_in = r_cfg_c) then
              -- Conf addr matches and conf transfer continues (either conf value
              -- or return addr)
              cfg_next_state <= Conf_Addr_Data;
            else
              -- ConfK addr does not match
              cfg_next_state <= Conf_Idle;
            end if;                         --am & comm
 
 
 
          when Conf_Addr_Data =>
 
            if cfg_rd_rdy_in = '1' then
              --  Current conf data goes into conf_mem/tx_ctrl
 
              if  (comm_in = w_cfg_c or comm_in = r_cfg_c) then
                -- Conf continues
 
                if av_in = '1' then
                  -- New confK addr
                  cfg_next_state <= Conf_One_Addr;
                else
                  -- new conf data
                  cfg_next_state <= Conf_Addr_Data;
                end if;                       --av
 
              else
                -- Conf ends
                cfg_next_state <= Conf_Idle;
              end if;                       --comm
 
            else
              -- Cannot forward current conf data
              if av_in = '1'
                and (comm_in = w_cfg_c or comm_in = r_cfg_c) then
                -- New confK addr
                cfg_next_state <= Conf_One_Addr;
              else
                -- Conf transfer ends, cannot forward current conf data
                cfg_next_state <= Conf_Addr_Data;
              end if;
 
            end if;                         --cfg_rd_rdy_in
 
 
          when others =>
            cfg_next_state <= Conf_Idle;
        end case;  --cfg_curr_state_r
      end if;                           -- cfg_we_g or cfg_re_g
 
  end process Def_conf_next_state;
 
 
 
 
  -- 7) PROC
  Control_Conf_registers : process (clk, rst_n)
  begin  -- process Control_Conf_registers
    if rst_n = '0' then                 -- asynchronous reset (active low)
      cfg_comm_r         <= (others => rst_value_arr (dbg_level* 1));
      cfg_id_r           <= (others => rst_value_arr (dbg_level* 1));
      cfg_addr_r         <= (others => rst_value_arr (dbg_level* 1));
      cfg_return_addr_r  <= (others => rst_value_arr (dbg_level* 1));
      cfg_new_value_r    <= (others => rst_value_arr (dbg_level* 1));
      cfg_read_enable_r  <= '0';
      cfg_write_enable_r <= '0';
 
    elsif clk'event and clk = '1' then  -- rising clock edge
 
      if cfg_re_g = 1 or cfg_we_g = 1 then
 
 
        case cfg_curr_state_r is
 
          when Conf_Idle                       =>
            -- Wait for conf addr
 
            if cfg_next_state = Conf_One_Addr then
              -- Conf addr on the bus
              cfg_id_r         <= data_in ( addr_width_g -1 downto addr_width_g - id_width_g );  -- 04.03.05;
              cfg_addr_r       <= data_in (cfg_addr_width_g -1 downto 0);  -- 04.03.05;
              cfg_comm_r       <= comm_in;
            end if;
            cfg_write_enable_r <= '0';
            cfg_read_enable_r  <= '0';
 
 
          when Conf_One_Addr =>
            -- Coonf addr received
 
 
            case cfg_next_state is
              when Conf_Idle                  =>
                -- Conf addr does not match
                cfg_write_enable_r <= '0';
                cfg_read_enable_r  <= '0';
 
              when Conf_One_Addr =>
                -- Illegal next state
                assert false report
                  "Illegal state transition conf_one_addr -> conf_one_addr" severity warning;
 
 
              when Conf_Addr_Data                   =>
                -- Conf addr matches
                -- Check whether the command is read or write
 
                if comm_in = w_cfg_c then
                  cfg_new_value_r    <= data_in;
                  cfg_write_enable_r <= '1';
                  cfg_read_enable_r  <= '0';
                else
                  cfg_return_addr_r  <= data_in(addr_width_g-1 downto 0);  -- 17.02
                  cfg_write_enable_r <= '0';
                  cfg_read_enable_r  <= '1';
                end if;
 
            end case;                     --cfg_next_state
 
 
          when Conf_Addr_Data =>
            -- Conf addr matched and conf data/return_addr also recieved
 
            case cfg_next_state is
              when Conf_Idle                  =>
                -- Conf ends
                cfg_write_enable_r <= '0';
                cfg_read_enable_r  <= '0';
 
              when Conf_One_Addr =>
                -- New conf immediatley following the previous
                -- Take new conf addr
                cfg_write_enable_r <= '0';
                cfg_read_enable_r  <= '0';
                cfg_id_r           <= data_in ( addr_width_g -1 downto addr_width_g - id_width_g );  -- 04.03.05;
                cfg_addr_r         <= data_in (cfg_addr_width_g -1 downto 0);  -- 04.03.05;
                cfg_comm_r         <= comm_in;
 
              when Conf_Addr_Data               =>
                -- More conf data immediatly, chekc command
                if comm_in = w_cfg_c then
                  -- Conf write
                  cfg_comm_r         <= comm_in;
                  cfg_new_value_r    <= data_in;
                  cfg_write_enable_r <= '1';
                  cfg_read_enable_r  <= '0';
 
                else
                  -- Conf read
                  cfg_comm_r         <= comm_in;
                  cfg_return_addr_r  <= data_in (addr_width_g -1 downto 0);  -- 31.01.05
                  cfg_write_enable_r <= '0';
                  cfg_read_enable_r  <= '1';
                end if;
                -- Increment conf addr
                -- NOTE: To make style "1 conf_addr + several conf_data"
                -- to work, also the tx_ctrl has to increment conf_addr
                -- so that it continues from correct addr if conf transmission is
                -- interrupted
                cfg_addr_r           <= cfg_addr_r+1;
 
 
            end case;                     -- cfg_next_state          
        end case;                         -- cfg_curr_state_r
      end if;
    end if;                             --rst / clk'event
  end process Control_Conf_registers;
end rtl;
 

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.