mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-02-21 22:58:06 +00:00
This splits out the decoding done in the decode0 step into a separate predecoder, used when writing instructions into the icache. The icache now holds 36 bits per instruction rather than 32. For valid instructions, those 36 bits comprise the bottom 26 bits of the instruction word, a 9-bit insn_code value (which uniquely identifies the instruction), and a zero in the MSB. For illegal instructions, the MSB is one and the full instruction word is in the bottom 32 bits. Having the full instruction word available for illegal instructions means that it can be printed in the log when simulating, or in future could be placed in the HEIR register. If we don't have an FPU, then the floating-point instructions are regarded as illegal. In that case, the insn_code values would fit into 8 bits, which could be used in future to reduce the size of decode_rom from 512 to 256 entries. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
87 lines
2.6 KiB
VHDL
87 lines
2.6 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use ieee.math_real.all;
|
|
|
|
entity cache_ram is
|
|
generic(
|
|
ROW_BITS : integer := 16;
|
|
WIDTH : integer := 64;
|
|
BYTEWID : integer := 8;
|
|
TRACE : boolean := false;
|
|
ADD_BUF : boolean := false
|
|
);
|
|
|
|
port(
|
|
clk : in std_logic;
|
|
rd_en : in std_logic;
|
|
rd_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
|
|
rd_data : out std_logic_vector(WIDTH - 1 downto 0);
|
|
wr_sel : in std_logic_vector(WIDTH/BYTEWID - 1 downto 0);
|
|
wr_addr : in std_logic_vector(ROW_BITS - 1 downto 0);
|
|
wr_data : in std_logic_vector(WIDTH - 1 downto 0)
|
|
);
|
|
|
|
end cache_ram;
|
|
|
|
architecture rtl of cache_ram is
|
|
constant SIZE : integer := 2**ROW_BITS;
|
|
|
|
type ram_type is array (0 to SIZE - 1) of std_logic_vector(WIDTH - 1 downto 0);
|
|
signal ram : ram_type;
|
|
attribute ram_style : string;
|
|
attribute ram_style of ram : signal is "block";
|
|
|
|
signal rd_data0 : std_logic_vector(WIDTH - 1 downto 0);
|
|
|
|
begin
|
|
process(clk)
|
|
variable lbit : integer range 0 to WIDTH - 1;
|
|
variable mbit : integer range 0 to WIDTH - 1;
|
|
variable widx : integer range 0 to SIZE - 1;
|
|
constant sel0 : std_logic_vector(WIDTH/BYTEWID - 1 downto 0)
|
|
:= (others => '0');
|
|
begin
|
|
if rising_edge(clk) then
|
|
if TRACE then
|
|
if wr_sel /= sel0 then
|
|
report "write a:" & to_hstring(wr_addr) &
|
|
" sel:" & to_hstring(wr_sel) &
|
|
" dat:" & to_hstring(wr_data);
|
|
end if;
|
|
end if;
|
|
for i in 0 to WIDTH/BYTEWID-1 loop
|
|
lbit := i * BYTEWID;
|
|
mbit := lbit + BYTEWID - 1;
|
|
widx := to_integer(unsigned(wr_addr));
|
|
if wr_sel(i) = '1' then
|
|
ram(widx)(mbit downto lbit) <= wr_data(mbit downto lbit);
|
|
end if;
|
|
end loop;
|
|
if rd_en = '1' then
|
|
rd_data0 <= ram(to_integer(unsigned(rd_addr)));
|
|
if TRACE then
|
|
report "read a:" & to_hstring(rd_addr) &
|
|
" dat:" & to_hstring(ram(to_integer(unsigned(rd_addr))));
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
buf: if ADD_BUF generate
|
|
begin
|
|
process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
rd_data <= rd_data0;
|
|
end if;
|
|
end process;
|
|
end generate;
|
|
|
|
nobuf: if not ADD_BUF generate
|
|
begin
|
|
rd_data <= rd_data0;
|
|
end generate;
|
|
|
|
end;
|