📄 dcache.vhd
字号:
v.holdn := '1'; v.dstate := 0;
else
v.dstate := 3; v.wexc := '1'; v.mds := '0';
v.holdn := '0'; error := '0';
end if;
end if;
end if;
when 1 => -- read miss, wait for memory data
v.req := '1'; v.holdn := '0'; rdatasel := memory;
v.burst := r.burst and not r.xaddress(2);
if mcdo.ready = '1' then
v.mds := r.nomds; v.req := v.burst; v.burst := '0'; v.dstate := 2;
end if;
when 2 => -- read miss, update cache and send data to IU
rdatasel := memory;
if (mcdo.dcs = "01") then
twrite := r.cachable and r.hit;
elsif (mcdo.dcs(1) = '1') then
twrite := r.cachable;
end if;
dwrite := twrite;
if (size = "11") and (r.xaddress(2) = '0') then
v.xaddress(2) := '1';
if mcdo.ready = '1' then -- true on 0-ws burst read
v.dstate := 2;
else
v.dstate := 1; v.req := '1'; v.nomds := not ico.hold;
end if;
else
if (dci.enaddr = '1') and (mcdo.dcs /= "00") then
v.dstate := 3; v.holdn := '0';
else
v.dstate := 0;
end if;
end if;
when 3 => -- return from read miss with load pending
taddr := dci.maddress(TAG_HIGH downto LINE_LOW);
v.dstate := 0;
when 4 => -- second part of double store cycle
v.dstate := 0; v.wb.data2 := eaddress;
if (mcdo.dcs /= "00") and (r.hit = '1') then -- write hit
twrite := '1'; dwrite := twrite;
end if;
when 5 => -- icache diag access
rdatasel := icache; v.icenable := '1'; v.holdn := '0';
if ((ico.diagrdy and (not read)) or not r.mds) = '1' then
v.dstate := 3; v.icenable := '0';
elsif ico.diagrdy = '1' then
v.mds := not read; v.icenable := read;
end if;
when others => null;
end case;
-- select data to return on read access
-- align if byte/half word read from cache or memory.
rdata := (others => '0');
align_data := (others => '0');
case rdatasel is
when dtag => rdata(TAG_HIGH downto TAG_LOW) := dcramo.dtramout.tag;
rdata(DLINE_SIZE -1 downto 0) := dcramo.dtramout.valid;
rdata(31) := dcramo.dtramout.parity;
when icache => rdata := ico.diagdata;
when ddata | memory =>
if rdatasel = ddata then align_data := dcramo.ddramout.data;
else align_data := mcdo.data; end if;
case size is
when "00" => -- byte read
case maddress(1 downto 0) is
when "00" =>
rdata(7 downto 0) := align_data(31 downto 24);
if signed = '1' then rdata(31 downto 8) := (others => align_data(31)); end if;
when "01" =>
rdata(7 downto 0) := align_data(23 downto 16);
if signed = '1' then rdata(31 downto 8) := (others => align_data(23)); end if;
when "10" =>
rdata(7 downto 0) := align_data(15 downto 8);
if signed = '1' then rdata(31 downto 8) := (others => align_data(15)); end if;
when others =>
rdata(7 downto 0) := align_data(7 downto 0);
if signed = '1' then rdata(31 downto 8) := (others => align_data(7)); end if;
end case;
when "01" => -- half-word read
if maddress(1) = '1' then
rdata(15 downto 0) := align_data(15 downto 0);
if signed = '1' then rdata(31 downto 15) := (others => align_data(15)); end if;
else
rdata(15 downto 0) := align_data(31 downto 16);
if signed = '1' then rdata(31 downto 15) := (others => align_data(31)); end if;
end if;
when others => -- single and double word read
rdata := align_data;
end case;
end case;
-- select which data to update the data cache with
if read = '1' then
ddatain := mcdo.data; -- load full word from memory
else
case size is -- merge data during partial write
when "00" =>
case maddress(1 downto 0) is
when "00" =>
ddatain := eaddress(7 downto 0) & dcramo.ddramout.data(23 downto 0);
when "01" =>
ddatain := dcramo.ddramout.data(31 downto 24) & eaddress(7 downto 0) &
dcramo.ddramout.data(15 downto 0);
when "10" =>
ddatain := dcramo.ddramout.data(31 downto 16) & eaddress(7 downto 0) &
dcramo.ddramout.data(7 downto 0);
when others =>
ddatain := dcramo.ddramout.data(31 downto 8) & eaddress(7 downto 0);
end case;
when "01" =>
if maddress(1) = '0' then
ddatain := eaddress(15 downto 0) & dcramo.ddramout.data(15 downto 0);
else
ddatain := dcramo.ddramout.data(31 downto 16) & eaddress(15 downto 0);
end if;
when others =>
ddatain := eaddress;
end case;
end if;
-- Generate new valid bits
vmaskraw := decode(r.xaddress(LINE_HIGH downto LINE_LOW));
case mcdo.dcs is
when "00" => vmask := (others => '0');
when "01" => vmask := dcramo.dtramout.valid or vmaskraw;
when others =>
if hit = '1' then vmask := dcramo.dtramout.valid or vmaskraw;
else vmask := vmaskraw; end if;
end case;
if mcdo.mexc = '1' then
vmask := vmask and not vmaskraw; dwrite := '0';
end if;
if tdiagwrite = '1' then -- diagnostic tag write
vmask := eaddress(DLINE_SIZE - 1 downto 0);
end if;
if (r.dstate /= 0) and (twrite = '1') then
taddr(OFFSET_HIGH downto LINE_LOW) := r.xaddress(OFFSET_HIGH downto LINE_LOW);
end if;
v.lineaddr := taddr(LINE_HIGH downto LINE_LOW);
-- cache flush
if (dci.flush or flush) = '1' then
v.flush := '1'; v.faddr := (others => '0');
end if;
if r.flush = '1' then
twrite := '1'; vmask := (others => '0'); v.faddr := r.faddr +1;
maddress(TAG_HIGH downto TAG_LOW) := (others => '0');
taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;
taddr(OFFSET_LOW-1 downto LINE_LOW) := (others => '0');
if (r.faddr(DOFFSET_BITS -1) and not v.faddr(DOFFSET_BITS -1)) = '1' then
v.flush := '0';
end if;
end if;
-- parity generation
v.taddrpar := '0';
if DTAGPAR then
v.taddrpar := xorv(taddr(OFFSET_HIGH downto OFFSET_LOW)) and DTAGAPAR;
end if;
v.daddrpar := '0';
if DDATPAR then
v.daddrpar := xorv(taddr(OFFSET_HIGH downto LINE_LOW)) and DDATAPAR;
end if;
tparin := '0'; v.dparerr2 := '0';
if DTAGPAR then
tparin := xorv(vmask & maddress(TAG_HIGH downto TAG_LOW));
if (r.flush and DTAGAPAR) = '1' then
tparin := xorv(r.faddr & tparin);
else
tparin := xorv(v.taddrpar & tparin);
end if;
-- if tdiagwrite = '1' then tparin := tparin xor maddress(31); end if;
if tdiagwrite = '1' then tparin := tparin xor dci.maddress(31); end if;
v.dparerr2 := r.dparerr;
end if;
dparin := '0'; v.tparerr2 := '0';
if DDATPAR then
dparin := xorv(v.daddrpar & ddatain); v.tparerr2 := r.tparerr;
-- if ddiagwrite = '1' then dparin := dparin xor maddress(31); end if;
if ddiagwrite = '1' then dparin := dparin xor dci.maddress(31); end if;
end if;
-- reset
if rst = '0' then
v.dstate := 0; v.stpend := '0'; v.req := '0'; v.burst := '0';
v.read := '0'; v.flush := '0'; v.werr := '0';
end if;
-- Drive signals
c <= v; -- register inputs
-- tag ram inputs
dcrami.dtramin.valid <= vmask;
dcrami.dtramin.tag <= maddress(TAG_HIGH downto TAG_LOW);
dcrami.dtramin.enable <= enable;
dcrami.dtramin.write <= twrite;
dcrami.dtramin.parity <= tparin;
-- data ram inputs
dcrami.ddramin.enable <= enable;
dcrami.ddramin.address <= taddr(OFFSET_HIGH downto LINE_LOW) ;
dcrami.ddramin.data <= ddatain;
dcrami.ddramin.write <= dwrite;
dcrami.ddramin.parity <= dparin;
-- memory controller inputs
mcdi.address <= r.wb.addr;
if (r.burst and mcdo.ready) = '1' then
mcdi.data <= r.wb.data2;
else
mcdi.data <= r.wb.data1;
end if;
mcdi.asi <= r.wb.asi;
mcdi.burst <= r.burst;
mcdi.size <= r.wb.size;
mcdi.read <= r.wb.read;
mcdi.req <= r.req;
mcdi.tparerr <= r.tparerr and not r.tparerr2;
mcdi.dparerr <= r.dparerr and not r.dparerr2;
mcdi.flush <= r.flush;
-- diagnostic instruction cache
dco.icdiag.flush <= iflush;
dco.icdiag.read <= read;
dco.icdiag.tag <= not asi(0);
dco.icdiag.addr <= r.xaddress;
dco.icdiag.enable <= r.icenable;
-- IU data cache inputs
dco.data <= rdata;
dco.mexc <= (mcdo.mexc and not r.stpend) or r.wexc or error;
dco.wexc <= r.wexc or werr;
dco.hold <= r.holdn;
dco.mds <= r.mds;
end process;
-- Local registers
dlat : process(clk)
begin
if clk'event and (clk='1') then
r <= c;
end if;
end process;
end ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -