DS_DMA
pcie_src/pcie_core64_m1/source_virtex6/pcie_bram_v6.vhd
00001 -------------------------------------------------------------------------------
00002 --
00003 -- (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved.
00004 --
00005 -- This file contains confidential and proprietary information
00006 -- of Xilinx, Inc. and is protected under U.S. and
00007 -- international copyright and other intellectual property
00008 -- laws.
00009 --
00010 -- DISCLAIMER
00011 -- This disclaimer is not a license and does not grant any
00012 -- rights to the materials distributed herewith. Except as
00013 -- otherwise provided in a valid license issued to you by
00014 -- Xilinx, and to the maximum extent permitted by applicable
00015 -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
00016 -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
00017 -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
00018 -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
00019 -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
00020 -- (2) Xilinx shall not be liable (whether in contract or tort,
00021 -- including negligence, or under any other theory of
00022 -- liability) for any loss or damage of any kind or nature
00023 -- related to, arising under or in connection with these
00024 -- materials, including for any direct, or any indirect,
00025 -- special, incidental, or consequential loss or damage
00026 -- (including loss of data, profits, goodwill, or any type of
00027 -- loss or damage suffered as a result of any action brought
00028 -- by a third party) even if such damage or loss was
00029 -- reasonably foreseeable or Xilinx had been advised of the
00030 -- possibility of the same.
00031 --
00032 -- CRITICAL APPLICATIONS
00033 -- Xilinx products are not designed or intended to be fail-
00034 -- safe, or for use in any application requiring fail-safe
00035 -- performance, such as life-support or safety devices or
00036 -- systems, Class III medical devices, nuclear facilities,
00037 -- applications related to the deployment of airbags, or any
00038 -- other applications that could lead to death, personal
00039 -- injury, or severe property or environmental damage
00040 -- (individually and collectively, "Critical
00041 -- Applications"). Customer assumes the sole risk and
00042 -- liability of any use of Xilinx products in Critical
00043 -- Applications, subject only to applicable laws and
00044 -- regulations governing limitations on product liability.
00045 --
00046 -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
00047 -- PART OF THIS FILE AT ALL TIMES.
00048 --
00049 -------------------------------------------------------------------------------
00050 -- Project    : Virtex-6 Integrated Block for PCI Express
00051 -- File       : pcie_bram_v6.vhd
00052 -- Version    : 2.3
00053 --
00054 -- Description: BlockRAM module for Virtex6 PCIe Block
00055 --
00056 --------------------------------------------------------------------------------
00057 
00058 library ieee;
00059    use ieee.std_logic_1164.all;
00060    use ieee.std_logic_unsigned.all;
00061 
00062 library unisim;
00063 use unisim.vcomponents.all;
00064 
00065 entity pcie_bram_v6 is
00066    generic (
00067       DOB_REG                              : integer := 0;              -- 1 use the output register 0 don't use the output register
00068       WIDTH                                : integer := 0               -- supported WIDTH's are: 4, 9, 18, 36 (uses RAMB36) and 72 (uses RAMB36SDP)
00069    );
00070    port (
00071 
00072       user_clk_i                           : in std_logic;                              -- user clock
00073       reset_i                              : in std_logic;                              -- bram reset
00074       wen_i                                : in std_logic;                              -- write enable
00075       waddr_i                              : in std_logic_vector(12 downto 0);          -- write address
00076       wdata_i                              : in std_logic_vector(WIDTH - 1 downto 0);   -- write data
00077       ren_i                                : in std_logic;                              -- read enable
00078       rce_i                                : in std_logic;                              -- output register clock enable
00079       raddr_i                              : in std_logic_vector(12 downto 0);          -- read address
00080       rdata_o                              : out std_logic_vector(WIDTH - 1 downto 0)   -- read data
00081    );
00082 end pcie_bram_v6;
00083 
00084 architecture v6_pcie of pcie_bram_v6 is
00085 
00086   -- map the address bits
00087   function msb_addr (
00088     constant wdt   : integer)
00089     return integer is
00090      variable addr_msb : integer := 8;
00091   begin  -- msb_addr
00092 
00093     if (wdt = 4) then
00094       addr_msb := 12;
00095     elsif (wdt = 9) then
00096       addr_msb := 11;
00097     elsif (wdt = 18) then
00098       addr_msb := 10;
00099     elsif (wdt = 36) then
00100       addr_msb := 9;
00101     else
00102       addr_msb := 8;
00103     end if;
00104     return addr_msb;
00105   end msb_addr;
00106 
00107       constant ADDR_MSB                    : integer := msb_addr(WIDTH);
00108       
00109       -- set the width of the tied off low address bits
00110   function alb (
00111     constant wdt   : integer)
00112     return integer is
00113      variable addr_lo_bit : integer := 8;
00114   begin  -- alb
00115 
00116     if (wdt = 4) then
00117       addr_lo_bit := 2;
00118     elsif (wdt = 9) then
00119       addr_lo_bit := 3;
00120     elsif (wdt = 18) then
00121       addr_lo_bit := 4;
00122     elsif (wdt = 36) then
00123       addr_lo_bit := 5;
00124     else
00125       addr_lo_bit := 0;      -- for WIDTH 72 use RAMB36SDP
00126     end if;
00127     return addr_lo_bit;
00128   end alb;
00129 
00130       constant ADDR_LO_BITS                : integer := alb(WIDTH);
00131 
00132       -- map the data bits
00133   function msb_d (
00134     constant wdt   : integer)
00135     return integer is
00136      variable dmsb : integer := 8;
00137   begin  -- msb_d
00138 
00139     if (wdt = 4) then
00140       dmsb := 3;
00141     elsif (wdt = 9) then
00142       dmsb := 7;
00143     elsif (wdt = 18) then
00144       dmsb := 15;
00145     elsif (wdt = 36) then
00146       dmsb := 31;
00147     else
00148       dmsb := 63;
00149     end if;
00150     return dmsb;
00151   end msb_d;
00152 
00153       constant D_MSB                       : integer :=  msb_d(WIDTH);
00154       
00155       -- map the data parity bits
00156       constant DP_LSB                      : integer := D_MSB + 1;
00157       
00158   function msb_dp (
00159     constant wdt   : integer)
00160     return integer is
00161      variable dpmsb : integer := 8;
00162   begin  -- msb_dp
00163 
00164     if (wdt = 4) then
00165       dpmsb := 4;
00166     elsif (wdt = 9) then
00167       dpmsb := 8;
00168     elsif (wdt = 18) then
00169       dpmsb := 17;
00170     elsif (wdt = 36) then
00171       dpmsb := 35;
00172     else
00173       dpmsb := 71;
00174     end if;
00175     return dpmsb;
00176   end msb_dp;
00177 
00178   function pad_val (
00179     in_vec   : std_logic_vector;
00180     range_hi : integer;
00181     range_lo : integer;
00182     pad      : std_logic;
00183     op_len   : integer)
00184     return std_logic_vector is 
00185    variable ret : std_logic_vector(op_len-1 downto 0) := (others => '0');
00186   begin  -- pad_val
00187     for i in 0 to op_len-1 loop
00188       if ((i >= range_lo) and (i <= range_hi)) then
00189         ret(i) := in_vec(i - range_lo);
00190       else
00191         ret(i) := pad;
00192       end if;
00193     end loop;  -- i
00194     return ret;
00195   end pad_val;
00196 
00197   constant DP_MSB                      : integer :=  msb_dp(WIDTH);
00198       
00199       constant DPW                         : integer := DP_MSB - DP_LSB + 1;
00200       
00201       constant WRITE_MODE                  : string := "NO_CHANGE";
00202 
00203     -- ground and tied_to_vcc_i signals
00204     signal  tied_to_ground_i                :   std_logic;
00205     signal  tied_to_ground_vec_i            :   std_logic_vector(31 downto 0);
00206     signal  tied_to_vcc_i                   :   std_logic;
00207 
00208 
00209    -- X-HDL generated signals
00210 
00211    signal v6pcie2 : std_logic_vector(7 downto 0) := (others => '0');
00212    signal v6pcie5 : std_logic_vector(15 downto 0) := (others => '0');
00213    signal v6pcie7 : std_logic_vector(15 downto 0) := (others => '0');
00214    signal v6pcie11 : std_logic_vector(31 downto 0) := (others => '0');
00215    signal v6pcie12 : std_logic_vector(3 downto 0) := (others => '0');
00216    signal v6pcie15 : std_logic_vector(63 downto 0) := (others => '0');
00217    signal v6pcie16 : std_logic_vector(7 downto 0) := (others => '0');
00218    signal v6pcie13 : std_logic_vector((DP_MSB - DP_LSB) downto 0) := (others => '0');
00219 
00220       -- dob_unused and dopb_unused only needed when WIDTH < 36. how to declare
00221 -- these accordingly.
00222    signal dob_unused : std_logic_vector(31 - D_MSB - 1 downto 0);
00223    signal dopb_unused : std_logic_vector(4 - DPW - 1 downto 0);
00224 
00225       
00226    -- Declare intermediate signals for referenced outputs
00227    signal rdata_o_v6pcie0                  : std_logic_vector(WIDTH - 1 downto 0);
00228 
00229 begin
00230 
00231   ---------------------------  Static signal Assignments ---------------------
00232 
00233     tied_to_ground_i                    <= '0';
00234     tied_to_ground_vec_i(31 downto 0)   <= (others => '0');
00235     tied_to_vcc_i                       <= '1';
00236 
00237    -- Drive referenced outputs
00238    rdata_o <= rdata_o_v6pcie0;
00239    
00240    --synthesis translate_off
00241    process 
00242    begin
00243       --$display("[%t] %m DOB_REG %0d WIDTH %0d ADDR_MSB %0d ADDR_LO_BITS %0d DP_MSB %0d DP_LSB %0d D_MSB %0d",
00244       --          $time, DOB_REG,   WIDTH,    ADDR_MSB,    ADDR_LO_BITS,    DP_MSB,    DP_LSB,    D_MSB);
00245       
00246       case WIDTH is
00247          when 4 | 9 | 18 | 36 | 72 =>
00248          when others =>         -- case (WIDTH)
00249             -- $display("[%t] %m Error WIDTH %0d not supported", now, to_stdlogic(WIDTH));
00250             -- $finish();
00251       end case;
00252       wait;
00253    end process;
00254    
00255    --synthesis translate_on
00256    
00257    use_ramb36sdp : if (WIDTH = 72) generate
00258       
00259       v6pcie2 <= (others => wen_i);
00260       rdata_o_v6pcie0 <= v6pcie16((DP_MSB - DP_LSB) downto 0) & v6pcie15(D_MSB downto 0);
00261 
00262       -- use RAMB36SDP if the width is 72
00263       ramb36sdp_i : RAMB36SDP
00264          generic map (
00265             DO_REG  => DOB_REG
00266          )
00267          port map (
00268             DBITERR => open,
00269             ECCPARITY => open,
00270             SBITERR => open,
00271             WRCLK   => user_clk_i ,
00272             SSR     => '0',
00273             WRADDR  => waddr_i(ADDR_MSB downto 0),
00274             DI      => wdata_i(D_MSB downto 0),
00275             DIP     => wdata_i(DP_MSB downto DP_LSB),
00276             WREN    => wen_i,
00277             WE      => v6pcie2,
00278             
00279             RDCLK   => user_clk_i,
00280             RDADDR  => raddr_i(ADDR_MSB downto 0),
00281             DO      => v6pcie15,
00282             DOP     => v6pcie16,
00283             RDEN    => ren_i,
00284             REGCE   => rce_i
00285          );
00286       
00287       -- use RAMB36's if the width is 4, 9, 18, or 36   
00288    end generate;
00289    use_ramb36_1 : if (WIDTH = 36) generate
00290 
00291       v6pcie2 <= (others => wen_i);
00292       v6pcie5 <= pad_val(waddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00293       v6pcie7 <= pad_val(raddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00294       rdata_o_v6pcie0 <= v6pcie16((DP_MSB - DP_LSB) downto 0) & v6pcie15(D_MSB downto 0);
00295 
00296       ramb36_i : RAMB36
00297          generic map (
00298             DOA_REG        => 0,
00299             DOB_REG        => DOB_REG,
00300             READ_WIDTH_A   => 0,
00301             READ_WIDTH_B   => WIDTH,
00302             WRITE_WIDTH_A  => WIDTH,
00303             WRITE_WIDTH_B  => 0,
00304             WRITE_MODE_A   => WRITE_MODE
00305          )
00306          port map (
00307             CLKA            => user_clk_i,
00308             SSRA            => '0',
00309             REGCEA          => '0',
00310             CASCADEINLATA   => '0',
00311             CASCADEINREGA   => '0',
00312             CASCADEOUTLATA  => open,
00313             CASCADEOUTREGA  => open,
00314             DOA             => open,
00315             DOPA            => open,
00316             ADDRA           => v6pcie5,
00317             DIA             => wdata_i(D_MSB downto 0),
00318             DIPA            => wdata_i(DP_MSB downto DP_LSB),
00319             ENA             => wen_i,
00320             WEA             => v6pcie2(3 downto 0),
00321             CLKB            => user_clk_i,
00322             SSRB            => '0',
00323             WEB             => "0000",
00324             CASCADEINLATB   => '0',
00325             CASCADEINREGB   => '0',
00326             CASCADEOUTLATB  => open,
00327             CASCADEOUTREGB  => open,
00328             DIB             => "00000000000000000000000000000000",
00329             DIPB            => "0000",
00330             ADDRB           => v6pcie7,
00331             DOB             => v6pcie15(31 downto 0),
00332             DOPB            => v6pcie16(3 downto 0),
00333             ENB             => ren_i,
00334             REGCEB          => rce_i
00335          );
00336       
00337    end generate;
00338    use_ramb36_2 : if (WIDTH < 36 and WIDTH > 4) generate
00339 
00340       v6pcie2 <= (others => wen_i);
00341       v6pcie5 <= pad_val(waddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00342       v6pcie7 <= pad_val(raddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00343       v6pcie11 <= pad_val(wdata_i(D_MSB downto 0), D_MSB, 0, '0', 32);
00344       v6pcie13 <= wdata_i(DP_MSB downto DP_LSB);
00345       v6pcie12 <= pad_val(v6pcie13((DP_MSB - DP_LSB) downto 0), DP_MSB - DP_LSB, 0, '0', 4);
00346       rdata_o_v6pcie0 <= v6pcie16((DP_MSB - DP_LSB) downto 0) & v6pcie15(D_MSB downto 0);
00347 
00348       ramb36_i : RAMB36
00349          generic map (
00350             DOA_REG        => 0,
00351             DOB_REG        => DOB_REG,
00352             READ_WIDTH_A   => 0,
00353             READ_WIDTH_B   => WIDTH,
00354             WRITE_WIDTH_A  => WIDTH,
00355             WRITE_WIDTH_B  => 0,
00356             WRITE_MODE_A   => WRITE_MODE
00357          )
00358          port map (
00359             CLKA            => user_clk_i,
00360             SSRA            => '0',
00361             REGCEA          => '0',
00362             CASCADEINLATA   => '0',
00363             CASCADEINREGA   => '0',
00364             CASCADEOUTLATA  => open,
00365             CASCADEOUTREGA  => open,
00366             DOA             => open,
00367             DOPA            => open,
00368             ADDRA           => v6pcie5,
00369             DIA             => v6pcie11,
00370             DIPA            => v6pcie12,
00371             ENA             => wen_i,
00372             WEA             => v6pcie2(3 downto 0),
00373             CLKB            => user_clk_i,
00374             SSRB            => '0',
00375             WEB             => "0000",
00376             CASCADEINLATB   => '0',
00377             CASCADEINREGB   => '0',
00378             CASCADEOUTLATB  => open,
00379             CASCADEOUTREGB  => open,
00380             DIB             => "00000000000000000000000000000000",
00381             DIPB            => "0000",
00382             ADDRB           => v6pcie7,
00383             DOB             => v6pcie15(31 downto 0),
00384             DOPB            => v6pcie16(3 downto 0),
00385             ENB             => ren_i,
00386             REGCEB          => rce_i
00387          );
00388       
00389    end generate;
00390    use_ramb36_3 : if (WIDTH = 4) generate
00391       
00392       v6pcie2 <= (others => wen_i);
00393       v6pcie5 <= pad_val(waddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00394       v6pcie7 <= pad_val(raddr_i(ADDR_MSB downto 0), ADDR_MSB + ADDR_LO_BITS, ADDR_LO_BITS, '1', 16);
00395       v6pcie11 <= pad_val(wdata_i(D_MSB downto 0), D_MSB, 0, '0', 32);
00396       rdata_o_v6pcie0 <= v6pcie15(D_MSB downto 0);
00397 
00398       ramb36_i : RAMB36
00399          generic map (
00400             dob_reg        => DOB_REG,
00401             read_width_a   => 0,
00402             read_width_b   => WIDTH,
00403             write_width_a  => WIDTH,
00404             write_width_b  => 0,
00405             write_mode_a   => WRITE_MODE
00406          )
00407          port map (
00408             CLKA            => user_clk_i,
00409             SSRA            => '0',
00410             REGCEA          => '0',
00411             CASCADEINLATA   => '0',
00412             CASCADEINREGA   => '0',
00413             CASCADEOUTLATA  => open,
00414             CASCADEOUTREGA  => open,
00415             DOA             => open,
00416             DOPA            => open,
00417             ADDRA           => v6pcie5,
00418             DIA             => v6pcie11,
00419             DIPA            => tied_to_ground_vec_i(3 downto 0),
00420             ENA             => wen_i,
00421             WEA             => v6pcie2(3 downto 0),
00422             CLKB            => user_clk_i,
00423             SSRB            => '0',
00424             WEB             => "0000",
00425             CASCADEINLATB   => '0',
00426             CASCADEINREGB   => '0',
00427             CASCADEOUTLATB  => open,
00428             CASCADEOUTREGB  => open,
00429             ADDRB           => v6pcie7,
00430             DIB             => tied_to_ground_vec_i,
00431             DIPB            => tied_to_ground_vec_i(3 downto 0),
00432             DOB             => v6pcie15(31 downto 0),
00433             DOPB            => open,
00434             ENB             => ren_i,
00435             REGCEB          => rce_i
00436          );
00437 
00438 
00439       -- block: use_ramb36
00440    end generate;
00441    
00442                 -- pcie_bram_v6
00443 end v6_pcie;
00444 
00445