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

Subversion Repositories spi_slave

[/] [spi_slave/] [trunk/] [pcore/] [opb_spi_slave_v1_00_a/] [hdl/] [vhdl/] [opb_m_if.vhd] - Rev 35

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--* 
--* @short OPB-Master Interface
--* 
--* Generics described in top entity.
--*
--* @see opb_spi_slave
--*    @author: Daniel Köthe
--*   @version: 1.0
--* @date: 2007-11-11
--/
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
use IEEE.numeric_std.all;               -- conv_integer()
 
library work;
use work.opb_spi_slave_pack.all;
 
entity opb_m_if is
  generic (
    C_BASEADDR        : std_logic_vector(0 to 31) := X"00000000";
    C_HIGHADDR        : std_logic_vector(0 to 31) := X"FFFFFFFF";
    C_USER_ID_CODE    : integer                   := 0;
    C_OPB_AWIDTH      : integer                   := 32;
    C_OPB_DWIDTH      : integer                   := 32;
    C_FAMILY          : string                    := "virtex-4";
    C_SR_WIDTH        : integer                   := 8;
    C_MSB_FIRST       : boolean                   := true;
    C_CPOL            : integer range 0 to 1      := 0;
    C_PHA             : integer range 0 to 1      := 0;
    C_FIFO_SIZE_WIDTH : integer range 4 to 7      := 7);
 
  port (
    -- opb master interface
    OPB_Clk           : in  std_logic;
    OPB_Rst           : in  std_logic;
    OPB_DBus          : in  std_logic_vector(0 to C_OPB_DWIDTH-1);
    M_request         : out std_logic;
    MOPB_MGrant       : in  std_logic;
    M_busLock         : out std_logic;
    M_ABus            : out std_logic_vector(0 to C_OPB_AWIDTH-1);
    M_BE              : out std_logic_vector(0 to C_OPB_DWIDTH/8-1);
    M_DBus            : out std_logic_vector(0 to C_OPB_DWIDTH-1);
    M_RNW             : out std_logic;
    M_select          : out std_logic;
    M_seqAddr         : out std_logic;
    MOPB_errAck       : in  std_logic;
    MOPB_retry        : in  std_logic;
    MOPB_timeout      : in  std_logic;
    MOPB_xferAck      : in  std_logic;
    ---------------------------------------------------------------------------
    -- read transfer
    -- read data from memory and fill fifo
    opb_m_tx_req      : in  std_logic;
    opb_m_tx_en       : out std_logic;
    opb_m_tx_data     : out std_logic_vector(C_SR_WIDTH-1 downto 0);
    -- enable/disable dma transfer
    opb_tx_dma_ctl    : in  std_logic_vector(0 downto 0);
    -- base adress for transfer
    opb_tx_dma_addr   : in  std_logic_vector(C_OPB_DWIDTH-1 downto 0);
    opb_tx_dma_num    : in  std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
    opb_tx_dma_done   : out std_logic;
    ---------------------------------------------------------------------------
    -- write transfer
    -- read fifo an write to memory 
    opb_m_rx_req      : in  std_logic;
    opb_m_rx_en       : out std_logic;
    opb_m_rx_data     : in  std_logic_vector(C_SR_WIDTH-1 downto 0);
    -- enable/disable dma transfer
    opb_rx_dma_ctl    : in  std_logic_vector(0 downto 0);
    -- base adress for transfer
    opb_rx_dma_addr   : in  std_logic_vector(C_OPB_DWIDTH-1 downto 0);
    opb_rx_dma_num    : in  std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
    opb_rx_dma_done   : out std_logic;
    ---------------------------------------------------------------------------
    opb_abort_flg     : out std_logic;
    opb_m_last_block : out std_logic);
end opb_m_if;
 
architecture behavior of opb_m_if is
 
  type state_t is (idle,
                   wait_grant,
                   transfer_write,
                   transfer_read,
                   done);
 
 
  signal state : state_t := idle;
 
  signal M_DBus_big_end   : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal M_ABus_big_end   : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal OPB_DBus_big_end : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
 
  signal M_select_int  : std_logic;
  signal read_transfer : boolean;
 
  -- read transfer
  signal opb_tx_dma_addr_int : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal opb_tx_dma_en       : std_logic;
  signal opb_tx_dma_num_int  : std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
  signal opb_tx_dma_done_int : std_logic;
 
  -- write transfer
  signal opb_rx_dma_en       : std_logic;
  signal opb_rx_dma_addr_int : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal opb_rx_dma_num_int  : std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
  signal opb_rx_dma_done_int : std_logic;
 
 
begin  -- behavior
 
  --* convert M_DBus_big_end to little endian
  process(M_DBus_big_end)
  begin
    for i in 0 to 31 loop
      M_DBus(31-i) <= M_DBus_big_end(i);
    end loop;  -- i  
  end process;
 
  --* convert M_ABus_big_end to little endian
  process(M_ABus_big_end)
  begin
    for i in 0 to 31 loop
      M_ABus(31-i) <= M_ABus_big_end(i);
    end loop;  -- i  
  end process;
 
  --* convert OPB_DBus to bi endian
  process(OPB_DBus)
  begin
    for i in 0 to 31 loop
      OPB_DBus_big_end(31-i) <= OPB_DBus(i);
    end loop;  -- i  
  end process;
 
  -- for both sides
  M_ABus_big_end <= opb_tx_dma_addr_int when (M_select_int = '1' and (read_transfer = true)) else
                    opb_rx_dma_addr_int when (M_select_int = '1' and (read_transfer = false)) else
                    (others => '0');
  M_select <= M_select_int;
 
 
 
  -- write transfer
  opb_m_rx_en <= MOPB_xferAck when (M_select_int = '1' and (read_transfer = false)) else
                 '0';
 
  M_DBus_big_end(C_SR_WIDTH-1 downto 0) <= opb_m_rx_data when (M_select_int = '1' and (read_transfer = false)) else
                                           (others => '0');
  M_DBus_big_end(C_OPB_DWIDTH-1 downto C_SR_WIDTH) <= (others => '0');
 
  opb_tx_dma_done <= opb_tx_dma_done_int;
 
  -- read transfer
  opb_m_tx_en <= MOPB_xferAck when (M_select_int = '1' and (read_transfer = true)) else
                 '0';
  opb_m_tx_data <= OPB_DBus_big_end(C_SR_WIDTH-1 downto 0);
 
  opb_rx_dma_done <= opb_rx_dma_done_int;
 
 
 
-------------------------------------------------------------------------------
  opb_masteer_proc : process(OPB_Rst, OPB_Clk)
  begin
    if (OPB_Rst = '1') then
      M_BE                <= (others => '0');
      M_busLock           <= '0';
      M_request           <= '0';
      M_RNW               <= '0';
      M_select_int        <= '0';
      M_seqAddr           <= '0';
      opb_tx_dma_done_int <= '0';
      opb_rx_dma_done_int <= '0';
      opb_abort_flg       <= '0';
      opb_m_last_block   <= '0';
      opb_tx_dma_num_int <= (others => '0');
      opb_rx_dma_num_int <= (others => '0');      
    elsif rising_edge(OPB_Clk) then
      case state is
        when idle =>
          opb_abort_flg <= '0';
          opb_tx_dma_en <= opb_tx_dma_ctl(0);
          opb_rx_dma_en <= opb_rx_dma_ctl(0);
 
          if (opb_tx_dma_ctl(0) = '1' and opb_tx_dma_en = '0') then
            opb_tx_dma_addr_int <= opb_tx_dma_addr;
            opb_tx_dma_num_int  <= opb_tx_dma_num;
            opb_tx_dma_done_int <= '0';
 
          end if;
 
          if (opb_rx_dma_ctl(0) = '1' and opb_rx_dma_en = '0') then
            opb_rx_dma_addr_int <= opb_rx_dma_addr;
            opb_rx_dma_num_int  <= opb_rx_dma_num;
            opb_rx_dma_done_int <= '0';
          end if;
 
          if (opb_tx_dma_en = '1' and opb_m_tx_req = '1' and opb_tx_dma_done_int = '0') then
            -- read from memory to fifo
            M_request     <= '1';
            read_transfer <= true;
            state         <= wait_grant;
          elsif (opb_rx_dma_en = '1' and opb_m_rx_req = '1'and opb_rx_dma_done_int = '0') then
            -- read from fifo and write memory
            M_request     <= '1';
            read_transfer <= false;
            state         <= wait_grant;
          else
            state <= idle;
          end if;
 
        when wait_grant =>
          if (MOPB_MGrant = '1') then
            M_request    <= '0';
            M_busLock    <= '1';
            M_select_int <= '1';
            M_seqAddr    <= '1';
            M_BE         <= "1111";
            if (read_transfer) then
              -- read
              M_RNW <= '1';
              if (conv_integer(opb_tx_dma_num_int) = 0) then
                opb_m_last_block <= '1';
              end if;
              state <= transfer_read;
            else
              -- write
              M_RNW <= '0';
              if (conv_integer(opb_rx_dma_num_int) = 0) then
                opb_m_last_block <= '1';
              end if;
              state <= transfer_write;
            end if;
          else
            state <= wait_grant;
          end if;
 
        when transfer_read =>
          if (MOPB_xferAck = '1') then
            opb_tx_dma_addr_int <= opb_tx_dma_addr_int +4;
            if (opb_tx_dma_addr_int(5 downto 2) = conv_std_logic_vector(14, 4)) then
              -- cycle 14
              -- deassert buslock and seq_address 1 cycle before transfer complete
              M_busLock <= '0';
              M_seqAddr <= '0';
            elsif (opb_tx_dma_addr_int(5 downto 2) = conv_std_logic_vector(15, 4)) then
              -- cycle 15
              M_RNW        <= '0';
              M_select_int <= '0';
              M_BE         <= (others => '0');
              if (conv_integer(opb_tx_dma_num_int) = 0) then
                opb_tx_dma_done_int <= '1';
                opb_m_last_block   <= '0';
              else
                opb_tx_dma_num_int <= opb_tx_dma_num_int-1;
              end if;
              state <= done;
            end if;
          elsif (MOPB_retry = '1' or MOPB_errAck = '1' or MOPB_timeout = '1') then
            -- cancel transfer
            M_busLock     <= '0';
            M_seqAddr     <= '0';
            M_RNW         <= '0';
            M_select_int  <= '0';
            M_BE          <= (others => '0');
            opb_abort_flg <= '1';
            state         <= done;
          else
            state <= transfer_read;
          end if;
 
        when transfer_write =>
          if (MOPB_xferAck = '1') then
            opb_rx_dma_addr_int <= opb_rx_dma_addr_int +4;
            if (opb_rx_dma_addr_int(5 downto 2) = conv_std_logic_vector(14, 4)) then
              -- cycle 14
              -- deassert buslock and seq_address 1 cycle before transfer complete
              M_busLock <= '0';
              M_seqAddr <= '0';
            elsif (opb_rx_dma_addr_int(5 downto 2) = conv_std_logic_vector(15, 4)) then
              -- cycle 15
              M_RNW        <= '0';
              M_select_int <= '0';
              M_BE         <= (others => '0');
              if (conv_integer(opb_rx_dma_num_int) = 0) then
                opb_rx_dma_done_int <= '1';
                opb_m_last_block   <= '0';
              else
                opb_rx_dma_num_int <= opb_rx_dma_num_int-1;
              end if;
              state <= done;
            end if;
          elsif (MOPB_retry = '1' or MOPB_errAck = '1' or MOPB_timeout = '1') then
            -- cancel transfer
            M_busLock     <= '0';
            M_seqAddr     <= '0';
            M_RNW         <= '0';
            M_select_int  <= '0';
            M_BE          <= (others => '0');
            opb_abort_flg <= '1';
            state         <= done;
          else
            state <= transfer_write;
          end if;
 
        when done =>
 
          state <= idle;
 
        when others =>
          state <= idle;
      end case;
    end if;
  end process opb_masteer_proc;
end behavior;
 

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.