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

Subversion Repositories wb_3p_spram_wrapper

[/] [wb_3p_spram_wrapper/] [trunk/] [wb_Np_ram.vhd] - Rev 3

Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company:       VISENGI S.L. (www.visengi.com)
-- Engineer:      Victor Lopez Lorenzo (victor.lopez (at) visengi (dot) com)
-- 
-- Create Date:    23:44:13 22/August/2008 
-- Project Name:   Triple Port WISHBONE SPRAM Wrapper
-- Tool versions:  Xilinx ISE 9.2i
-- Description: 
--
-- Description: This is a wrapper for an inferred single port RAM, that converts it
--              into a Three-port RAM with one WISHBONE slave interface for each port. 
--
--
-- LICENSE TERMS: GNU LESSER GENERAL PUBLIC LICENSE Version 2.1
--     That is you may use it in ANY project (commercial or not) without paying a cent.
--     You are only required to include in the copyrights/about section of accompanying 
--     software and manuals of use that your system contains a "3P WB SPRAM Wrapper
--     (C) VISENGI S.L. under LGPL license"
--     This holds also in the case where you modify the core, as the resulting core
--     would be a derived work.
--     Also, we would like to know if you use this core in a project of yours, just an email will do.
--
--    Please take good note of the disclaimer section of the LPGL license, as we don't
--    take any responsability for anything that this core does.
----------------------------------------------------------------------------------
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity wb_Np_ram is
      generic (data_width : integer := 32;
					addr_width : integer := 8);
      port (
			wb_clk_i: in std_logic;
         wb_rst_i: in std_logic;
 
         wb1_cyc_i : in std_logic;
         wb1_stb_i : in std_logic;
         wb1_we_i : in std_logic;
         wb1_adr_i : in std_logic_vector(addr_width-1 downto 0);
         wb1_dat_i : in std_logic_vector(data_width-1 downto 0);
			wb1_dat_o : out std_logic_vector(data_width-1 downto 0);
         wb1_ack_o : out std_logic;
 
         wb2_cyc_i : in std_logic;
         wb2_stb_i : in std_logic;
         wb2_we_i : in std_logic;
         wb2_adr_i : in std_logic_vector(addr_width-1 downto 0);
         wb2_dat_i : in std_logic_vector(data_width-1 downto 0);
			wb2_dat_o : out std_logic_vector(data_width-1 downto 0);
         wb2_ack_o : out std_logic;
 
         wb3_cyc_i : in std_logic;
         wb3_stb_i : in std_logic;
         wb3_we_i : in std_logic;
         wb3_adr_i : in std_logic_vector(addr_width-1 downto 0);
         wb3_dat_i : in std_logic_vector(data_width-1 downto 0);
			wb3_dat_o : out std_logic_vector(data_width-1 downto 0);
         wb3_ack_o : out std_logic);
end wb_Np_ram;
 
architecture Behavioral of wb_Np_ram is
   component sp_ram is --uncomment to use an inferred spram
		generic (data_width : integer := 32;
					addr_width : integer := 8);
   --component sp_ram_core is --uncomment to use the coregen spram
		port (
			clka: IN std_logic;
			wea: IN std_logic_vector(0 downto 0);
			addra: IN std_logic_vector(addr_width-1 downto 0);
			dina: IN std_logic_vector(data_width-1 downto 0);
			douta: OUT std_logic_vector(data_width-1 downto 0));
   end component;
 
   signal we: std_logic_vector(0 downto 0);
   signal a : std_logic_vector(addr_width-1 downto 0);
   signal d,q : std_logic_vector(data_width-1 downto 0);
begin
 
 
	u_sp_ram : sp_ram --uncomment to use an inferred spram
		generic map (data_width,addr_width)
   --u_sp_ram : sp_ram_core  --uncomment to use the coregen spram
		port map (
			clka => wb_clk_i,
			wea => we,
			addra => a,
			dina => d,
			douta => q);	
 
   wb1_dat_o <= q;
   wb2_dat_o <= q;
   wb3_dat_o <= q;
 
   WB_interconnect: process (wb_clk_i, wb_rst_i)
      variable ack1, ack2, ack3 : std_logic;
      variable lock : integer;
      variable State : integer;
   begin
      if (wb_rst_i = '1') then
         we(0) <= '0';
         a <= (others => '0');
         d <= (others => '0');
         ack1 := '0';
         wb1_ack_o <= '0';
         ack2 := '0';
         wb2_ack_o <= '0';
         ack3 := '0';
         wb3_ack_o <= '0';
 
         lock := 0;
         State := 0;
      elsif (wb_clk_i = '1' and wb_clk_i'event) then
         --defaults (unless overriden afterwards)
         we(0) <= '0';
 
         case State is
            when 0 => --priority for wb1
               --unlockers
               if (lock = 1 and wb1_cyc_i = '0') then lock := 0; end if;
               if (lock = 2 and wb2_cyc_i = '0') then lock := 0; end if;
               if (lock = 3 and wb3_cyc_i = '0') then lock := 0; end if;
 
               if (wb1_cyc_i = '1' and (lock = 0 or lock=1)) then --lock request (grant if lock is available)
                  ack2 := '0';
                  ack3 := '0';
                  lock := 1;
                  if (wb1_stb_i = '1' and ack1 = '0') then --operation request
                     we(0) <= wb1_we_i;
                     a <= wb1_adr_i;
                     d <= wb1_dat_i;
                     if (wb1_we_i = '1') then
                        ack1 := '1'; --ack now and stay in this state waiting for new ops
                        State := 1;
                     else
                        State := 11; --wait one cycle for operation to end
                     end if;
                  else
                     ack1 := '0'; --force one cycle wait between operations
                     --or else the wb master could issue a write, then receive two acks (first legal ack and then
                     --a spurious one due to being in the cycle where the master is still reading the first ack)
                     --followed by a read and misinterpret the spurious ack as an ack for the read
                  end if;
               elsif (wb2_cyc_i = '1' and (lock = 0 or lock=2)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack3 := '0';
                  lock := 2;
                  if (wb2_stb_i = '1' and ack2 = '0') then --operation request
                     we(0) <= wb2_we_i;
                     a <= wb2_adr_i;
                     d <= wb2_dat_i;
                     if (wb2_we_i = '1') then
                        ack2 := '1'; --ack now and stay in this state waiting for new ops
                        State := 2;
                     else
                        State := 12; --wait one cycle for operation to end
                     end if;
                  else
                     ack2 := '0'; --force one cycle wait between operations
                  end if;
               elsif (wb3_cyc_i = '1' and (lock = 0 or lock=3)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack2 := '0';
                  lock := 3;
                  if (wb3_stb_i = '1' and ack3 = '0') then --operation request
                     we(0) <= wb3_we_i;
                     a <= wb3_adr_i;
                     d <= wb3_dat_i;
                     if (wb3_we_i = '1') then
                        ack3 := '1'; --ack now and stay in this state waiting for new ops
                        State := 0;
                     else
                        State := 13; --wait one cycle for operation to end
                     end if;
                  else
                     ack3 := '0'; --force one cycle wait between operations
                  end if;
               end if;
 
            when 1 => --priority for wb2 (same code as previous State but changing the order of the if...elsifs)
               --unlockers
               if (lock = 1 and wb1_cyc_i = '0') then lock := 0; end if;
               if (lock = 2 and wb2_cyc_i = '0') then lock := 0; end if;
               if (lock = 3 and wb3_cyc_i = '0') then lock := 0; end if;
 
               if (wb2_cyc_i = '1' and (lock = 0 or lock=2)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack3 := '0';
                  lock := 2;
                  if (wb2_stb_i = '1' and ack2 = '0') then --operation request
                     we(0) <= wb2_we_i;
                     a <= wb2_adr_i;
                     d <= wb2_dat_i;
                     if (wb2_we_i = '1') then
                        ack2 := '1'; --ack now and stay in this state waiting for new ops
                        State := 2;
                     else
                        State := 12; --wait one cycle for operation to end
                     end if;
                  else
                     ack2 := '0'; --force one cycle wait between operations
                  end if;
               elsif (wb3_cyc_i = '1' and (lock = 0 or lock=3)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack2 := '0';
                  lock := 3;
                  if (wb3_stb_i = '1' and ack3 = '0') then --operation request
                     we(0) <= wb3_we_i;
                     a <= wb3_adr_i;
                     d <= wb3_dat_i;
                     if (wb3_we_i = '1') then
                        ack3 := '1'; --ack now and stay in this state waiting for new ops
                        State := 0;
                     else
                        State := 13; --wait one cycle for operation to end
                     end if;
                  else
                     ack3 := '0'; --force one cycle wait between operations
                  end if;
               elsif (wb1_cyc_i = '1' and (lock = 0 or lock=1)) then --lock request (grant if lock is available)
                  ack2 := '0';
                  ack3 := '0';
                  lock := 1;
                  if (wb1_stb_i = '1' and ack1 = '0') then --operation request
                     we(0) <= wb1_we_i;
                     a <= wb1_adr_i;
                     d <= wb1_dat_i;
                     if (wb1_we_i = '1') then
                        ack1 := '1'; --ack now and stay in this state waiting for new ops
                        State := 1;
                     else
                        State := 11; --wait one cycle for operation to end
                     end if;
                  else
                     ack1 := '0'; --force one cycle wait between operations
                  end if;
               end if;
 
            when 2 => --priority for wb3 (same code as previous State but changing the order of the if...elsifs)
               --unlockers
               if (lock = 1 and wb1_cyc_i = '0') then lock := 0; end if;
               if (lock = 2 and wb2_cyc_i = '0') then lock := 0; end if;
               if (lock = 3 and wb3_cyc_i = '0') then lock := 0; end if;
 
               if (wb3_cyc_i = '1' and (lock = 0 or lock=3)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack2 := '0';
                  lock := 3;
                  if (wb3_stb_i = '1' and ack3 = '0') then --operation request
                     we(0) <= wb3_we_i;
                     a <= wb3_adr_i;
                     d <= wb3_dat_i;
                     if (wb3_we_i = '1') then
                        ack3 := '1'; --ack now and stay in this state waiting for new ops
                        State := 0;
                     else
                        State := 13; --wait one cycle for operation to end
                     end if;
                  else
                     ack3 := '0'; --force one cycle wait between operations
                  end if;
               elsif (wb1_cyc_i = '1' and (lock = 0 or lock=1)) then --lock request (grant if lock is available)
                  ack2 := '0';
                  ack3 := '0';
                  lock := 1;
                  if (wb1_stb_i = '1' and ack1 = '0') then --operation request
                     we(0) <= wb1_we_i;
                     a <= wb1_adr_i;
                     d <= wb1_dat_i;
                     if (wb1_we_i = '1') then
                        ack1 := '1'; --ack now and stay in this state waiting for new ops
                        State := 1;
                     else
                        State := 11; --wait one cycle for operation to end
                     end if;
                  else
                     ack1 := '0'; --force one cycle wait between operations
                  end if;
               elsif (wb2_cyc_i = '1' and (lock = 0 or lock=2)) then --lock request (grant if lock is available)
                  ack1 := '0';
                  ack3 := '0';
                  lock := 2;
                  if (wb2_stb_i = '1' and ack2 = '0') then --operation request
                     we(0) <= wb2_we_i;
                     a <= wb2_adr_i;
                     d <= wb2_dat_i;
                     if (wb2_we_i = '1') then
                        ack2 := '1'; --ack now and stay in this state waiting for new ops
                        State := 2;
                     else
                        State := 12; --wait one cycle for operation to end
                     end if;
                  else
                     ack2 := '0'; --force one cycle wait between operations
                  end if;
               end if;               
 
            when 11 =>
               ack1 := '1'; --ack operation
               ack2 := '0';
               ack3 := '0';
               State := 1;
            when 12 =>
               ack1 := '0';
               ack2 := '1'; --ack operation
               ack3 := '0';
               State := 2;
            when 13 =>
               ack1 := '0';
               ack2 := '0';
               ack3 := '1'; --ack operation
               State := 0;
 
            when others => --sanity
               ack1 := '0';
               ack2 := '0';
               ack3 := '0';
               State := 0;
         end case;
 
         wb1_ack_o <= (ack1 and wb1_stb_i and wb1_cyc_i); --to don't ack aborted operations
         wb2_ack_o <= (ack2 and wb2_stb_i and wb2_cyc_i); --to don't ack aborted operations
         wb3_ack_o <= (ack3 and wb3_stb_i and wb3_cyc_i); --to don't ack aborted operations
      end if;   
   end process WB_interconnect;
end Behavioral;
 
 

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.