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_if.vhd] - Rev 38

Compare with Previous | Blame | View Log

-------------------------------------------------------------------------------
--* 
--* @short OPB-Slave 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_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                   := 3;
    C_OPB_AWIDTH      : integer                   := 32;
    C_OPB_DWIDTH      : integer                   := 32;
    C_FAMILY          : string                    := "virtex-4";
    C_SR_WIDTH        : integer                   := 8;
    C_FIFO_SIZE_WIDTH : integer                   := 4;
    C_DMA_EN          : boolean                   := false;
    C_CRC_EN          : boolean                   := false);
  port (
    -- OPB-Bus Signals
    OPB_ABus         : in  std_logic_vector(0 to C_OPB_AWIDTH-1);
    OPB_BE           : in  std_logic_vector(0 to C_OPB_DWIDTH/8-1);
    OPB_Clk          : in  std_logic;
    OPB_DBus         : in  std_logic_vector(0 to C_OPB_DWIDTH-1);
    OPB_RNW          : in  std_logic;
    OPB_Rst          : in  std_logic;
    OPB_select       : in  std_logic;
    OPB_seqAddr      : in  std_logic;
    Sln_DBus         : out std_logic_vector(0 to C_OPB_DWIDTH-1);
    Sln_errAck       : out std_logic;
    Sln_retry        : out std_logic;
    Sln_toutSup      : out std_logic;
    Sln_xferAck      : out std_logic;
    -- fifo ports
    opb_s_tx_en      : out std_logic;
    opb_s_tx_data    : out std_logic_vector(C_SR_WIDTH-1 downto 0);
    opb_s_rx_en      : out std_logic;
    opb_s_rx_data    : in  std_logic_vector(C_SR_WIDTH-1 downto 0);
    -- control register
    opb_ctl_reg      : out std_logic_vector(C_OPB_CTL_REG_WIDTH-1 downto 0);
    -- Fifo almost full/empty thresholds
    tx_thresh        : out std_logic_vector((2*C_FIFO_SIZE_WIDTH)-1 downto 0);
    rx_thresh        : out std_logic_vector((2*C_FIFO_SIZE_WIDTH)-1 downto 0);
    opb_fifo_flg     : in  std_logic_vector(C_NUM_FLG-1 downto 0);
    -- interrupts
    opb_dgie         : out std_logic;
    opb_ier          : out std_logic_vector(C_NUM_INT-1 downto 0);
    opb_isr          : in  std_logic_vector(C_NUM_INT-1 downto 0);
    opb_isr_clr      : out std_logic_vector(C_NUM_INT-1 downto 0);
    -- dma register
    opb_tx_dma_addr  : out std_logic_vector(C_OPB_DWIDTH-1 downto 0);
    opb_tx_dma_ctl   : out std_logic_vector(0 downto 0);
    opb_tx_dma_num   : out std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
    opb_rx_dma_addr  : out std_logic_vector(C_OPB_DWIDTH-1 downto 0);
    opb_rx_dma_ctl   : out std_logic_vector(0 downto 0);
    opb_rx_dma_num   : out std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
    -- rx crc
    opb_rx_crc_value : in  std_logic_vector(C_SR_WIDTH-1 downto 0);
    opb_tx_crc_value : in  std_logic_vector(C_SR_WIDTH-1 downto 0));
end opb_if;
 
architecture behavior of opb_if is
 
 
  signal Sln_DBus_big_end : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal OPB_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);
 
 
  type state_t is (idle,
                   done);
  signal state : state_t := idle;
 
  -- internal signals to enable readback
 
  signal tx_thresh_int : std_logic_vector((2*C_FIFO_SIZE_WIDTH)-1 downto 0);
  signal rx_thresh_int : std_logic_vector((2*C_FIFO_SIZE_WIDTH)-1 downto 0);
  signal opb_ier_int   : std_logic_vector(C_NUM_INT-1 downto 0);
  signal opb_dgie_int  : std_logic;
 
  signal opb_ctl_reg_int : std_logic_vector(C_OPB_CTL_REG_WIDTH-1 downto 0);
 
 
  -- only used if C_DMA_EN=true
  signal opb_tx_dma_addr_int : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal opb_tx_dma_ctl_int  : std_logic_vector(0 downto 0);
  signal opb_tx_dma_num_int  : std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
  signal opb_rx_dma_addr_int : std_logic_vector(C_OPB_DWIDTH-1 downto 0);
  signal opb_rx_dma_ctl_int  : std_logic_vector(0 downto 0);
  signal opb_rx_dma_num_int  : std_logic_vector(C_WIDTH_DMA_NUM-1 downto 0);
 
begin  -- behavior
 
  tx_thresh <= tx_thresh_int;
  rx_thresh <= rx_thresh_int;
  opb_ier   <= opb_ier_int;
  opb_dgie  <= opb_dgie_int;
 
  opb_ctl_reg <= opb_ctl_reg_int;
 
  --* Signals for DMA-Engine control
  u1 : if C_DMA_EN generate
    opb_tx_dma_ctl  <= opb_tx_dma_ctl_int;
    opb_tx_dma_addr <= opb_tx_dma_addr_int;
    opb_tx_dma_num  <= opb_tx_dma_num_int;
    opb_rx_dma_ctl  <= opb_rx_dma_ctl_int;
    opb_rx_dma_addr <= opb_rx_dma_addr_int;
    opb_rx_dma_num  <= opb_rx_dma_num_int;
  end generate u1;
 
 
-- unused outputs
  Sln_errAck  <= '0';
  Sln_retry   <= '0';
  Sln_toutSup <= '0';
 
  --* convert Sln_DBus_big_end  to little mode
  conv_big_Sln_DBus_proc : process(Sln_DBus_big_end)
  begin
    for i in 0 to 31 loop
      Sln_DBus(31-i) <= Sln_DBus_big_end(i);
    end loop;  -- i  
  end process conv_big_Sln_DBus_proc;
 
  --* convert OPB_ABus to big endian
  conv_big_OPB_ABus_proc : process(OPB_ABus)
  begin
    for i in 0 to 31 loop
      OPB_ABus_big_end(31-i) <= OPB_ABus(i);
    end loop;  -- i  
  end process conv_big_OPB_ABus_proc;
 
  --* convert OPB_DBus  to little mode
  conv_big_OPB_DBus_proc : 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 conv_big_OPB_DBus_proc;
 
  --* control OPB requests
  --*
  --* handles OPB-read and -write request
  opb_slave_proc : process (OPB_Rst, OPB_Clk)
  begin
    if (OPB_Rst = '1') then
      -- OPB
      Sln_xferAck      <= '0';
      Sln_DBus_big_end <= (others => '0');
      -- FIFO
      opb_s_rx_en      <= '0';
      opb_s_tx_en      <= '0';
      -- 
      state            <= idle;
      -- Register
      tx_thresh_int    <= (others => '0');
      rx_thresh_int    <= (others => '0');
      opb_ier_int      <= (others => '0');
      opb_dgie_int     <= '0';
      opb_ctl_reg_int  <= (others => '0');
 
      if C_DMA_EN then
        opb_tx_dma_ctl_int  <= (others => '0');
        opb_tx_dma_addr_int <= (others => '0');
        opb_tx_dma_num_int  <= (others => '0');
        opb_rx_dma_ctl_int  <= (others => '0');
        opb_rx_dma_addr_int <= (others => '0');
        opb_rx_dma_num_int  <= (others => '0');
      end if;
 
 
    elsif (OPB_Clk'event and OPB_Clk = '1') then
      case state is
        when idle =>
          if (OPB_select = '1' and
              ((OPB_ABus >= C_BASEADDR) and (OPB_ABus <= C_HIGHADDR))) then
            -- *device selected
            Sln_xferAck <= '1';
            state       <= done;
            if (OPB_RNW = '1') then
              -- read acess
              case OPB_ABus_big_end(7 downto 2) is
                when C_ADR_CTL =>
                  Sln_DBus_big_end(C_OPB_CTL_REG_WIDTH-1 downto 0) <= opb_ctl_reg_int;
 
                when C_ADR_RX_DATA =>
                  opb_s_rx_en                             <= '1';
                  Sln_DBus_big_end(C_SR_WIDTH-1 downto 0) <= opb_s_rx_data;
 
                when C_ADR_STATUS =>
                  Sln_DBus_big_end(C_NUM_FLG-1 downto 0) <= opb_fifo_flg;
 
                when C_ADR_TX_THRESH =>
                  Sln_DBus_big_end(C_FIFO_SIZE_WIDTH-1 downto 0)     <= tx_thresh_int(C_FIFO_SIZE_WIDTH-1 downto 0);
                  Sln_DBus_big_end(16+C_FIFO_SIZE_WIDTH-1 downto 16) <= tx_thresh_int((2*C_FIFO_SIZE_WIDTH)-1 downto C_FIFO_SIZE_WIDTH);
 
                when C_ADR_RX_THRESH =>
                  Sln_DBus_big_end(C_FIFO_SIZE_WIDTH-1 downto 0)     <= rx_thresh_int(C_FIFO_SIZE_WIDTH-1 downto 0);
                  Sln_DBus_big_end(16+C_FIFO_SIZE_WIDTH-1 downto 16) <= rx_thresh_int((2*C_FIFO_SIZE_WIDTH)-1 downto C_FIFO_SIZE_WIDTH);
 
                when C_ADR_DGIE =>
                  Sln_DBus_big_end(0) <= opb_dgie_int;
                when C_ADR_IER =>
                  Sln_DBus_big_end(C_NUM_INT-1 downto 0) <= opb_ier_int;
 
                when C_ADR_ISR =>
                  Sln_DBus_big_end(C_NUM_INT-1 downto 0) <= opb_isr;
 
                when C_ADR_TX_DMA_CTL =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(0 downto 0) <= opb_tx_dma_ctl_int;
                  end if;
 
                when C_ADR_TX_DMA_ADDR =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(C_OPB_DWIDTH-1 downto 0) <= opb_tx_dma_addr_int;
                  end if;
 
                when C_ADR_TX_DMA_NUM =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(C_WIDTH_DMA_NUM-1 downto 0) <= opb_tx_dma_num_int;
                  end if;
 
 
                when C_ADR_RX_DMA_CTL =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(0 downto 0) <= opb_rx_dma_ctl_int;
                  end if;
 
                when C_ADR_RX_DMA_ADDR =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(C_OPB_DWIDTH-1 downto 0) <= opb_rx_dma_addr_int;
                  end if;
 
                when C_ADR_RX_DMA_NUM =>
                  if C_DMA_EN then
                    Sln_DBus_big_end(C_WIDTH_DMA_NUM-1 downto 0) <= opb_rx_dma_num_int;
                  end if;
 
                when C_ADR_RX_CRC =>
                  if C_CRC_EN then
                    Sln_DBus_big_end(C_OPB_DWIDTH-1 downto C_SR_WIDTH) <= (others => '0');
                    Sln_DBus_big_end(C_SR_WIDTH-1 downto 0)            <= opb_rx_crc_value;
                  end if;
 
                when C_ADR_TX_CRC =>
                  if C_CRC_EN then
                    Sln_DBus_big_end(C_OPB_DWIDTH-1 downto C_SR_WIDTH) <= (others => '0');
                    Sln_DBus_big_end(C_SR_WIDTH-1 downto 0)            <= opb_tx_crc_value;
                  end if;
                when others =>
                  null;
              end case;
            else
              -- write acess
              case OPB_ABus_big_end(7 downto 2) is
                when C_ADR_CTL =>
                  opb_ctl_reg_int <= OPB_DBus_big_end(C_OPB_CTL_REG_WIDTH-1 downto 0);
 
                when C_ADR_TX_DATA =>
                  opb_s_tx_en   <= '1';
                  opb_s_tx_data <= OPB_DBus_big_end(C_SR_WIDTH-1 downto 0);
 
                when C_ADR_TX_THRESH =>
                  tx_thresh_int(C_FIFO_SIZE_WIDTH-1 downto 0)                     <= OPB_DBus_big_end(C_FIFO_SIZE_WIDTH-1 downto 0);
                  tx_thresh_int((2*C_FIFO_SIZE_WIDTH)-1 downto C_FIFO_SIZE_WIDTH) <= OPB_DBus_big_end(16+C_FIFO_SIZE_WIDTH-1 downto 16);
 
                when C_ADR_RX_THRESH =>
                  rx_thresh_int(C_FIFO_SIZE_WIDTH-1 downto 0)                     <= OPB_DBus_big_end(C_FIFO_SIZE_WIDTH-1 downto 0);
                  rx_thresh_int((2*C_FIFO_SIZE_WIDTH)-1 downto C_FIFO_SIZE_WIDTH) <= OPB_DBus_big_end(16+C_FIFO_SIZE_WIDTH-1 downto 16);
 
                when C_ADR_DGIE =>
                  opb_dgie_int <= OPB_DBus_big_end(0);
 
                when C_ADR_IER =>
                  opb_ier_int <= OPB_DBus_big_end(C_NUM_INT-1 downto 0);
 
                when C_ADR_ISR =>
                  opb_isr_clr <= OPB_DBus_big_end(C_NUM_INT-1 downto 0);
 
                when C_ADR_TX_DMA_CTL =>
                  if C_DMA_EN then
                    opb_tx_dma_ctl_int <= OPB_DBus_big_end(0 downto 0);
                  end if;
 
                when C_ADR_TX_DMA_ADDR =>
                  if C_DMA_EN then
                    opb_tx_dma_addr_int <= OPB_DBus_big_end(C_OPB_DWIDTH-1 downto 0);
                  end if;
 
                when C_ADR_TX_DMA_NUM =>
                  if C_DMA_EN then
                    opb_tx_dma_num_int <= OPB_DBus_big_end(C_WIDTH_DMA_NUM-1 downto 0);
                  end if;
 
                when C_ADR_RX_DMA_CTL =>
                  if C_DMA_EN then
                    opb_rx_dma_ctl_int <= OPB_DBus_big_end(0 downto 0);
                  end if;
 
                when C_ADR_RX_DMA_ADDR =>
                  if C_DMA_EN then
                    opb_rx_dma_addr_int <= OPB_DBus_big_end(C_OPB_DWIDTH-1 downto 0);
                  end if;
 
                when C_ADR_RX_DMA_NUM =>
                  if C_DMA_EN then
                    opb_rx_dma_num_int <= OPB_DBus_big_end(C_WIDTH_DMA_NUM-1 downto 0);
                  end if;
 
                when others =>
                  null;
              end case;
            end if;  -- OPB_RNW
          else
            -- not selected
            state <= idle;
          end if;
        when done =>
          opb_ctl_reg_int(3) <= '0';
          opb_isr_clr        <= (others => '0');
          opb_s_rx_en        <= '0';
          opb_s_tx_en        <= '0';
          Sln_xferAck        <= '0';
          Sln_DBus_big_end   <= (others => '0');
          state              <= idle;
 
        when others =>
          state <= idle;
      end case;
    end if;
  end process opb_slave_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.