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

📄 dcache.vhd

📁 一个航天航空用的Sparc处理器(配美国欧洲宇航局用的R_tems嵌入式操作系统)的VHDL源代码
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-----------------------------------------------------------------------------
--  This file is a part of the LEON VHDL model
--  Copyright (C) 1999  European Space Agency (ESA)
--
--  This program is free software; you can redistribute it and/or modify
--  it under the terms of the GNU 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 for the full details of the license.
-----------------------------------------------------------------------------   
-- Entity:      dcache
-- File:        dcache.vhd
-- Author:      Jiri Gaisler - ESA/ESTEC
-- Description: This unit implements the data cache controller.
------------------------------------------------------------------------------  
-- Version control:
-- 17-07-1998:  : First implemetation
-- 11-12-1998:  : Switched to synchronous ram
-- 26-09-1999:  : Release 1.0
------------------------------------------------------------------------------  

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned."+";
use work.config.all;
use work.sparcv8.all;		-- ASI declarations
use work.iface.all;
use work.macro.all;		-- xorv()

entity dcache is
  port (
     Rst : in  std_logic;
     Clk : in  std_logic;
     dci : in  dcache_in_type;
     dco : out dcache_out_type;
     ico : in  icache_out_type;
    mcdi : out memory_dc_in_type;
    mcdo : in  memory_dc_out_type;
    dcrami : out dcram_in_type;
    dcramo : in  dcram_out_type
);
end; 

architecture rtl of dcache is

constant TAG_HIGH   : integer := DTAG_HIGH;
constant TAG_LOW    : integer := DOFFSET_BITS + DLINE_BITS + 2;
constant OFFSET_HIGH: integer := TAG_LOW - 1;
constant OFFSET_LOW : integer := DLINE_BITS + 2;
constant LINE_HIGH  : integer := OFFSET_LOW - 1;
constant LINE_LOW   : integer := 2;

type rdatatype is (dtag, ddata, icache, memory);	-- sources during cache read
type vmasktype is (clearone, clearall, merge, tnew);	-- valid bits operation

type write_buffer_type is record			-- write buffer 
  addr, data1, data2 : std_logic_vector(31 downto 0);
  size : std_logic_vector(1 downto 0);
  asi  : std_logic_vector(3 downto 0);
  read : std_logic;
end record;

type dcache_control_type is record			-- all registers
  read : std_logic;					-- access direction
  signed : std_logic;					-- signed/unsigned read
  asi : std_logic_vector(3 downto 0);			-- asi
  size : std_logic_vector(1 downto 0);			-- access size
  req, burst, mds, holdn, nomds, stpend  : std_logic;
  xaddress : std_logic_vector(31 downto 0);		-- common address buffer
  faddr : std_logic_vector(DOFFSET_BITS - 1 downto 0);	-- flush address
  lineaddr : std_logic_vector(LINE_HIGH  downto LINE_LOW);-- last line address
  dstate : integer range 0 to 15;			-- FSM vector
  ixread, itagen, idataen : std_logic;			-- icache I/F strobes
  hit, cachable : std_logic;
  werr   	: std_logic;				-- write error pending
  wexc   	: std_logic;				-- write error pending
  taddrpar 	: std_logic;				-- tag address parity
  daddrpar 	: std_logic;				-- data address parity
  tparerr	: std_logic;				-- tag parity error
  tparerr2	: std_logic;				-- tag parity error
  dparerr	: std_logic;				-- data parity error
  dparerr2	: std_logic;				-- data parity error
  flush		: std_logic;				-- flush in progress
  wb : write_buffer_type;				-- write buffer
  icenable	: std_logic;				-- icache diag access
end record;

signal r, c : dcache_control_type;	-- r is registers, c is combinational
 
begin

  dctrl : process(rst, r, dci, mcdo, ico, dcramo)
  variable rdatasel : rdatatype;
  variable eaddress, maddress : std_logic_vector(31 downto 0);
  variable size : std_logic_vector(1 downto 0);
  variable read : std_logic;
  variable asi : std_logic_vector(3 downto 0);			-- asi
  variable twrite, tdiagwrite, ddiagwrite, dwrite : std_logic;
  variable taddr : std_logic_vector(TAG_HIGH  downto LINE_LOW); -- tag address
  variable align_data : std_logic_vector((DDWORD_BITS -1) downto 0); -- aligned data
  variable ddatain : std_logic_vector((DDWORD_BITS -1) downto 0);
  variable rdata : std_logic_vector((DDWORD_BITS -1) downto 0);

  variable vmaskraw, vmask : std_logic_vector((DLINE_SIZE -1) downto 0);
  variable enable : std_logic;
  variable error : std_logic;
  variable werr : std_logic;
  variable cachable, hit, valid, forcemiss : std_logic;
  variable signed   : std_logic;
  variable tparerr  : std_logic;
  variable tparin   : std_logic;
  variable dparerr  : std_logic;
  variable dparin   : std_logic;
  variable flush    : std_logic;
  variable iflush   : std_logic;
  variable v : dcache_control_type;
  begin

-- init local variables

    v := r;

    v.mds := '1'; v.req := '0'; dwrite := '0'; twrite := '0'; 
    ddiagwrite := '0'; tdiagwrite := '0';
    v.holdn := '1'; error := '0'; v.tparerr := '0'; v.dparerr := '0';
    flush := '0'; v.icenable := '0'; v.wexc := '0'; werr := '0';
    iflush := '0';

    v.itagen := '0'; v.idataen := '0'; v.ixread  := '0'; 
    enable := '1';

    rdatasel := ddata;	-- read data from cache as default

-- generate access parameters during pipeline stall

    if (r.holdn) = '0' then
      taddr := r.xaddress(TAG_HIGH downto LINE_LOW);
    elsif ((dci.enaddr and not dci.read) = '1') or (ico.hold = '0')
    then
      taddr := dci.maddress(TAG_HIGH downto LINE_LOW);
    else
      taddr := dci.eaddress(TAG_HIGH downto LINE_LOW);
    end if;

    if (r.holdn) = '0' then
      eaddress := dci.maddress; maddress := r.xaddress;
      read := r.read; asi := r.asi; size := r.size; signed := r.signed;
    else
      eaddress := dci.eaddress; maddress := dci.maddress; signed := dci.signed;
      read := dci.read; asi := dci.asi(3 downto 0); size := dci.size;
    end if;

-- parity checking (1)

    tparerr  := '0';
    if DTAGPAR then
      tparerr  := xorv(r.taddrpar & dcramo.dtramout.tag & 
		       dcramo.dtramout.valid & dcramo.dtramout.parity);
    end if;
    dparerr  := '0';
    if DDATPAR then
      dparerr  := xorv(r.daddrpar & dcramo.ddramout.data & 
		       dcramo.ddramout.parity);
    end if;

-- generate cache hit and valid bits

    if (maddress(31) = '0') and (maddress(30 downto 29) /= "01") and
       (asi(2) = '0') then
      cachable := not r.flush; forcemiss := not asi(3);
    else
      cachable := '0'; forcemiss := '0';
    end if;
    if (dcramo.dtramout.tag = maddress(TAG_HIGH downto TAG_LOW)) then 
      hit := cachable and not tparerr; 
    else 
      hit := '0'; 
    end if;

    valid := genmux(r.lineaddr(LINE_HIGH downto LINE_LOW), dcramo.dtramout.valid);
    
    if (r.holdn) = '1' then
      if dci.enaddr = '1' then
        v.hit := hit; v.cachable := cachable; v.xaddress := dci.maddress;
	v.read := dci.read; v.asi := dci.asi(3 downto 0); v.size := dci.size;
	v.signed := dci.signed;
      end if;
    end if;

-- Store buffer

    if r.stpend = '1' then
      v.req := '1';
      if mcdo.ready = '1' then
	v.req := r.burst; v.stpend := r.burst; v.burst := '0';
	v.werr := r.werr or mcdo.mexc;
      end if;
    end if;

-- main Dcache state machine

    case r.dstate is
    when 0 =>			-- Idle state
      v.nomds := '0';
      if (((dci.enaddr and ico.hold) = '1') and (dci.nullify = '0')) or (r.holdn = '0') then
	case asi is
	when ASI_ITAG | ASI_IDATA =>		-- Read/write Icache tags
	  if ico.flush = '1' then
	    error := '1';
 	 else
 	   v.dstate := 5; v.holdn := '0';
 	 end if;
 	when ASI_IFLUSH =>		-- flush instruction cache
	  if read = '0' then iflush := '1'; end if;
 	when ASI_DFLUSH =>		-- flush data cache
	  if read = '0' then flush := '1'; end if;
 	when ASI_DDATA =>		-- Read/write Dcache data
 	  if (size /= "10") or (r.flush = '1') then -- only word access is allowed
 	    error := '1';
 	  elsif (read = '0') then
 	    dwrite := '1'; ddiagwrite := '1';
 	  end if;
 	when ASI_DTAG =>		-- Read/write Dcache tags
	  rdatasel := dtag;
 	  if (size /= "10") or (r.flush = '1') then -- allow only word access
 	    error := '1';
 	  elsif (read = '0') then
 	    twrite := '1'; tdiagwrite := '1';
 	  end if;
	when others =>
	  if (r.stpend  = '0') or ((mcdo.ready and not r.burst)= '1') then -- wait for store queue
	    v.wb.addr := maddress; v.wb.size := size; v.wb.asi := asi; 
	    v.wb.read := read; v.wb.data1 := eaddress;
	    if size = "11" then v.burst := not maddress(2); end if;
	  end if;
	  if read = '1' then	-- read access
	    if not ((mcdo.dcs /= "00") 
	       and ((hit and valid and (not dparerr) and not forcemiss) = '1')) then  -- read hit
	      v.holdn := '0';	-- hold pipeline
	      if (r.stpend  = '0') or ((mcdo.ready and not r.burst) = '1') then	-- wait for store queue
	          v.dstate := 1; v.req := '1'; 
		  v.burst := size(1) and size(0) and not maddress(2);
	      else
		taddr := maddress(TAG_HIGH downto LINE_LOW);
              end if;
            end if;
	  else			-- write access
	    if (r.stpend  = '0') or ((mcdo.ready and not r.burst)= '1') then	-- wait for store queue
	      v.req := '1'; v.stpend := '1';
	      if (mcdo.dcs /= "00") and (hit = '1') then  -- write hit
		twrite := '1'; dwrite := '1';
	       end if;
	       if size = "11" then -- double store
		 v.dstate := 4; v.xaddress(2) := '1';
               end if;
	     else		
	       v.holdn := '0';	-- wait for store queue
	     end if;
	   end if;
	   v.tparerr := tparerr and cachable;
	   v.dparerr := dparerr and cachable and hit and valid;
	end case;
	if (r.werr and not r.stpend) = '1' then
	  v.werr := '0'; v.icenable := '0'; v.stpend := '0';
	  v.req := '0'; v.burst := '0'; twrite := '0'; dwrite := '0';
	  flush := '0'; tdiagwrite := '0'; ddiagwrite := '0';
	  if r.holdn = '1' then
	    error := '1'; v.werr := '0'; werr := '1'; v.dstate := 0;

⌨️ 快捷键说明

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