⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmu_acache.vhd

📁 sparc org, vhdl rtl code
💻 VHD
字号:
----------------------------------------------------------------------------
--  This file is a part of the LEON VHDL model
--  Copyright (C) 2003  Gaisler Research
--
--  This library is free software; you can redistribute it and/or
--  modify it under the terms of the GNU Lesser General Public
--  License as published by the Free Software Foundation; either
--  version 2 of the License, or (at your option) any later version.
--
--  See the file COPYING.LGPL for the full details of the license.


-----------------------------------------------------------------------------   
-- Entity:      mmu_acache
-- File:        mmu_acache.vhd
-- Author:      Jiri Gaisler - Gaisler Research, Konrad Eisele <eiselekd@web.de>
-- Description: Interface module between I/D cache controllers and Amba AHB
------------------------------------------------------------------------------  


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned."+";
use IEEE.std_logic_arith.conv_unsigned;
use work.leon_target.all;
use work.leon_config.all;
use work.leon_iface.all;
use work.amba.all;
use work.macro.all;

 
entity mmu_acache is
  port (
    rst    : in  std_logic;
    clk    : in  clk_type;
    mcii   : in  memory_ic_in_type;
    mcio   : out memory_ic_out_type;
    mcdi   : in  memory_dc_in_type;
    mcdo   : out memory_dc_out_type;
    mcmmi  : in  memory_mm_in_type;
    mcmmo  : out memory_mm_out_type;
    iuo    : in  iu_out_type;
    apbi   : in  apb_slv_in_type;
    apbo   : out apb_slv_out_type;
    ahbi   : in  ahb_mst_in_type;
    ahbo   : out ahb_mst_out_type
  );
end;

architecture rtl of mmu_acache is

-- cache control register type

type cctrltype is record
  ib     : std_logic;				-- icache burst enable
  dfrz   : std_logic;				-- dcache freeze enable
  ifrz   : std_logic;				-- icache freeze enable
  dsnoop : std_logic;				-- data cache snooping
  dcs    : std_logic_vector(1 downto 0);	-- dcache state
  ics    : std_logic_vector(1 downto 0);	-- icache state
end record;

type astates is (idle, dcache, icache, mmu);
type reg_type is record
  bg     : std_logic; 	-- bus grant
  bo     : std_logic_vector(1 downto 0); 	-- bus owner
  ba     : std_logic;	-- bus active
  retry  : std_logic;	-- retry/split pending
  werr   : std_logic;	-- write error
  cctrl	 : cctrltype;
  pwd    : std_logic;	-- power-down
  hcache : std_logic;	-- cacheable access
  astate : astates;
end record;

signal r, rin : reg_type;
begin

  comb : process(ahbi, r, rst, mcii, mcdi, mcmmi, iuo, apbi)

  variable v : reg_type;
  variable haddr   : std_logic_vector(31 downto 0);   -- address bus
  variable htrans  : std_logic_vector(1 downto 0);    -- transfer type 
  variable hwrite  : std_logic;  		      -- read/write
  variable hlock   : std_logic;  		      -- bus lock
  variable hsize   : std_logic_vector(2 downto 0);    -- transfer size
  variable hburst  : std_logic_vector(2 downto 0);    -- burst type
  variable hwdata  : std_logic_vector(31 downto 0);   -- write data
  variable hbusreq : std_logic;   -- bus request
  variable iflush, dflush, mmflush : std_logic;   
  variable iready, dready, mmready : std_logic;   
  variable igrant, dgrant, mmgrant : std_logic;   
  variable iretry, dretry, mmretry : std_logic;   
  variable ihcache, dhcache, mmhcache, hcache : std_logic;   
  variable imexc, dmexc, mmmexc : std_logic;
  variable dreq : std_logic;
  variable nbo : std_logic_vector(1 downto 0);
  variable su : std_logic;   
  variable cctrl   : std_logic_vector(31 downto 0);

  begin

    -- initialisation

    htrans := HTRANS_IDLE;
    v := r;  v.werr := '0';
    iready := '0'; dready := '0'; mmready := '0';
    igrant := '0'; dgrant := '0'; mmgrant := '0'; 
    imexc := '0'; dmexc := '0'; mmmexc := '0'; hlock := '0';
    iretry := '0'; dretry := '0'; mmretry := '0';
    ihcache := '0'; dhcache := '0'; mmhcache := '0';
    iflush := '0'; dflush := '0'; mmflush := '0'; su := '0';

    haddr := (others => '0');
    hwrite := '0';
    hsize := (others => '0');
    hlock := '0'; 
    hburst := (others => '0'); 
    
    -- generate AHB signals

    dreq := mcdi.req and not r.pwd;
    hwdata := mcdi.data;
    hbusreq := '0';

    if (mcii.req = '1') and
      not (( ((r.ba and dreq) = '1') and (r.bo = "01")) or
           ( ((r.ba and mcmmi.req) = '1') and (r.bo = "10"))) then
      nbo := "00";
      hbusreq := '1';
      htrans := HTRANS_NONSEQ;
    elsif (dreq = '1') and
      not (( ((r.ba and mcii.req) = '1') and (r.bo = "00")) or
           ( ((r.ba and mcmmi.req) = '1') and (r.bo = "10"))) then
      nbo := "01";
      hbusreq := '1';
      htrans := HTRANS_NONSEQ;
    elsif (mcmmi.req = '1') and
      not (( ((r.ba and mcii.req) = '1') and (r.bo = "00")) or
           ( ((r.ba and dreq) = '1') and (r.bo = "01"))) then
      nbo := "10";
      hbusreq := '1';
      htrans := HTRANS_NONSEQ;
    else
      nbo := "11";
    end if;
    
    if nbo = "10" then
      haddr := mcmmi.address; hwrite := not mcmmi.read; hsize := '0' & mcmmi.size;
      hlock := mcmmi.lock;
--      if mcmmi.burst = '1' then hburst := HBURST_INCR; 
--      else hburst := HBURST_SINGLE; end if;
--      if ((mcmmi.req and r.ba) = '1')  and (r.bo = "10") and ((not r.retry) = '1') then 
--        htrans := HTRANS_SEQ; haddr(4 downto 2) := haddr(4 downto 2) +1;
--        hburst := HBURST_INCR; 
--      end if;
      htrans := HTRANS_NONSEQ; hburst := HBURST_SINGLE; 
      if (mcmmi.req and r.bg and ahbi.hready and not r.retry) = '1' 
      then mmgrant := '1'; end if; 
    elsif nbo = "00" then
      haddr := mcii.address; hwrite := '0'; hsize := HSIZE_WORD; hlock := '0';
      su := mcii.su;
      if mcii.burst = '1' then hburst := HBURST_INCR; 
      else hburst := HBURST_SINGLE; end if;
      if ((mcii.req and r.ba) = '1')  and (r.bo = "00") and ((not r.retry) = '1') then
        htrans := HTRANS_SEQ; haddr(4 downto 2) := haddr(4 downto 2) +1;
        hburst := HBURST_INCR; 
      end if;
      if (mcii.req and r.bg and ahbi.hready and not r.retry) = '1' 
      then igrant := '1'; end if; 
    elsif nbo = "01" then
      haddr := mcdi.address; hwrite := not mcdi.read; hsize := '0' & mcdi.size;
      hlock := mcdi.lock; 
      if mcdi.asi /= "1010" then su := '1'; else su := '0'; end if;  --ASI_UDATA
      if mcdi.burst = '1' then hburst := HBURST_INCR; 
      else hburst := HBURST_SINGLE; end if;
      if ((dreq and r.ba) = '1') and (r.bo = "01") and ((not r.retry) = '1') then 
        htrans := HTRANS_SEQ; haddr(4 downto 2) := haddr(4 downto 2) +1;
        hburst := HBURST_INCR; 
      end if;
      if (dreq and r.bg and ahbi.hready and not r.retry) = '1' 
      then dgrant := '1'; end if;
    end if;
    
    if mcii.req = '0' then hlock := mcdi.lock; end if;

    if (r.ba = '1') and 
       ((ahbi.hresp = HRESP_RETRY) or (ahbi.hresp = HRESP_SPLIT))
    then v.retry := not ahbi.hready; else v.retry := '0'; end if;
      
    if r.retry = '1' then htrans := HTRANS_IDLE; end if;

    if r.bo = "10" then
      hwdata := mcmmi.data;
      if r.ba = '1' then
        mmhcache := r.hcache;
        if ahbi.hready = '1' then
	  case ahbi.hresp is
	  when HRESP_OKAY => mmready := '1'; 
	  when HRESP_RETRY | HRESP_SPLIT=> mmretry := '1'; 
	  when others => mmready := '1'; mmmexc := '1'; v.werr := not mcmmi.read;
	  end case;
        end if;
      end if;
    elsif r.bo = "00" then
      if r.ba = '1' then
        ihcache := r.hcache;
        if ahbi.hready = '1' then
	  case ahbi.hresp is
	  when HRESP_OKAY => iready := '1'; 
	  when HRESP_RETRY | HRESP_SPLIT=> iretry := '1'; 
	  when others => iready := '1'; imexc := '1';
	  end case;
        end if;
      end if;
    elsif r.bo = "01" then
      --hwdata := mcdi.data;
      if r.ba = '1' then
	dhcache := r.hcache;
        if ahbi.hready = '1' then
	  case ahbi.hresp is
	  when HRESP_OKAY => dready := '1'; 
	  when HRESP_RETRY | HRESP_SPLIT=> dretry := '1'; 
	  when others => dready := '1'; dmexc := '1'; v.werr := not mcdi.read;
	  end case;
        end if;
      end if;
      hlock := mcdi.lock;
    end if;

    -- decode cacheability

    hcache := is_cacheable(haddr(31 downto 24));

    if nbo = "01" and ((hsize = "011") or ((hcache and mcdi.read) = '1')) then 
      hsize := "010";
    end if;

    if ahbi.hready = '1' then
      v.hcache := hcache; v.bo := nbo; v.bg := ahbi.hgrant;
      if (htrans = HTRANS_NONSEQ) or (htrans = HTRANS_SEQ) then
	v.ba := r.bg;
      else v.ba := '0'; end if;
    end if;

    -- cache freeze operation
    
    if (r.cctrl.ifrz and iuo.intack and r.cctrl.ics(0)) = '1' then
      v.cctrl.ics := "01";
    end if;
    if (r.cctrl.dfrz and iuo.intack and r.cctrl.dcs(0)) = '1' then
      v.cctrl.dcs := "01";
    end if;

    if (apbi.psel and apbi.penable and apbi.pwrite) = '1' then
      case apbi.paddr(2 downto 2) is
      when "1" =>

        v.cctrl.dsnoop := apbi.pwdata(23);
        dflush       := apbi.pwdata(22);
        iflush       := apbi.pwdata(21);
        v.cctrl.ib   := apbi.pwdata(16);
        v.cctrl.dfrz := apbi.pwdata(5);
        v.cctrl.ifrz := apbi.pwdata(4);
        v.cctrl.dcs  := apbi.pwdata(3 downto 2);
        v.cctrl.ics  := apbi.pwdata(1 downto 0);
      when others =>
	v.pwd := '1';
      end case;
    end if;

    cctrl := (others => '0');

    if DSNOOP then cctrl(23) := r.cctrl.dsnoop; end if;
    cctrl(16 downto 14) := r.cctrl.ib & mcii.flush  &  mcdi.flush; 
    cctrl(5 downto 0)   := r.cctrl.dfrz & r.cctrl.ifrz & r.cctrl.dcs & r.cctrl.ics;
    cctrl(25 downto 24) := std_logic_vector(conv_unsigned(DSETS-1,2));
    cctrl(27 downto 26) := std_logic_vector(conv_unsigned(ISETS-1,2));
    if ISETS /= 1 then
      if ICREPLACE = rnd then cctrl(29 downto 28) := "01"; end if;
      if ICREPLACE = lrr then cctrl(29 downto 28) := "10"; end if;
      if ICREPLACE = lru then cctrl(29 downto 28) := "11"; end if;
    end if;
    if DSETS /= 1 then
      if DCREPLACE = rnd then cctrl(31 downto 30) := "01"; end if;
      if DCREPLACE = lrr then cctrl(31 downto 30) := "10"; end if;
      if DCREPLACE = lru then cctrl(31 downto 30) := "11"; end if;
    end if;

  
    -- exit power-down in DSU debug mode
    
    if DEBUG_UNIT then 
      v.pwd := v.pwd and (not iuo.ipend) and not iuo.debug.dbreak;
    else v.pwd := v.pwd and not iuo.ipend; end if;


    -- reset operation

    if rst = '0' then
      v.bg := '0'; v.bo := "00"; v.ba := '0'; v.retry := '0'; v.werr := '0';
      v.cctrl.dcs := "00"; v.cctrl.ics := "00"; v.hcache := '0';
      v.cctrl.ib := '0'; v.pwd := '0'; v.cctrl.dsnoop := '0';
      v.astate := idle;
    end if;

    -- drive ports
    
    ahbo.haddr   <= haddr ;
    ahbo.htrans  <= htrans;
    ahbo.hbusreq <= hbusreq;
    ahbo.hwdata  <= hwdata;
    ahbo.hlock   <= hlock;
    ahbo.hwrite  <= hwrite;
    ahbo.hsize   <= hsize;
    ahbo.hburst  <= hburst;

    if nbo = "00" then ahbo.hprot   <= hcache & hcache & su & '0';
    else ahbo.hprot   <= hcache & hcache & su & '1'; end if;
    mcio.grant   <= igrant;
    mcio.ready   <= iready;
    mcio.mexc    <= imexc;
    mcio.retry   <= iretry;
    mcio.cache   <= ihcache;
    mcdo.grant   <= dgrant;
    mcdo.ready   <= dready;
    mcdo.mexc    <= dmexc;
    mcdo.retry   <= dretry;
    mcdo.werr    <= r.werr;
    mcdo.cache   <= dhcache;
    mcdo.iflush  <= iflush;
    mcdo.dflush  <= dflush;
    mcdo.ba      <= r.ba;
    mcdo.bg      <= r.bg;
    mcdo.dsnoop  <= r.cctrl.dsnoop;
    apbo.prdata  <= cctrl;

    mcmmo.grant   <= mmgrant;
    mcmmo.ready   <= mmready;
    mcmmo.mexc    <= mmmexc;
    mcmmo.retry   <= mmretry;
    mcmmo.werr    <= r.werr;
    mcmmo.cache   <= mmhcache;
 
    rin <= v;

  end process;

  mcio.data  <= ahbi.hrdata;
  mcdo.data  <= ahbi.hrdata;
  mcmmo.data <= ahbi.hrdata;

  mcio.ics <= r.cctrl.ics; mcdo.dcs <= r.cctrl.dcs;
  mcio.burst <= r.cctrl.ib;

  reg : process(clk)
  begin if rising_edge(clk) then r <= rin; end if; end process;


end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -