OpenCores
URL https://opencores.org/ocsvn/potato/potato/trunk

Subversion Repositories potato

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /potato/branches
    from Rev 23 to Rev 25
    Reverse comparison

Rev 23 → Rev 25

/cache-playground/src/pp_cache.vhd
0,0 → 1,185
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.pp_types.all;
use work.pp_utilities.all;
 
--! @brief Simple cache module.
entity pp_cache is
generic(
LINE_SIZE : natural := 8; --! Number of words per cache way
NUM_WAYS : natural := 2; --! Number of ways per set
NUM_SETS : natural := 128 --! Number of sets in the cache
);
port(
clk : in std_logic;
reset : in std_logic;
 
-- Control interface:
cache_enable : in std_logic;
cache_flush : in std_logic;
cached_areas : in std_logic_vector(31 downto 0);
 
-- Memory interface:
mem_address_in : in std_logic_vector(31 downto 0);
mem_data_in : in std_logic_vector(31 downto 0);
mem_data_out : out std_logic_vector(31 downto 0);
mem_data_size : in std_logic_vector( 1 downto 0);
mem_read_req : in std_logic;
mem_read_ack : out std_logic;
mem_write_req : in std_logic;
mem_write_ack : out std_logic;
 
-- Wishbone interface:
wb_inputs : in wishbone_master_inputs;
wb_outputs : out wishbone_master_outputs
);
end entity pp_cache;
 
architecture behaviour of pp_cache is
 
-- Input-related signals:
signal input_address_set : std_logic_vector(log2(NUM_SETS) - 1 downto 0);
signal input_address_word : std_logic_vector(log2(LINE_SIZE / 4) - 1 downto 0);
signal input_address_tag : std_logic_vector(31 - log2(NUM_SETS) - log2(LINE_SIZE / 4) downto 0);
signal input_address_cached : boolean;
 
-- Cache controller signals:
type state_type is (IDLE, SINGLE_READ, SINGLE_WRITE);
signal state : state_type := IDLE;
 
-- Gets the amount to shift output data to the processor with for requests of size != 32 bits:
function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
return natural is
begin
case size is
when b"01" =>
case address(1 downto 0) is
when b"00" =>
return 0;
when b"01" =>
return 8;
when b"10" =>
return 16;
when b"11" =>
return 24;
when others =>
return 0;
end case;
when b"10" =>
if address(1) = '0' then
return 0;
else
return 16;
end if;
when others =>
return 0;
end case;
end function get_data_shift;
 
-- Gets the value of the sel signals to the wishbone interconnect for the specified
-- operand size and address.
function get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
return std_logic_vector is
begin
case size is
when b"01" =>
case address(1 downto 0) is
when b"00" =>
return b"0001";
when b"01" =>
return b"0010";
when b"10" =>
return b"0100";
when b"11" =>
return b"1000";
when others =>
return b"0001";
end case;
when b"10" =>
if address(1) = '0' then
return b"0011";
else
return b"1100";
end if;
when others =>
return b"1111";
end case;
end function get_data_sel;
 
begin
 
-- Decompose the input address:
input_address_word <= mem_address_in(log2(LINE_SIZE / 4) - 1 downto 0);
input_address_set <= mem_address_in(log2(NUM_SETS) + log2(LINE_SIZE / 4) - 1 downto log2(LINE_SIZE / 4));
input_address_tag <= mem_address_in(31 downto log2(NUM_SETS) + log2(LINE_SIZE / 4));
 
-- Check if the current input address should be/is in the cache:
input_address_cached <= cached_areas(to_integer(unsigned(mem_address_in(31 downto 27)))) = '1';
 
-- Acknowledge signals:
mem_write_ack <= '1' when state = SINGLE_WRITE and wb_inputs.ack = '1' else '0';
 
controller: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
state <= IDLE;
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
mem_read_ack <= '0';
else
case state is
when IDLE =>
mem_read_ack <= '0';
 
--if input_address_cached and cache_enable = '1' then
-- if mem_read_req = '1' then
-- elsif mem_write_req = '1' then
-- end if;
--else
if mem_read_req = '1' then -- Do an uncached read
wb_outputs.adr <= mem_address_in;
wb_outputs.sel <= get_data_sel(mem_data_size, mem_address_in);
wb_outputs.cyc <= '1';
wb_outputs.stb <= '1';
wb_outputs.we <= '0';
state <= SINGLE_READ;
elsif mem_write_req = '1' then -- Do an uncached write
wb_outputs.adr <= mem_address_in;
wb_outputs.dat <= std_logic_vector(shift_left(unsigned(mem_data_in),
get_data_shift(mem_data_size, mem_address_in)));
wb_outputs.sel <= get_data_sel(mem_data_size, mem_address_in);
wb_outputs.cyc <= '1';
wb_outputs.stb <= '1';
wb_outputs.we <= '1';
state <= SINGLE_WRITE;
end if;
--end if;
when SINGLE_READ =>
if wb_inputs.ack = '1' then
mem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat),
get_data_shift(mem_data_size, mem_address_in)));
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
mem_read_ack <= '1';
state <= IDLE;
end if;
when SINGLE_WRITE =>
if wb_inputs.ack = '1' then
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
wb_outputs.we <= '0';
state <= IDLE;
end if;
end case;
end if;
end if;
end process controller;
 
end architecture behaviour;
/cache-playground/src/pp_types.vhd
42,6 → 42,22
MEMOP_SIZE_BYTE, MEMOP_SIZE_HALFWORD, MEMOP_SIZE_WORD
);
 
--! Wishbone master output signals:
type wishbone_master_outputs is record
adr : std_logic_vector(31 downto 0);
sel : std_logic_vector( 3 downto 0);
cyc : std_logic;
stb : std_logic;
we : std_logic;
dat : std_logic_vector(31 downto 0);
end record;
 
--! Wishbone master input signals:
type wishbone_master_inputs is record
dat : std_logic_vector(31 downto 0);
ack : std_logic;
end record;
 
end package pp_types;
 
package body pp_types is
/cache-playground/src/pp_potato.vhd
5,6 → 5,8
library ieee;
use ieee.std_logic_1164.all;
 
use work.pp_types.all;
 
--! @brief The Potato Processor.
--! This file provides a Wishbone-compatible interface to the Potato processor.
entity pp_potato is
54,6 → 56,10
signal dmem_write_req : std_logic;
signal dmem_write_ack : std_logic;
 
-- Wishbone signals:
signal icache_inputs, dcache_inputs : wishbone_master_inputs;
signal icache_outputs, dcache_outputs : wishbone_master_outputs;
 
begin
processor: entity work.pp_core
generic map(
82,22 → 88,52
irq => irq
);
 
wb_if: entity work.pp_wb_adapter
icache: entity work.pp_cache
port map(
clk => clk,
reset => reset,
imem_address => imem_address,
imem_data_out => imem_data,
imem_read_req => imem_req,
imem_read_ack => imem_ack,
dmem_address => dmem_address,
dmem_data_in => dmem_data_out,
dmem_data_out => dmem_data_in,
dmem_data_size => dmem_data_size,
dmem_read_req => dmem_read_req,
dmem_write_req => dmem_write_req,
dmem_read_ack => dmem_read_ack,
dmem_write_ack => dmem_write_ack,
cache_enable => '0',
cache_flush => '0',
cached_areas => (others => '0'),
mem_address_in => imem_address,
mem_data_out => imem_data,
mem_data_in => (others => '0'),
mem_data_size => b"00",
mem_read_req => imem_req,
mem_read_ack => imem_ack,
mem_write_req => '0',
mem_write_ack => open,
wb_inputs => icache_inputs,
wb_outputs => icache_outputs
);
 
dcache: entity work.pp_cache
port map(
clk => clk,
reset => reset,
cache_enable => '0',
cache_flush => '0',
cached_areas => (others => '0'),
mem_address_in => dmem_address,
mem_data_in => dmem_data_out,
mem_data_out => dmem_data_in,
mem_data_size => dmem_data_size,
mem_read_req => dmem_read_req,
mem_read_ack => dmem_read_ack,
mem_write_req => dmem_write_req,
mem_write_ack => dmem_write_ack,
wb_inputs => dcache_inputs,
wb_outputs => dcache_outputs
);
 
arbiter: entity work.pp_wb_arbiter
port map(
clk => clk,
reset => reset,
m1_inputs => dcache_inputs,
m1_outputs => dcache_outputs,
m2_inputs => icache_inputs,
m2_outputs => icache_outputs,
wb_adr_out => wb_adr_out,
wb_sel_out => wb_sel_out,
wb_cyc_out => wb_cyc_out,
/cache-playground/src/pp_wb_arbiter.vhd
0,0 → 1,99
-- The Potato Processor - A simple processor for FPGAs
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
 
library ieee;
use ieee.std_logic_1164.all;
 
use work.pp_types.all;
 
--! @brief Simple priority-based wishbone arbiter.
--! This module is used as an arbiter between the instruction and data caches.
entity pp_wb_arbiter is
port(
clk : in std_logic;
reset : in std_logic;
 
-- Wishbone input 1:
m1_inputs : out wishbone_master_inputs;
m1_outputs : in wishbone_master_outputs;
 
-- Wishbone input 2:
m2_inputs : out wishbone_master_inputs;
m2_outputs : in wishbone_master_outputs;
 
-- Wishbone interface:
wb_adr_out : out std_logic_vector(31 downto 0);
wb_sel_out : out std_logic_vector( 3 downto 0);
wb_cyc_out : out std_logic;
wb_stb_out : out std_logic;
wb_we_out : out std_logic;
wb_dat_out : out std_logic_vector(31 downto 0);
wb_dat_in : in std_logic_vector(31 downto 0);
wb_ack_in : in std_logic
);
end entity pp_wb_arbiter;
 
architecture behaviour of pp_wb_arbiter is
 
type state_type is (IDLE, M1_BUSY, M2_BUSY);
signal state : state_type := IDLE;
 
begin
 
m1_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M1_BUSY else (ack => '0', dat => (others => '0'));
m2_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M2_BUSY else (ack => '0', dat => (others => '0'));
 
output_mux: process(state, m1_outputs, m2_outputs)
begin
case state is
when IDLE =>
wb_adr_out <= (others => '0');
wb_sel_out <= (others => '0');
wb_dat_out <= (others => '0');
wb_cyc_out <= '0';
wb_stb_out <= '0';
wb_we_out <= '0';
when M1_BUSY =>
wb_adr_out <= m1_outputs.adr;
wb_sel_out <= m1_outputs.sel;
wb_dat_out <= m1_outputs.dat;
wb_cyc_out <= m1_outputs.cyc;
wb_stb_out <= m1_outputs.stb;
wb_we_out <= m1_outputs.we;
when M2_BUSY =>
wb_adr_out <= m2_outputs.adr;
wb_sel_out <= m2_outputs.sel;
wb_dat_out <= m2_outputs.dat;
wb_cyc_out <= m2_outputs.cyc;
wb_stb_out <= m2_outputs.stb;
wb_we_out <= m2_outputs.we;
end case;
end process output_mux;
 
controller: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
else
case state is
when IDLE =>
if m1_outputs.cyc = '1' then
state <= M1_BUSY;
elsif m2_outputs.cyc = '1' then
state <= M2_BUSY;
end if;
when M1_BUSY =>
if m1_outputs.cyc = '0' then
state <= IDLE;
end if;
when M2_BUSY =>
if m2_outputs.cyc = '0' then
state <= IDLE;
end if;
end case;
end if;
end if;
end process controller;
 
end architecture behaviour;
/cache-playground/Makefile
8,6 → 8,7
src/pp_alu.vhd \
src/pp_alu_mux.vhd \
src/pp_alu_control_unit.vhd \
src/pp_cache.vhd \
src/pp_comparator.vhd \
src/pp_constants.vhd \
src/pp_control_unit.vhd \
25,7 → 26,7
src/pp_register_file.vhd \
src/pp_types.vhd \
src/pp_utilities.vhd \
src/pp_wb_adapter.vhd \
src/pp_wb_arbiter.vhd \
src/pp_writeback.vhd
TESTBENCHES := \
testbenches/tb_processor.vhd \
95,7 → 96,7
test -d tests-build || mkdir tests-build
for test in $(RISCV_TESTS) $(LOCAL_TESTS); do \
echo "Compiling test $$test..."; \
$(TOOLCHAIN_PREFIX)-gcc -c -m32 -Iriscv-tests -o tests-build/$$test.o tests/$$test.S; \
$(TOOLCHAIN_PREFIX)-gcc -c -m32 -march=RV32I -Iriscv-tests -o tests-build/$$test.o tests/$$test.S; \
$(TOOLCHAIN_PREFIX)-ld -m elf32lriscv -T tests.ld tests-build/$$test.o -o tests-build/$$test.elf; \
scripts/extract_hex.sh tests-build/$$test.elf tests-build/$$test-imem.hex tests-build/$$test-dmem.hex; \
done

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.