Saturday, 4 November 2017

VHDL Asynchronous FIFO


--=============================
-- asynchronous fifo
--=============================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fifo_async_ctrl is
   generic(DEPTH: natural:=4);
   port(
      clkw: in std_logic;
      resetw: in std_logic;
      wr: in std_logic;
      full: out std_logic;
      w_addr: out std_logic_vector (DEPTH-1 downto 0);
      clkr: in std_logic;
      resetr: in std_logic;
      rd: in std_logic;
      empty: out std_logic;
      r_addr: out std_logic_vector (DEPTH-1 downto 0)
   );
end fifo_async_ctrl ;

architecture str_arch of fifo_async_ctrl is
   signal r_ptr_in: std_logic_vector(DEPTH downto 0);
   signal r_ptr_out: std_logic_vector(DEPTH downto 0);
   signal w_ptr_in: std_logic_vector(DEPTH downto 0);
   signal w_ptr_out: std_logic_vector(DEPTH downto 0);
   -- component declarations
   component fifo_read_ctrl
      generic(N: natural);
      port(
         clkr: in std_logic;
         rd: in std_logic;
         resetr: in std_logic;
         w_ptr_in: in std_logic_vector (N downto 0);
         empty: out std_logic;
         r_addr: out std_logic_vector (N-1 downto 0);
      r_ptr_out: out std_logic_vector (N downto 0)
      );
   end component;
   component fifo_write_ctrl
      generic(N: natural);
      port(
         clkw: in std_logic;
         r_ptr_in: in std_logic_vector (N downto 0);
         resetw: in std_logic;
         wr: in std_logic;
         full: out std_logic;
         w_addr: out std_logic_vector (N-1 downto 0);
         w_ptr_out: out std_logic_vector (N downto 0)
      );
   end component;
   component synchronizer_g
      generic(N: natural);
      port(
         clk: in std_logic;
         in_async: in std_logic_vector (N-1 downto 0);
         reset: in std_logic;
         out_sync: out std_logic_vector (N-1 downto 0)
      );
   end component;
begin
   read_ctrl: fifo_read_ctrl
      generic map(N=>DEPTH)
      port map (clkr=>clkr, resetr=>resetr, rd=>rd,
                w_ptr_in=>w_ptr_in, empty=>empty,
                r_ptr_out=>r_ptr_out, r_addr=>r_addr);
   write_ctrl: fifo_write_ctrl
      generic map(N =>DEPTH)
      port map(clkw=>clkw, resetw=>resetw, wr=>wr,
               r_ptr_in=>r_ptr_in, full=>full,
               w_ptr_out=>w_ptr_out, w_addr=>w_addr);
   sync_w_ptr: synchronizer_g
      generic map(N=>DEPTH+1)
      port map(clk=>clkw, reset=>resetw,
               in_async=>w_ptr_out, out_sync=>w_ptr_in);
   sync_r_ptr: synchronizer_g
      generic map(N=>DEPTH+1)
      port map(clk=>clkr, reset=>resetr,
               in_async=>r_ptr_out, out_sync =>r_ptr_in);
end str_arch;

--=============================
--  FIFO read port
--=============================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fifo_read_ctrl is
   generic(N: natural:=4);
   port(
      clkr, resetr: in std_logic;
      w_ptr_in: in std_logic_vector(N downto 0);
      rd: in std_logic;
      empty: out std_logic;
      r_ptr_out: out std_logic_vector(N downto 0);
      r_addr: out std_logic_vector(N-1 downto 0)
   );
end fifo_read_ctrl;

architecture gray_arch of fifo_read_ctrl is
   signal r_ptr_reg, r_ptr_next: std_logic_vector(N downto 0);
   signal gray1, bin, bin1: std_logic_vector(N downto 0);
   signal raddr_all: std_logic_vector(N-1 downto 0);
   signal raddr_msb,waddr_msb: std_logic;
   signal empty_flag: std_logic;
begin
   -- register
   process(clkr,resetr)
   begin
      if (resetr='1') then
         r_ptr_reg <= (others=>'0');
      elsif (clkr'event and clkr='1') then
         r_ptr_reg <= r_ptr_next;
      end if;
   end process;
   -- (N+1)-bit Gray counter
   bin <= r_ptr_reg xor ('0' & bin(N downto 1));
   bin1 <= std_logic_vector(unsigned(bin) + 1);
   gray1 <= bin1 xor ('0' & bin1(N downto 1));
   -- update read pointer
   r_ptr_next <= gray1 when rd='1' and empty_flag='0' else
                 r_ptr_reg;
   -- N-bit Gray counter
   raddr_msb <= r_ptr_reg(N) xor r_ptr_reg(N-1);
   raddr_all <= raddr_msb & r_ptr_reg(N-2 downto 0);
   waddr_msb <= w_ptr_in(N) xor w_ptr_in(N-1);
   -- check for FIFO empty
   empty_flag <=
      '1' when w_ptr_in(N)=r_ptr_reg(N) and
          w_ptr_in(N-2 downto 0)=r_ptr_reg(N-2 downto 0) and
          raddr_msb = waddr_msb else
      '0';
    -- output
    r_addr <= raddr_all;
    r_ptr_out <= r_ptr_reg;
    empty <= empty_flag;
end gray_arch;

--=============================
-- FIFO write port
--=============================
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fifo_write_ctrl is
   generic(N: natural:=4);
   port(
      clkw, resetw: in std_logic;
      wr: in std_logic;
      r_ptr_in: in std_logic_vector(N downto 0);
      full: out std_logic;
      w_ptr_out: out std_logic_vector(N downto 0);
      w_addr: out std_logic_vector(N-1 downto 0)
   );
end fifo_write_ctrl;

architecture gray_arch of fifo_write_ctrl is
   signal w_ptr_reg, w_ptr_next:
      std_logic_vector(N downto 0);
   signal gray1, bin, bin1: std_logic_vector(N downto 0);
   signal waddr_all: std_logic_vector(N-1 downto 0);
   signal waddr_msb, raddr_msb: std_logic;
   signal full_flag: std_logic;
begin
   -- register
   process(clkw,resetw)
   begin
      if (resetw='1') then
          w_ptr_reg <= (others=>'0');
      elsif (clkw'event and clkw='1') then
         w_ptr_reg <= w_ptr_next;
      end if;
   end process;
   -- (N+1)-bit Gray counter
   bin <= w_ptr_reg xor ('0' & bin(N downto 1));
   bin1 <= std_logic_vector(unsigned(bin) + 1);
   gray1 <= bin1 xor ('0' & bin1(N downto 1));
   -- update write pointer
   w_ptr_next <= gray1 when wr='1' and full_flag='0' else
                 w_ptr_reg;
   -- N-bit Gray counter
   waddr_msb <=  w_ptr_reg(N) xor w_ptr_reg(N-1);
   waddr_all <= waddr_msb & w_ptr_reg(N-2 downto 0);
   -- check for FIFO full
   raddr_msb <= r_ptr_in(N) xor r_ptr_in(N-1);
   full_flag <=
     '1' when r_ptr_in(N) /=w_ptr_reg(N) and
         r_ptr_in(N-2 downto 0)=w_ptr_reg(N-2 downto 0) and
         raddr_msb = waddr_msb else
     '0';
   -- output
   w_addr <= waddr_all;
   w_ptr_out <= w_ptr_reg;
   full <= full_flag;
end gray_arch;

--=============================
-- WRITE parameterized synchronizer
--=============================
library ieee;
use ieee.std_logic_1164.all;
entity synchronizer_g is
   generic(N: natural);
   port(
      clk, reset: in std_logic;
      in_async: in std_logic_vector(N-1 downto 0);
      out_sync: out std_logic_vector(N-1 downto 0)
   );
end synchronizer_g;

architecture two_ff_arch of synchronizer_g is
   signal meta_reg, sync_reg: std_logic_vector(N-1 downto 0);
   signal meta_next, sync_next:
      std_logic_vector(N-1 downto 0);
begin
   -- two registers
   process(clk,reset)
   begin
      if (reset='1') then
         meta_reg <= (others=>'0');
         sync_reg <= (others=>'0');
      elsif (clk'event and clk='1') then
         meta_reg <= meta_next;
         sync_reg <= sync_next;
      end if;
   end process;
   -- next-state logic
   meta_next <= in_async;
   sync_next <= meta_reg;
   -- output
   out_sync <= sync_reg;
end two_ff_arch;

--=============================
-- READ parameterized synchronizer
--=============================
library ieee;
use ieee.std_logic_1164.all;
entity synchronizer_g is
   generic(N: natural);
   port(
      clk, reset: in std_logic;
      in_async: in std_logic_vector(N-1 downto 0);
      out_sync: out std_logic_vector(N-1 downto 0)
   );
end synchronizer_g;

architecture two_ff_arch of synchronizer_g is
   signal meta_reg, sync_reg: std_logic_vector(N-1 downto 0);
   signal meta_next, sync_next:
      std_logic_vector(N-1 downto 0);
begin
   -- two registers
   process(clk,reset)
   begin
      if (reset='1') then
         meta_reg <= (others=>'0');
         sync_reg <= (others=>'0');
      elsif (clk'event and clk='1') then
         meta_reg <= meta_next;
         sync_reg <= sync_next;
      end if;
   end process;
   -- next-state logic
   meta_next <= in_async;
   sync_next <= meta_reg;
   -- output
   out_sync <= sync_reg;
end two_ff_arch;

3 comments:

  1. Casino - MapyRO
    Casino Casino is a casino in Maricopa, 이천 출장마사지 Arizona. Read 광명 출장안마 reviews, see photos, see special 전라남도 출장마사지 offers, and 김천 출장안마 learn more 상주 출장샵 about it. Rating: 2.3 · ‎9 votes

    ReplyDelete
  2. where is code for memory buffer

    ReplyDelete
  3. @Anonymous - the data path here is just a single bit (top-level signals wr, rd are std_logic), but it can be converted to handle any data width by replacing wr and rd with some std_logic_vector (or any other array type). Then add a dual-port RAM component and use w_addr and r_addr as the index into the RAM.

    ReplyDelete