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

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

-------------------------------------------------------------------------------
--* 
--* @short Configurable FIFO
--* 
--* @generic C_FIFO_WIDTH       RAM-With (1..xx)
--* @generic C_FIFO_SIZE_WIDTH  RAM Size = 2**C_FIFO_SIZE_WIDTH
--* @generic C_SYNC_TO          Sync FIFO Flags to read or write clock
--*
--*    @author: Daniel Köthe
--*   @version: 1.0
--* @date:      2007-11-11
--/
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
 
 
entity fifo is
  generic (
    C_FIFO_WIDTH      : integer := 8;
    C_FIFO_SIZE_WIDTH : integer := 4;
    C_SYNC_TO         : string  := "RD");
  port (
    rst               : in  std_logic;
    -- write port
    wr_clk            : in  std_logic;
    wr_en             : in  std_logic;
    din               : in  std_logic_vector(C_FIFO_WIDTH-1 downto 0);
    -- read port
    rd_clk            : in  std_logic;
    rd_en             : in  std_logic;
    dout              : out std_logic_vector(C_FIFO_WIDTH-1 downto 0);
    -- flags    
    empty             : out std_logic;
    full              : out std_logic;
    overflow          : out std_logic;
    underflow         : out std_logic;
    prog_empty_thresh : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
    prog_full_thresh  : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
    prog_empty        : out std_logic;
    prog_full         : out std_logic);
 
end fifo;
 
architecture behavior of fifo is
  --* ram with sync write and async read
  component ram
    generic (
      C_FIFO_WIDTH      : integer := 8;
      C_FIFO_SIZE_WIDTH : integer := 4);
    port (
      clk  : in  std_logic;
      we   : in  std_logic;
      a    : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      dpra : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      di   : in  std_logic_vector(C_FIFO_WIDTH-1 downto 0);
      dpo  : out std_logic_vector(C_FIFO_WIDTH-1 downto 0));
  end component;
 
  --* component generates fifo flag
  component fifo_prog_flags
    generic (
      C_FIFO_SIZE_WIDTH : integer;
      C_SYNC_TO         : string);
    port (
      rst               : in  std_logic;
      clk               : in  std_logic;
      cnt_grey          : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      cnt               : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      prog_full_thresh  : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      prog_empty_thresh : in  std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
      prog_empty        : out std_logic;
      prog_full         : out std_logic);
  end component;
 
  --* logic coded gray counter
  component gray_adder
    generic (
      width : integer);
    port (
      in_gray  : in  std_logic_vector(width-1 downto 0);
      out_gray : out std_logic_vector(width-1 downto 0));
  end component;
 
  signal wr_cnt_gray_add_one      : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  signal wr_cnt_next_grey_add_one : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  signal rd_cnt_grey_add_one      : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
 
  attribute fsm_extract                : string;
  -- wr_clock domain
  -- main wr grey code counter
  signal wr_cnt_grey                   : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  attribute fsm_extract of wr_cnt_grey : signal is "no";
 
  -- main grey code counter for full
  signal wr_cnt_next_grey                   : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  attribute fsm_extract of wr_cnt_next_grey : signal is "no";
 
  -- rd_clk domain
  -- main rd grey code counter
  signal rd_cnt_grey                   : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  attribute fsm_extract of rd_cnt_grey : signal is "no";
 
  -- binary counter for prog full/empty
  signal rd_cnt : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
  signal wr_cnt : std_logic_vector(C_FIFO_SIZE_WIDTH-1 downto 0);
 
  signal empty_int : std_logic;
  signal full_int  : std_logic;
 
begin  -- behavior
 
  empty <= empty_int;
  full  <= full_int;
 
--* write counter generation
  fifo_write_proc: process(rst, wr_clk)
  begin
    if (rst = '1') then
      wr_cnt_grey                                    <= (others => '0');
      wr_cnt                                         <= (others => '0');
      wr_cnt_next_grey(C_FIFO_SIZE_WIDTH-1 downto 1) <= (others => '0');
      wr_cnt_next_grey(0)                            <= '1';
    elsif rising_edge(wr_clk) then
      if (wr_en = '1') then
        wr_cnt <= wr_cnt+1;
 
        -- wr_cnt_grey      <= add_grey_rom(conv_integer(wr_cnt_grey));
        wr_cnt_grey <= wr_cnt_gray_add_one;
 
        -- wr_cnt_next_grey <= add_grey_rom(conv_integer(wr_cnt_next_grey));
        wr_cnt_next_grey <= wr_cnt_next_grey_add_one;
 
      end if;
    end if;
  end process fifo_write_proc;
 
  --* add one to wr_cnt_gray
  gray_adder_1 : gray_adder
    generic map (
      width => C_FIFO_SIZE_WIDTH)
    port map (
      in_gray  => wr_cnt_grey,
      out_gray => wr_cnt_gray_add_one);
 
  --* add one to wr_cnt_next_grey
  gray_adder_2 : gray_adder
    generic map (
      width => C_FIFO_SIZE_WIDTH)
    port map (
      in_gray  => wr_cnt_next_grey,
      out_gray => wr_cnt_next_grey_add_one);    
 
 
--* read counter generation
  fifo_read_proc: process(rst, rd_clk)
  begin
    if (rst = '1') then
      rd_cnt_grey <= (others => '0');
      rd_cnt      <= (others => '0');
    elsif rising_edge(rd_clk) then
      -- rd grey code counter
      if (rd_en = '1') then
        -- rd_cnt_grey <= add_grey_rom(conv_integer(rd_cnt_grey));
        rd_cnt_grey <= rd_cnt_grey_add_one;
        rd_cnt      <= rd_cnt+1;
      end if;
    end if;
  end process fifo_read_proc;
 
  --* add one to rd_cnt_grey 
  gray_adder_3 : gray_adder
    generic map (
      width => C_FIFO_SIZE_WIDTH)
    port map (
      in_gray  => rd_cnt_grey,
      out_gray => rd_cnt_grey_add_one);    
 
 
  --* FIFO Memory
  ram_1 : ram
    generic map (
      C_FIFO_WIDTH      => C_FIFO_WIDTH,
      C_FIFO_SIZE_WIDTH => C_FIFO_SIZE_WIDTH)
    port map (
      clk  => wr_clk,
      we   => wr_en,
      a    => wr_cnt_grey,
      di   => din,
      dpra => rd_cnt_grey,
      dpo  => dout);
 
 
  --* generate overflow
  gen_of_proc: process(rst, wr_clk)
  begin
    if (rst = '1') then
      overflow <= '0';
    elsif rising_edge(wr_clk) then
      if (full_int = '1' and wr_en = '1') then
        overflow <= '1';
      end if;
    end if;
  end process gen_of_proc;
 
  --* generate underflow
  gen_uf_proc: process(rst, rd_clk)
  begin
    if (rst = '1') then
      underflow <= '0';
    elsif rising_edge(rd_clk) then
      if (empty_int = '1' and rd_en = '1') then
        underflow <= '1';
      end if;
    end if;
  end process gen_uf_proc;
 
  -- generate empty
  empty_int <= '1' when (wr_cnt_grey = rd_cnt_grey) else
               '0';
 
  -- generate full
  full_int <= '1' when (wr_cnt_next_grey = rd_cnt_grey) else
              '0';
 
  --* select clock side for flags
  u1 : if (C_SYNC_TO = "WR") generate
  --* sync flags to write clock
    fifo_prog_flags_1 : fifo_prog_flags
      generic map (
        C_FIFO_SIZE_WIDTH => C_FIFO_SIZE_WIDTH,
        C_SYNC_TO         => C_SYNC_TO)
      port map (
        rst               => rst,
        clk               => wr_clk,
        cnt_grey          => rd_cnt_grey,
        cnt               => wr_cnt,
        prog_full_thresh  => prog_full_thresh,
        prog_empty_thresh => prog_empty_thresh,
        prog_empty        => prog_empty,
        prog_full         => prog_full);
  end generate u1;
 
  u2 : if (C_SYNC_TO = "RD") generate
  --* sync flags to read clock
    fifo_prog_flags_1 : fifo_prog_flags
      generic map (
        C_FIFO_SIZE_WIDTH => C_FIFO_SIZE_WIDTH,
        C_SYNC_TO         => C_SYNC_TO)
      port map (
        rst               => rst,
        clk               => rd_clk,
        cnt_grey          => wr_cnt_grey,
        cnt               => rd_cnt,
        prog_full_thresh  => prog_full_thresh,
        prog_empty_thresh => prog_empty_thresh,
        prog_empty        => prog_empty,
        prog_full         => prog_full);    
  end generate u2;
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.