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

Subversion Repositories potato

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /potato/trunk
    from Rev 36 to Rev 45
    Reverse comparison

Rev 36 → Rev 45

/tests/sw-jal.S
0,0 → 1,41
# The Potato Processor - A simple RISC-V based processor for FPGAs
# (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
# Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
 
#include "riscv_test.h"
#include "test_macros.h"
 
.section .text
RVTEST_RV32U
RVTEST_CODE_BEGIN
 
test_1:
li TESTNUM, 1
 
la ra, test_failed
la sp, temp
sw ra, 0(sp)
jal ra, test_cmp
 
1:
j fail
j pass
 
test_cmp:
la t0, 1b
bne ra, t0, fail
addi ra, ra, 4
ret
 
TEST_PASSFAIL
RVTEST_CODE_END
 
test_failed:
RVTEST_FAIL
# Allocate a 32-bit word to store some data into
.section .data
temp:
.word 0x00000000
 
 
/src/pp_execute.vhd
197,9 → 197,9
jump_target_out <= jump_target;
 
evec_out <= evec_forwarded;
exception_taken <= decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted;
exception_taken <= (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted) and not stall;
 
irq_asserted <= (not stall) and to_std_logic(exception_context_forwarded.status.ei = '1' and
irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and
(irq and exception_context_forwarded.status.im) /= x"00");
 
rs1_data <= rs1_data_in;
/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
/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, dmem_if_inputs : wishbone_master_inputs;
signal icache_outputs, dmem_if_outputs : wishbone_master_outputs;
 
begin
processor: entity work.pp_core
generic map(
82,22 → 88,54
irq => irq
);
 
wb_if: entity work.pp_wb_adapter
icache: entity work.pp_icache
generic map(
LINE_SIZE => 4,
NUM_LINES => 128
) port map(
clk => clk,
reset => reset,
cache_enable => '1',
cache_flush => '0',
cached_areas => (others => '1'),
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
);
 
dmem_if: entity work.pp_wb_adapter
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_read_ack => dmem_read_ack,
dmem_write_req => dmem_write_req,
dmem_read_ack => dmem_read_ack,
dmem_write_ack => dmem_write_ack,
wb_inputs => dmem_if_inputs,
wb_outputs => dmem_if_outputs
);
 
arbiter: entity work.pp_wb_arbiter
port map(
clk => clk,
reset => reset,
--m1_inputs => dmem_if_inputs,
--m1_outputs => dmem_if_outputs,
m1_inputs => icache_inputs,
m1_outputs => icache_outputs,
m2_inputs => dmem_if_inputs,
m2_outputs => dmem_if_outputs,
wb_adr_out => wb_adr_out,
wb_sel_out => wb_sel_out,
wb_cyc_out => wb_cyc_out,
/src/pp_wb_adapter.vhd
6,6 → 6,9
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.pp_types.all;
use work.pp_utilities.all;
 
--! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches.
entity pp_wb_adapter is
port(
12,12 → 15,6
clk : in std_logic;
reset : in std_logic;
 
-- Processor instruction memory signals:
signal imem_address : in std_logic_vector(31 downto 0);
signal imem_data_out : out std_logic_vector(31 downto 0);
signal imem_read_req : in std_logic;
signal imem_read_ack : out std_logic;
-- Processor data memory signals:
signal dmem_address : in std_logic_vector(31 downto 0);
signal dmem_data_in : in std_logic_vector(31 downto 0); -- Data in to the bus
29,20 → 26,14
signal dmem_write_ack : out std_logic;
 
-- Wishbone interface:
wb_adr_out : out std_logic_vector(31 downto 0);
wb_dat_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_in : in std_logic_vector(31 downto 0);
wb_ack_in : in std_logic
wb_inputs : in wishbone_master_inputs;
wb_outputs : out wishbone_master_outputs
);
end entity pp_wb_adapter;
 
architecture behaviour of pp_wb_adapter is
 
type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK, IREAD_WAIT_ACK);
type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK);
signal state : states;
 
signal dmem_r_ack : std_logic;
75,40 → 66,9
end case;
end function get_data_shift;
 
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
 
imem_read_ack <= '1' when state = IREAD_WAIT_ACK and wb_ack_in = '1' else '0';
imem_data_out <= wb_dat_in;
 
dmem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_ack_in = '1' else '0';
dmem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_inputs.ack = '1' else '0';
dmem_read_ack <= dmem_r_ack;
 
wishbone: process(clk)
116,8 → 76,8
if rising_edge(clk) then
if reset = '1' then
state <= IDLE;
wb_cyc_out <= '0';
wb_stb_out <= '0';
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
dmem_r_ack <= '0';
else
case state is
126,43 → 86,36
 
-- Prioritize requests from the data memory:
if dmem_write_req = '1' then
wb_adr_out <= dmem_address;
wb_dat_out <= std_logic_vector(shift_left(unsigned(dmem_data_in),
wb_outputs.adr <= dmem_address;
wb_outputs.dat <= std_logic_vector(shift_left(unsigned(dmem_data_in),
get_data_shift(dmem_data_size, dmem_address)));
wb_sel_out <= get_data_sel(dmem_data_size, dmem_address);
wb_cyc_out <= '1';
wb_stb_out <= '1';
wb_we_out <= '1';
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
wb_outputs.cyc <= '1';
wb_outputs.stb <= '1';
wb_outputs.we <= '1';
state <= WRITE_WAIT_ACK;
elsif dmem_read_req = '1' and dmem_r_ack = '0' then
wb_adr_out <= dmem_address;
wb_sel_out <= get_data_sel(dmem_data_size, dmem_address);
wb_cyc_out <= '1';
wb_stb_out <= '1';
wb_we_out <= '0';
elsif dmem_read_req = '1' then
wb_outputs.adr <= dmem_address;
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
wb_outputs.cyc <= '1';
wb_outputs.stb <= '1';
wb_outputs.we <= '0';
state <= READ_WAIT_ACK;
elsif imem_read_req = '1' then
wb_adr_out <= imem_address;
wb_sel_out <= (others => '1');
wb_cyc_out <= '1';
wb_stb_out <= '1';
wb_we_out <= '0';
state <= IREAD_WAIT_ACK;
end if;
when READ_WAIT_ACK =>
if wb_ack_in = '1' then
dmem_data_out <= std_logic_vector(shift_right(unsigned(wb_dat_in),
if wb_inputs.ack = '1' then
dmem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat),
get_data_shift(dmem_data_size, dmem_address)));
wb_cyc_out <= '0';
wb_stb_out <= '0';
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
dmem_r_ack <= '1';
state <= IDLE;
end if;
when WRITE_WAIT_ACK | IREAD_WAIT_ACK =>
if wb_ack_in = '1' then
wb_cyc_out <= '0';
wb_stb_out <= '0';
wb_we_out <= '0';
when WRITE_WAIT_ACK =>
if wb_inputs.ack = '1' then
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
wb_outputs.we <= '0';
state <= IDLE;
end if;
end case;
src/pp_wb_adapter.vhd Property changes : Added: svn:mergeinfo ## -0,0 +0,1 ## Merged /potato/branches/cache-playground/src/pp_wb_adapter.vhd:r31-33,44 Index: src/pp_memory.vhd =================================================================== --- src/pp_memory.vhd (revision 36) +++ src/pp_memory.vhd (revision 45) @@ -110,7 +110,7 @@ if exception_in = '1' then exception_context_out.status <= ( pim => exception_context_in.status.im, - im => exception_context_in.status.im, + im => (others => '0'), pei => exception_context_in.status.ei, ei => '0' ); Index: src/pp_utilities.vhd =================================================================== --- src/pp_utilities.vhd (revision 36) +++ src/pp_utilities.vhd (revision 45) @@ -19,6 +19,11 @@ --! Calculates log2 with integers. function log2(input : in natural) return natural; + -- Gets the value of the sel signals to the wishbone interconnect for the specified + -- operand size and address. + function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) + return std_logic_vector; + end package pp_utilities; package body pp_utilities is @@ -35,7 +40,7 @@ function is_pow2(input : in natural) return boolean is variable c : natural := 1; begin - for i in 0 to 31 loop + for i in 0 to 30 loop -- FIXME: Simulator complains about 2^31 being out of range! if input = i then return true; end if; @@ -58,4 +63,32 @@ return retval; end function log2; + function wb_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 wb_get_data_sel; + end package body pp_utilities;
/src/pp_icache.vhd
0,0 → 1,293
-- 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 read-only direct-mapped instruction cache.
entity pp_icache is
generic(
LINE_SIZE : natural := 4; --! Number of words per cache line
NUM_LINES : natural := 128 --! Number of lines 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_icache;
 
architecture behaviour of pp_icache is
 
-- Counter types:
subtype line_counter_type is natural range 0 to NUM_LINES;
subtype word_counter_type is natural range 0 to LINE_SIZE;
 
-- Cache line types:
subtype cache_line_type is std_logic_vector((LINE_SIZE * 32) - 1 downto 0);
type cache_line_word_array is array(0 to LINE_SIZE - 1) of std_logic_vector(31 downto 0);
type cache_line_array is array(0 to NUM_LINES - 1) of cache_line_type;
 
-- Cache tag type:
subtype cache_tag_type is std_logic_vector(31 - log2(LINE_SIZE * 4) - log2(NUM_LINES) downto 0);
type cache_tag_array is array(0 to NUM_LINES - 1) of cache_tag_type;
 
-- Cache memories:
signal cache_memory : cache_line_array;
signal tag_memory : cache_tag_array;
signal valid : std_logic_vector(NUM_LINES - 1 downto 0) := (others => '0');
 
attribute ram_style : string;
attribute ram_style of cache_memory: signal is "block";
--attribute ram_style of tag_memory: signal is "block";
 
-- Cache controller signals:
type state_type is (IDLE, CACHE_READ_STALL, SINGLE_READ, SINGLE_WRITE,
LOAD_CACHELINE_START, LOAD_CACHELINE_WAIT_ACK, LOAD_CACHELINE_FINISH);
signal state : state_type := IDLE;
 
-- Is the current input address in the cache?
signal input_address_cached : boolean;
 
-- Input address components:
signal input_address_line : std_logic_vector(log2(NUM_LINES) - 1 downto 0);
signal input_address_word : std_logic_vector(log2(LINE_SIZE) - 1 downto 0);
signal input_address_tag : std_logic_vector(31 - log2(LINE_SIZE * 4) - log2(NUM_LINES) downto 0);
 
-- Cacheline matching the current input address:
signal current_cache_line, cache_lookup : cache_line_type;
signal current_cache_line_words : cache_line_word_array;
signal current_tag : cache_tag_type;
 
-- Base address to store a cacheline to:
signal cl_store_address : std_logic_vector(31 downto log2(LINE_SIZE * 4));
-- Base address to load a cacheline from:
signal cl_load_address : std_logic_vector(31 downto log2(LINE_SIZE * 4));
-- Cache line to load:
signal cl_current_line : line_counter_type;
-- Current word being loaded/stored:
signal cl_current_word : word_counter_type;
 
-- Buffer for holding a cache line while loading:
signal load_buffer : cache_line_type;
signal load_buffer_tag : cache_tag_type;
 
-- Causes a cache line to be stored in the cache memory:
signal store_cache_line : std_logic;
 
-- Set when the current input address matches a cache line:
signal cache_hit : std_logic;
 
-- For regular reads:
signal read_ack : std_logic;
signal read_data_out : std_logic_vector(31 downto 0);
 
-- For regular writes:
signal write_ack : std_logic;
 
-- 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;
 
begin
 
--assert is_pow2(LINE_SIZE) report "Cache line size must be a power of 2!" severity FAILURE;
--assert is_pow2(NUM_LINES) report "Number of cache lines must be a power of 2!" severity FAILURE;
 
-- 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';
 
mem_data_out <= current_cache_line_words(to_integer(unsigned(input_address_word))) when
input_address_cached and cache_enable = '1' and cache_flush = '0'
else read_data_out;
mem_read_ack <= (cache_hit and mem_read_req)
when state = IDLE and input_address_cached and cache_enable = '1' and cache_flush = '0'
else read_ack;
write_ack <= wb_inputs.ack when state = SINGLE_WRITE else '0';
mem_write_ack <= write_ack;
 
input_address_line <= mem_address_in(log2(LINE_SIZE * 4) + log2(NUM_LINES) - 1 downto log2(LINE_SIZE * 4));
input_address_tag <= mem_address_in(31 downto log2(LINE_SIZE * 4) + log2(NUM_LINES));
 
find_word: process(clk)
begin
if rising_edge(clk) then
input_address_word <= mem_address_in(log2(LINE_SIZE * 4) - 1 downto 2);
end if;
end process find_word;
 
cacheline_lookup: process(clk)
begin
if rising_edge(clk) then
if store_cache_line = '1' then
cache_memory(cl_current_line) <= load_buffer;
end if;
 
current_cache_line <= cache_memory(to_integer(unsigned(input_address_line)));
end if;
end process cacheline_lookup;
 
decompose_cache_line: for i in 0 to LINE_SIZE - 1 generate
current_cache_line_words(i) <= current_cache_line(32 * i + 31 downto 32 * i);
end generate decompose_cache_line;
 
tag_lookup: process(clk)
begin
if rising_edge(clk) then
if reset = '1' then
cache_hit <= '0';
else
if store_cache_line = '1' then
tag_memory(cl_current_line) <= load_buffer_tag;
end if;
current_tag <= tag_memory(to_integer(unsigned(input_address_line)));
cache_hit <= valid(to_integer(unsigned(input_address_line))) and to_std_logic(tag_memory(to_integer(unsigned(input_address_line))) = input_address_tag);
end if;
end if;
end process tag_lookup;
 
controller: process(clk)
variable current_word : std_logic_vector(31 downto 0);
begin
if rising_edge(clk) then
if reset = '1' then
state <= IDLE;
wb_outputs.cyc <= '0';
wb_outputs.stb <= '0';
store_cache_line <= '0';
read_ack <= '0';
valid <= (others => '0');
read_data_out <= (others => '0');
else
case state is
when IDLE =>
read_ack <= '0';
if cache_flush = '1' then
valid <= (others => '0');
elsif input_address_cached and cache_enable = '1' then
if (mem_read_req = '1' or mem_write_req = '1') and cache_hit = '0' then
wb_outputs.adr <= mem_address_in(31 downto log2(LINE_SIZE * 4)) & (log2(LINE_SIZE * 4) - 1 downto 0 => '0');
wb_outputs.cyc <= '1';
wb_outputs.we <= '0';
wb_outputs.sel <= (others => '1');
load_buffer_tag <= input_address_tag;
cl_load_address <= mem_address_in(31 downto log2(LINE_SIZE * 4));
cl_store_address <= input_address_tag & input_address_line;
cl_current_line <= to_integer(unsigned(input_address_line));
cl_current_word <= 0;
state <= LOAD_CACHELINE_START;
end if;
else
if mem_read_req = '1' and read_ack = '0' then -- Do an uncached read
wb_outputs.adr <= mem_address_in;
wb_outputs.sel <= wb_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 <= wb_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 CACHE_READ_STALL =>
state <= IDLE;
when SINGLE_READ =>
if wb_inputs.ack = '1' then
read_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';
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;
when LOAD_CACHELINE_START =>
wb_outputs.stb <= '1';
wb_outputs.we <= '0';
wb_outputs.adr <= cl_load_address & std_logic_vector(to_unsigned(cl_current_word, log2(LINE_SIZE))) & b"00";
state <= LOAD_CACHELINE_WAIT_ACK;
when LOAD_CACHELINE_WAIT_ACK =>
if wb_inputs.ack = '1' then
wb_outputs.stb <= '0';
load_buffer(cl_current_word * 32 + 31 downto cl_current_word * 32) <= wb_inputs.dat;
if natural(cl_current_word) = LINE_SIZE - 1 then
wb_outputs.cyc <= '0';
store_cache_line <= '1';
state <= LOAD_CACHELINE_FINISH;
else
cl_current_word <= cl_current_word + 1;
state <= LOAD_CACHELINE_START;
end if;
end if;
when LOAD_CACHELINE_FINISH =>
store_cache_line <= '0';
valid(cl_current_line) <= '1';
state <= CACHE_READ_STALL;
end case;
end if;
end if;
end process controller;
 
end architecture behaviour;
/src/pp_wb_arbiter.vhd
0,0 → 1,100
-- 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
state <= IDLE;
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;
/src/pp_csr_unit.vhd
130,14 → 130,16
end if;
end process write;
 
status_out <= exception_context.status when exception_context_write = '1' else status_register;
 
read: process(clk)
begin
if rising_edge(clk) then
if exception_context_write = '1' then
status_out <= exception_context.status;
else
status_out <= status_register;
end if;
--if exception_context_write = '1' then
-- status_out <= exception_context.status;
--else
-- status_out <= status_register;
--end if;
 
if write_mode /= CSR_WRITE_NONE and write_address = CSR_EVEC then
evec_out <= write_data_in;
/src/pp_fetch.vhd
40,23 → 40,17
end entity pp_fetch;
 
architecture behaviour of pp_fetch is
--signal pc, pc_next : std_logic_vector(31 downto 0);
--signal acknowledge, ready : std_logic;
 
signal pc : std_logic_vector(31 downto 0);
signal pc_next : std_logic_vector(31 downto 0);
 
signal pc : std_logic_vector(31 downto 0);
signal pc_next : std_logic_vector(31 downto 0);
signal cancel_fetch : std_logic;
begin
 
imem_address <= pc_next;
imem_address <= pc_next when cancel_fetch = '0' else pc;
 
instruction_data <= imem_data_in;
instruction_ready <= imem_ack and (not stall) and (not cancel_fetch);
instruction_address <= pc;
 
--imem_req <= '1' when cancel_fetch = '0' and
 
imem_req <= '1';
 
set_pc: process(clk)
81,9 → 75,7
 
calc_next_pc: process(reset, stall, branch, exception, imem_ack, branch_target, evec, pc, cancel_fetch)
begin
if reset = '1' then
pc_next <= RESET_ADDRESS;
elsif exception = '1' then
if exception = '1' then
pc_next <= evec;
elsif branch = '1' then
pc_next <= branch_target;
/example/toplevel.vhd
209,8 → 209,8
uart1: entity work.pp_soc_uart
generic map(
FIFO_DEPTH => 64,
--SAMPLE_CLK_DIVISOR => 27 -- For 50 MHz
SAMPLE_CLK_DIVISOR => 33 -- For 60 MHz
SAMPLE_CLK_DIVISOR => 27 -- For 50 MHz
--SAMPLE_CLK_DIVISOR => 33 -- For 60 MHz
) port map(
clk => system_clk,
reset => reset,
301,7 → 301,7
else
case ad_state is
when IDLE =>
if p_cyc_out = '1' and p_stb_out = '1' then
if p_cyc_out = '1' then
if p_adr_out(31 downto 13) = b"0000000000000000000" then
active_module <= MODULE_IMEM;
ad_state <= BUSY;
324,6 → 324,8
active_module <= MODULE_DUMMY;
ad_state <= BUSY;
end if;
else
active_module <= MODULE_NONE;
end if;
when BUSY =>
if p_cyc_out = '0' then
/Makefile
8,6 → 8,7
src/pp_alu.vhd \
src/pp_alu_mux.vhd \
src/pp_alu_control_unit.vhd \
src/pp_icache.vhd \
src/pp_comparator.vhd \
src/pp_constants.vhd \
src/pp_control_unit.vhd \
25,6 → 26,7
src/pp_register_file.vhd \
src/pp_types.vhd \
src/pp_utilities.vhd \
src/pp_wb_arbiter.vhd \
src/pp_wb_adapter.vhd \
src/pp_writeback.vhd
TESTBENCHES := \
76,7 → 78,8
# Local tests to run:
LOCAL_TESTS ?= \
scall \
sbreak
sbreak \
sw-jal
 
all: potato.prj run-tests
 
95,7 → 98,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
/benchmarks/hello/main.c
0,0 → 1,26
// The Potato Processor Benchmark Applications
// (c) Kristian Klomsten Skordal 2015 <kristian.skordal@wafflemail.net>
// Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
 
#include <stdint.h>
#include "../platform.h"
 
void exception_handler(uint32_t cause, void * epc, void * regbase)
{
// Not used in this application
}
 
int main(void)
{
const char * hello_string = "Hello world\n\r";
volatile uint32_t * uart = IO_ADDRESS(UART_BASE);
 
for(int i = 0; hello_string[i] != 0; ++i)
{
while(uart[UART_STATUS >> 2] & (1 << 3));
uart[UART_TX >> 2] = hello_string[i] & 0x000000ff;
}
 
return 0;
}
 
/benchmarks/hello/Makefile
0,0 → 1,46
# The Potato Processor Benchmark Applications
# (c) Kristian Klomsten Skordal 2015 <kristian.skordal@wafflemail.net>
# Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
 
.PHONY: all clean
 
TARGET_PREFIX ?= riscv64-unknown-elf
TARGET_CC := $(TARGET_PREFIX)-gcc
TARGET_LD := $(TARGET_PREFIX)-ld
TARGET_SIZE := $(TARGET_PREFIX)-size
TARGET_OBJCOPY := $(TARGET_PREFIX)-objcopy
HEXDUMP ?= hexdump
 
TARGET_CFLAGS += -m32 -march=RV32I -Wall -O2 -fomit-frame-pointer \
-ffreestanding -fno-builtin -I.. -std=gnu99
TARGET_LDFLAGS += -m elf32lriscv -T../benchmark.ld
 
OBJECTS := main.o start.o
 
all: hello.coe
 
hello.elf: $(OBJECTS)
$(TARGET_LD) -o hello.elf $(TARGET_LDFLAGS) $(OBJECTS)
$(TARGET_SIZE) hello.elf
 
hello.bin: hello.elf
$(TARGET_OBJCOPY) -j .text -j .data -O binary hello.elf hello.bin
 
hello.coe: hello.bin
echo "memory_initialization_radix=16;" > hello.coe
echo "memory_initialization_vector=" >> hello.coe
$(HEXDUMP) -v -e '1/4 "%08x\n"' hello.bin >> hello.coe
echo ";" >> hello.coe
 
clean:
-$(RM) $(OBJECTS)
-$(RM) hello.elf hello.bin hello.coe
 
# Object file rules:
 
main.o: main.c ../platform.h ../potato.h
$(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $<
 
start.o: ../start.S ../platform.h
$(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $<
 
/benchmarks/platform.h
9,7 → 9,7
#define PLATFORM_H
 
// Clock frequency in Hz:
#define SYSTEM_CLK_FREQ 60000000
#define SYSTEM_CLK_FREQ 50000000
 
// Macro for using the addresses below in C code:
#define IO_ADDRESS(x) ((volatile void *) x)
/benchmarks/potato.h
52,6 → 52,13
#define potato_disable_interrupts() asm volatile("csrci %[status], 1 << %[ei_bit] | 1 << %[pei_bit]\n" \
:: [status] "i" (CSR_STATUS), [ei_bit] "i" (STATUS_EI), [pei_bit] "i" (STATUS_PEI))
 
#define potato_write_host(data) \
do { \
register uint32_t temp = data; \
asm volatile("csrw %[tohost], %[temp]\n" \
:: [tohost] "i" (CSR_TOHOST), [temp] "r" (temp)); \
} while(0);
 
#define potato_enable_irq(n) \
do { \
register uint32_t temp = 0; \
/.
. Property changes : Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /potato/branches/cache-playground:r23-30,34-44

powered by: WebSVN 2.1.0

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