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/] [shift_register.vhd] - Rev 38

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

-------------------------------------------------------------------------------
--* 
--* @short Shift-Register
--* 
--* Control Register Description:
--* @li Bit0: DGE  :  Global Device Enable
--* @li Bit1: TX_EN:  Transmit enable
--* @li Bit2: RX_EN:  Receive enable
--*
--* Generics described in top entity.
--* @port opb_ctl_reg Control Register
--*
--* @see opb_spi_slave
--*    @author: Daniel Köthe
--*   @version: 1.1
--* @date: 2007-11-11
--/
-- Version 1.0 Initial Release
-- Version 1.1 rx_cnt/tx_cnt only increment if < C_SR_WIDTH
-- Version 1.2 removed delays for simulation
-------------------------------------------------------------------------------
 
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
 
library work;
use work.opb_spi_slave_pack.all;
 
entity shift_register is
 
  generic (
    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);
 
  port (
    rst         : in  std_logic;
    -- control register
    opb_ctl_reg : in  std_logic_vector(C_OPB_CTL_REG_WIDTH-1 downto 0);
    -- external 
    sclk        : in  std_logic;
    ss_n        : in  std_logic;
    mosi        : in  std_logic;
    miso_o      : out std_logic;
    miso_i      : in  std_logic;
    miso_t      : out std_logic;
    -- transmit fifo
    sr_tx_clk   : out std_logic;
    sr_tx_en    : out std_logic;
    sr_tx_data  : in  std_logic_vector(C_SR_WIDTH-1 downto 0);
    -- receive fifo
    sr_rx_clk   : out std_logic;
    sr_rx_en    : out std_logic;
    sr_rx_data  : out std_logic_vector(C_SR_WIDTH-1 downto 0));    
end shift_register;
 
 
architecture behavior of shift_register is
  --* Global
  signal sclk_int     : std_logic;
  signal sclk_int_inv : std_logic;
  signal rx_cnt       : integer range 0 to 31 := 0;
 
  -- RX
  signal rx_sr_reg      : std_logic_vector(C_SR_WIDTH-2 downto 0);
  signal sr_rx_en_int   : std_logic;
  signal sr_rx_data_int : std_logic_vector(C_SR_WIDTH-1 downto 0);
 
  -- tx
  signal miso_int       : std_logic;
  signal tx_cnt         : integer range 0 to 31 := 0;
  signal sr_tx_en_int   : std_logic;
  signal sr_tx_data_int : std_logic_vector(C_SR_WIDTH-1 downto 0);
 
 
begin  -- behavior
 
  miso_t <= ss_n;                       -- tristate
 
 
  sclk_int <= sclk when (C_PHA = 0 and C_CPOL = 0) else
              sclk when (C_PHA = 1 and C_CPOL = 1) else
              not sclk;
 
 
  sr_rx_en <= sr_rx_en_int;
  sr_tx_en <= sr_tx_en_int;
 
  --* reorder received bits if not "MSB_First"
  reorder_rx_bits : process(sr_rx_data_int)
  begin
    for i in 0 to C_SR_WIDTH-1 loop
      if C_MSB_FIRST then
        sr_rx_data(i) <= sr_rx_data_int(i);
      else
        sr_rx_data(C_SR_WIDTH-1-i) <= sr_rx_data_int(i);
      end if;
    end loop;  -- i
  end process reorder_rx_bits;
 
  --* reorder transmit bits if not "MSB_First" 
  reorder_tx_bits : process(sr_tx_data)
  begin
    for i in 0 to C_SR_WIDTH-1 loop
      if C_MSB_FIRST then
        sr_tx_data_int(i) <= sr_tx_data(i);
      else
        sr_tx_data_int(C_SR_WIDTH-1-i) <= sr_tx_data(i);
      end if;
    end loop;  -- i
  end process reorder_tx_bits;
 
 
  -----------------------------------------------------------------------------
 
  sr_rx_clk <= sclk_int;
 
  sr_rx_data_int <= rx_sr_reg & mosi;
 
  --* RX-Shift-Register
  rx_shift_proc : process(rst, opb_ctl_reg, sclk_int)
  begin
    if (rst = '1' or opb_ctl_reg(C_OPB_CTL_REG_DGE) = '0' or opb_ctl_reg(C_OPB_CTL_REG_RX_EN) = '0') then
      rx_cnt       <= 0;
      sr_rx_en_int <= '0';
      rx_sr_reg    <= (others => '0');
 
    elsif rising_edge(sclk_int) then
      if (ss_n = '0') then
        rx_sr_reg <= rx_sr_reg(C_SR_WIDTH-3 downto 0) & mosi;
        if (rx_cnt = C_SR_WIDTH-2) then
          rx_cnt       <= rx_cnt +1;
          sr_rx_en_int <= '1';
          elsif (rx_cnt = C_SR_WIDTH-1) then
            rx_cnt       <= 0;
            sr_rx_en_int <= '0';
          else
            rx_cnt <= rx_cnt +1;
          end if;
        else
          -- ss_n high
          -- assert framing error if cnt != 0?
          sr_rx_en_int <= '0';
          rx_cnt       <= 0;
        end if;
      end if;
    end process rx_shift_proc;
 
-------------------------------------------------------------------------------
      -- TX Shift Register
      sr_tx_clk    <= sclk_int_inv;
      sclk_int_inv <= not sclk_int;
 
      miso_o <= sr_tx_data_int(C_SR_WIDTH-1) when (tx_cnt = 0) else
                miso_int;
 
 
      --* TX Shift-Register
      tx_shift_proc : process(rst, opb_ctl_reg, sclk_int_inv)
      begin
        if (rst = '1' or opb_ctl_reg(C_OPB_CTL_REG_DGE) = '0' or opb_ctl_reg(C_OPB_CTL_REG_TX_EN) = '0') then
          tx_cnt       <= 0;
          sr_tx_en_int <= '0';
          miso_int     <= '0';
        elsif rising_edge(sclk_int_inv) then
          if (ss_n = '0') then
            if (tx_cnt /= C_SR_WIDTH-1) then
              miso_int <= sr_tx_data_int(C_SR_WIDTH-1-(tx_cnt+1));
            end if;
            if (tx_cnt = C_SR_WIDTH-2) then
              sr_tx_en_int <= '1';
              tx_cnt       <= tx_cnt +1;
              elsif (tx_cnt = C_SR_WIDTH-1) then
                tx_cnt       <= 0;
                sr_tx_en_int <= '0';
              else
                tx_cnt <= tx_cnt +1;
              end if;
            else
              -- ss_n high
              -- assert framing error if cnt != 0?
              sr_tx_en_int <= '0';
              tx_cnt       <= 0;
            end if;
          end if;
        end process tx_shift_proc;
-------------------------------------------------------------------------------
 
        end behavior;
 

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.