原创 Microblaze LMB Decode Mask

2010-1-8 21:30 2388 5 5 分类: FPGA/CPLD

-------------------------------------------------------------------------------
-- $Id: lmb_bram_if_cntlr.vhd,v 1.4 2008/10/02 07:47:46 rolandp Exp $
-------------------------------------------------------------------------------
-- DISCLAIMER OF LIABILITY
--
-- This file contains proprietary and confidential information of
-- Xilinx, Inc. ("Xilinx"), that is distributed under a license
-- from Xilinx, and may be used, copied and/or disclosed only
-- pursuant to the terms of a valid license agreement with Xilinx.
--
-- XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
-- ("MATERIALS") "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
-- EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING WITHOUT
-- LIMITATION, ANY WARRANTY WITH RESPECT TO NONINFRINGEMENT,
-- MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE. Xilinx
-- does not warrant that functions included in the Materials will
-- meet the requirements of Licensee, or that the operation of the
-- Materials will be uninterrupted or error-free, or that defects
-- in the Materials will be corrected. Furthermore, Xilinx does
-- not warrant or make any representations regarding use, or the
-- results of the use, of the Materials in terms of correctness,
-- accuracy, reliability or otherwise.
--
-- Xilinx products are not designed or intended to be fail-safe,
-- or for use in any application requiring fail-safe performance,
-- such as life-support or safety devices or systems, Class III
-- medical devices, nuclear facilities, applications related to
-- the deployment of airbags, or any other applications that could
-- lead to death, personal injury or severe property or
-- environmental damage (individually and collectively, "critical
-- applications"). Customer assumes the sole risk and liability
-- of any use of Xilinx products in critical applications,
-- subject only to applicable laws and regulations governing
-- limitations on product liability.
--
-- Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Xilinx, Inc.
-- All rights reserved.
--
-- This disclaimer and copyright notice must be retained as part
-- of this file at all times.
--
-------------------------------------------------------------------------------
-- Filename:        lmb_bram_if_cntlr.vhd
--
-- Description:
--
-- VHDL-Standard:   VHDL'93
-------------------------------------------------------------------------------
-- Structure:
--              lmb_bram_if_cntlr.vhd
--
-------------------------------------------------------------------------------
-- Author:          goran
-- Revision:        $Revision: 1.4 $
-- Date:            $Date: 2008/10/02 07:47:46 $
--
-- History:
--   paulo  2002-07-08    First Version
--
-------------------------------------------------------------------------------
-- Naming Conventions:
--      active low signals:                     "*_n"
--      clock signals:                          "clk", "clk_div#", "clk_#x"
--      reset signals:                          "rst", "rst_n"
--      generics:                               "C_*"
--      user defined types:                     "*_TYPE"
--      state machine next state:               "*_ns"
--      state machine current state:            "*_cs"
--      combinatorial signals:                  "*_com"
--      pipelined or register delay signals:    "*_d#"
--      counter signals:                        "*cnt*"
--      clock enable signals:                   "*_ce"
--      internal version of output port         "*_i"
--      device pins:                            "*_pin"
--      ports:                                  - Names begin with Uppercase
--      processes:                              "*_PROCESS"
--      component instantiations:               "<ENTITY_>I_<#|FUNC>
-------------------------------------------------------------------------------


library ieee;
use ieee.std_logic_1164.all;


library lmb_bram_if_cntlr_v2_10_b;
use lmb_bram_if_cntlr_v2_10_b.pselect_mask;


entity lmb_bram_if_cntlr is
  generic (
    C_HIGHADDR   : std_logic_vector(0 to 31) := X"00000000";
    C_BASEADDR   : std_logic_vector(0 to 31) := X"FFFFFFFF";
    C_MASK       : std_logic_vector(0 to 31) := X"00800000";
    C_LMB_AWIDTH : integer                   := 32;
    C_LMB_DWIDTH : integer                   := 32
    );
  port (
    LMB_Clk : in std_logic := '0';
    LMB_Rst : in std_logic := '0';


    -- Instruction Bus
    LMB_ABus        : in  std_logic_vector(0 to C_LMB_AWIDTH-1);
    LMB_WriteDBus   : in  std_logic_vector(0 to C_LMB_DWIDTH-1);
    LMB_AddrStrobe  : in  std_logic;
    LMB_ReadStrobe  : in  std_logic;
    LMB_WriteStrobe : in  std_logic;
    LMB_BE          : in  std_logic_vector(0 to (C_LMB_DWIDTH/8 - 1));
    Sl_DBus         : out std_logic_vector(0 to C_LMB_DWIDTH-1);
    Sl_Ready        : out std_logic;


    -- ports to memory block
    BRAM_Rst_A  : out std_logic;
    BRAM_Clk_A  : out std_logic;
    BRAM_Addr_A : out std_logic_vector(0 to C_LMB_AWIDTH-1);
    BRAM_EN_A   : out std_logic;
    BRAM_WEN_A  : out std_logic_vector(0 to C_LMB_DWIDTH/8-1);
    BRAM_Dout_A : out std_logic_vector(0 to C_LMB_DWIDTH-1);
    BRAM_Din_A  : in  std_logic_vector(0 to C_LMB_DWIDTH-1)
    );
end lmb_bram_if_cntlr;


architecture imp of lmb_bram_if_cntlr is


------------------------------------------------------------------------------
-- component declarations
------------------------------------------------------------------------------


  component pselect_mask is
    generic (
      C_AW   : integer                   := 32;
      C_BAR  : std_logic_vector(0 to 31) := X"00000000";
      C_MASK : std_logic_vector(0 to 31) := X"00800000");
    port (
      A     : in  std_logic_vector(0 to 31);
      CS    : out std_logic;
      Valid : in  std_logic);
  end component;


------------------------------------------------------------------------------
-- internal signals
------------------------------------------------------------------------------


  signal lmb_select : std_logic;


  signal lmb_select_1 : std_logic;


  signal lmb_we : std_logic_vector(0 to 3);


  signal Sl_Ready_i       : std_logic;
  signal lmb_addrstrobe_i : std_logic;


  signal One : std_logic;
begin  -- architecture IMP


 
  -----------------------------------------------------------------------------
  -- Top-level port assignments


  -- Port A
  BRAM_Rst_A  <= '0';
  BRAM_Clk_A  <= LMB_Clk;
  BRAM_EN_A   <= LMB_AddrStrobe; -- 每个外设都 Enable, 都会输出数据
  BRAM_WEN_A  <= lmb_we;
  BRAM_Dout_A <= LMB_WriteDBus;
  Sl_DBus     <= BRAM_Din_A;
  BRAM_Addr_A <= LMB_ABus;


  -----------------------------------------------------------------------------
  -- Handling the LMB bus interface
  -----------------------------------------------------------------------------


  -----------------------------------------------------------------------------
  -- Writes are pipelined in MB with 5 stage pipeline
  -----------------------------------------------------------------------------
  Ready_Handling : process (LMB_Clk, LMB_Rst) is
  begin  -- PROCESS Ready_Handling
    if (LMB_Clk'event and LMB_Clk = '1') then  -- rising clock edge
      if (LMB_Rst = '1') then
        Sl_Ready_i       <= '0';
        lmb_addrstrobe_i <= '0';
      else
        Sl_Ready_i       <= lmb_select; -- 只有选择的外设才会Ready
        lmb_addrstrobe_i <= LMB_AddrStrobe; -- 延时一个Clock
      end if;
    end if;
  end process Ready_Handling;


  Sl_Ready <= Sl_Ready_i and lmb_addrstrobe_i; -- 只有选择的外设才会Ready
        
  -- 只有选择的外设才会被写入
  lmb_we(0) <= LMB_BE(0) and LMB_WriteStrobe and lmb_select;
  lmb_we(1) <= LMB_BE(1) and LMB_WriteStrobe and lmb_select;
  lmb_we(2) <= LMB_BE(2) and LMB_WriteStrobe and lmb_select;
  lmb_we(3) <= LMB_BE(3) and LMB_WriteStrobe and lmb_select;
   
  -----------------------------------------------------------------------------
  -- Do the LMB address decoding
  -----------------------------------------------------------------------------
  One <= '1';
  pselect_mask_lmb : pselect_mask
    generic map (
      C_AW   => LMB_ABus'length,
      C_BAR  => C_BASEADDR,
      C_MASK => C_MASK)
    port map (
      A     => LMB_ABus, -- 当前地址
      CS    => lmb_select, -- 外设选择
      Valid => One);


end architecture imp;



    -- LMB slave signals
    Sl_DBus  : in std_logic_vector(0 to (C_LMB_DWIDTH*C_LMB_NUM_SLAVES)-1);
-- 所有外设的输出
    Sl_Ready : in std_logic_vector(0 to C_LMB_NUM_SLAVES-1);


  -----------------------------------------------------------------------------
  -- Drive all the Slave to Master signals
  -----------------------------------------------------------------------------
  -- 应该只有一个外设Ready ( lmb_select = '1' ) 的外设
  -- 
lmb_select = '0',  Sl_Ready = '0'
  Ready_ORing : process (Sl_Ready) is
    variable i : std_logic;
  begin  -- process Ready_ORing
    i := '0';
    for S in Sl_Ready'range loop
      i := i or Sl_Ready(S);
    end loop;  -- S
    LMB_Ready <= i;
  end process Ready_ORing;


 


  DBus_Oring : process (Sl_Ready, Sl_DBus) is
    variable Res    : std_logic_vector(0 to C_LMB_DWIDTH-1);
    variable Tmp    : std_logic_vector(Sl_DBus'range);
    variable tmp_or : std_logic;
  begin  -- process DBus_Oring
    if (C_LMB_NUM_SLAVES = 1) then -- 如果只有一个外设
      LMB_ReadDBus <= Sl_DBus;
    else
      -- First gating all data signals with their resp. ready signal
      for I in 0 to C_LMB_NUM_SLAVES-1 loop
        for J in 0 to C_LMB_DWIDTH-1 loop
          tmp(I*C_LMB_DWIDTH + J) := Sl_Ready(I) and Sl_DBus(I*C_LMB_DWIDTH + J);
-- 没有选中的外设, Sl_Ready(I) = '0' 数据被忽略
        end loop;  -- J
      end loop;  -- I
      -- then oring the tmp signals together
      for J in 0 to C_LMB_DWIDTH-1 loop
        tmp_or := '0';
        for I in 0 to C_LMB_NUM_SLAVES-1 loop
          tmp_or := tmp_or or tmp(I*C_LMB_DWIDTH + j);
        end loop;  -- J
        res(J) := tmp_or; -- 所有选择的外设相同数据位 相或
      end loop;  -- I
      LMB_ReadDBus <= Res; -- 最终结果
    end if;
  end process DBus_Oring;


------------------------------------------------------------
-- 地址解码 ( 掩码, 地址, 基址 )
------------------------------------------------------------


地址[ 掩码为 '1' 的位位置 ] = 基址[ 掩码为 '1' 的位位置 ]


基址 = 0000_0000_0000_0000_0000_0000_0000_0000
( 0x????0000 -- 0x????7FFF ) 有效


掩码 = 0000_0000_0000_0000_1000_0000_0000_0000


地址 = 0000_0000_0000_0000_0000_0000_0000_0000 -- 有效


地址 = 0000_0000_0000_0000_1000_0000_0000_0000 -- 无效


基址 = 0000_0000_0000_0000_1000_0000_0000_0000
( 0x????8000 -- 0x????FFFF ) 有效

掩码 = 0000_0000_0000_0000_1000_0000_0000_0000


地址 = 0000_0000_0000_0000_0000_0000_0000_0000 -- 无效


地址 = 0000_0000_0000_0000_1000_0000_0000_0000 -- 有效


 

-- Definition of Generics:
--          C_AB            -- number of address bits to decode
--          C_AW            -- width of address bus
--          C_BAR           -- base address of peripheral (peripheral select
--                             is asserted when the C_AB most significant
--                             address bits match the C_AB most significant
--                             C_BAR bits
-- Definition of Ports:
--          A               -- address input
--          AValid          -- address qualifier
--          PS              -- peripheral select


entity pselect_mask is


  generic (
    C_AW   : integer                   := 32;
    C_BAR  : std_logic_vector(0 to 31) := "00000000000000100000000000000000";
    C_MASK : std_logic_vector(0 to 31) := "00000000000001111100000000000000"
    );
  port (
    A     : in  std_logic_vector(0 to C_AW-1);
    Valid : in  std_logic;
    CS    : out std_logic
    );


end entity pselect_mask;


library unisim;
use unisim.all;


architecture imp of pselect_mask is


-- 计算MASK '1' 的位数


  function Nr_Of_Ones (S : std_logic_vector) return natural is
    variable tmp : natural := 0;
  begin  -- function Nr_Of_Ones
    for I in S'range loop
      if (S(I) = '1') then
        tmp := tmp + 1;
      end if;
    end loop;  -- I
    return tmp;
  end function Nr_Of_Ones;


  function fix_AB (B : boolean; I : integer) return integer is
  begin  -- function fix_AB
    if (not B) then
      return I + 1;
    else
      return I;
    end if;
  end function fix_AB;


 


-- 计算MASK '1' 的位数
constant Nr      : integer := Nr_Of_Ones(C_MASK);



  constant Use_CIN : boolean := ((Nr mod 4) = 0);
  constant AB      : integer := fix_AB(Use_CIN, Nr);


  signal A_Bus : std_logic_vector(0 to AB);  -- 给出的地址
  signal BAR   : std_logic_vector(0 to AB);  -- 基址


begin  -- VHDL_RTL


  Make_Busses : process (A,Valid) is
    variable tmp : natural;
  begin  -- process Make_Busses
    tmp   := 0;
    A_Bus <= (others => '0');
    BAR   <= (others => '0');
    for I in C_MASK'range loop  -- 计算 32 次
      if (C_MASK(I) = '1') then -- 掩码中 为'1'的位
        A_Bus(tmp) <= A(I);     -- 地址
        BAR(tmp)   <= C_BAR(I); -- 基址
        tmp        := tmp + 1;
      end if;
    end loop;  -- I


    if (not Use_CIN) then -- 没有效果 ? Valid = '1'
      BAR(tmp) <= '1';
      A_Bus(tmp) <= Valid; -- Valid = '1'
    end if;



  end process Make_Busses;


    CS <= Valid when A_Bus=BAR else '0';  -- Valid = '1'
end imp;


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /2 下一条