-- The Potato Processor - A simple processor for FPGAs
|
-- The Potato Processor - A simple processor for FPGAs
|
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
|
-- (c) Kristian Klomsten Skordal 2014 - 2015 <kristian.skordal@wafflemail.net>
|
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
|
-- Report bugs and issues on <http://opencores.org/project,potato,bugtracker>
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
|
use work.pp_types.all;
|
use work.pp_types.all;
|
use work.pp_utilities.all;
|
use work.pp_utilities.all;
|
|
|
--! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches.
|
--! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches.
|
entity pp_wb_adapter is
|
entity pp_wb_adapter is
|
port(
|
port(
|
clk : in std_logic;
|
clk : in std_logic;
|
reset : in std_logic;
|
reset : in std_logic;
|
|
|
-- Processor data memory signals:
|
-- Processor data memory signals:
|
signal dmem_address : in std_logic_vector(31 downto 0);
|
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
|
signal dmem_data_in : in std_logic_vector(31 downto 0); -- Data in to the bus
|
signal dmem_data_out : out std_logic_vector(31 downto 0); -- Data out to the bus
|
signal dmem_data_out : out std_logic_vector(31 downto 0); -- Data out to the bus
|
signal dmem_data_size : in std_logic_vector( 1 downto 0);
|
signal dmem_data_size : in std_logic_vector( 1 downto 0);
|
signal dmem_read_req : in std_logic;
|
signal dmem_read_req : in std_logic;
|
signal dmem_read_ack : out std_logic;
|
signal dmem_read_ack : out std_logic;
|
signal dmem_write_req : in std_logic;
|
signal dmem_write_req : in std_logic;
|
signal dmem_write_ack : out std_logic;
|
signal dmem_write_ack : out std_logic;
|
|
|
-- Wishbone interface:
|
-- Wishbone interface:
|
wb_inputs : in wishbone_master_inputs;
|
wb_inputs : in wishbone_master_inputs;
|
wb_outputs : out wishbone_master_outputs
|
wb_outputs : out wishbone_master_outputs
|
);
|
);
|
end entity pp_wb_adapter;
|
end entity pp_wb_adapter;
|
|
|
architecture behaviour of pp_wb_adapter is
|
architecture behaviour of pp_wb_adapter is
|
|
|
type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK);
|
type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK);
|
signal state : states;
|
signal state : states;
|
|
|
signal dmem_r_ack : std_logic;
|
signal dmem_r_ack : std_logic;
|
|
|
function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
|
function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector)
|
return natural is
|
return natural is
|
begin
|
begin
|
case size is
|
case size is
|
when b"01" =>
|
when b"01" =>
|
case address(1 downto 0) is
|
case address(1 downto 0) is
|
when b"00" =>
|
when b"00" =>
|
return 0;
|
return 0;
|
when b"01" =>
|
when b"01" =>
|
return 8;
|
return 8;
|
when b"10" =>
|
when b"10" =>
|
return 16;
|
return 16;
|
when b"11" =>
|
when b"11" =>
|
return 24;
|
return 24;
|
when others =>
|
when others =>
|
return 0;
|
return 0;
|
end case;
|
end case;
|
when b"10" =>
|
when b"10" =>
|
if address(1) = '0' then
|
if address(1) = '0' then
|
return 0;
|
return 0;
|
else
|
else
|
return 16;
|
return 16;
|
end if;
|
end if;
|
when others =>
|
when others =>
|
return 0;
|
return 0;
|
end case;
|
end case;
|
end function get_data_shift;
|
end function get_data_shift;
|
|
|
begin
|
begin
|
|
|
dmem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_inputs.ack = '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;
|
dmem_read_ack <= dmem_r_ack;
|
|
|
wishbone: process(clk)
|
wishbone: process(clk)
|
begin
|
begin
|
if rising_edge(clk) then
|
if rising_edge(clk) then
|
if reset = '1' then
|
if reset = '1' then
|
state <= IDLE;
|
state <= IDLE;
|
wb_outputs.cyc <= '0';
|
wb_outputs.cyc <= '0';
|
wb_outputs.stb <= '0';
|
wb_outputs.stb <= '0';
|
dmem_r_ack <= '0';
|
dmem_r_ack <= '0';
|
else
|
else
|
case state is
|
case state is
|
when IDLE =>
|
when IDLE =>
|
dmem_r_ack <= '0';
|
dmem_r_ack <= '0';
|
|
|
-- Prioritize requests from the data memory:
|
-- Prioritize requests from the data memory:
|
if dmem_write_req = '1' then
|
if dmem_write_req = '1' then
|
wb_outputs.adr <= dmem_address;
|
wb_outputs.adr <= dmem_address;
|
wb_outputs.dat <= std_logic_vector(shift_left(unsigned(dmem_data_in),
|
wb_outputs.dat <= std_logic_vector(shift_left(unsigned(dmem_data_in),
|
get_data_shift(dmem_data_size, dmem_address)));
|
get_data_shift(dmem_data_size, dmem_address)));
|
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
|
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
|
wb_outputs.cyc <= '1';
|
wb_outputs.cyc <= '1';
|
wb_outputs.stb <= '1';
|
wb_outputs.stb <= '1';
|
wb_outputs.we <= '1';
|
wb_outputs.we <= '1';
|
state <= WRITE_WAIT_ACK;
|
state <= WRITE_WAIT_ACK;
|
elsif dmem_read_req = '1' then
|
elsif dmem_read_req = '1' then
|
wb_outputs.adr <= dmem_address;
|
wb_outputs.adr <= dmem_address;
|
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
|
wb_outputs.sel <= wb_get_data_sel(dmem_data_size, dmem_address);
|
wb_outputs.cyc <= '1';
|
wb_outputs.cyc <= '1';
|
wb_outputs.stb <= '1';
|
wb_outputs.stb <= '1';
|
wb_outputs.we <= '0';
|
wb_outputs.we <= '0';
|
state <= READ_WAIT_ACK;
|
state <= READ_WAIT_ACK;
|
end if;
|
end if;
|
when READ_WAIT_ACK =>
|
when READ_WAIT_ACK =>
|
if wb_inputs.ack = '1' then
|
if wb_inputs.ack = '1' then
|
dmem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat),
|
dmem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat),
|
get_data_shift(dmem_data_size, dmem_address)));
|
get_data_shift(dmem_data_size, dmem_address)));
|
wb_outputs.cyc <= '0';
|
wb_outputs.cyc <= '0';
|
wb_outputs.stb <= '0';
|
wb_outputs.stb <= '0';
|
dmem_r_ack <= '1';
|
dmem_r_ack <= '1';
|
state <= IDLE;
|
state <= IDLE;
|
end if;
|
end if;
|
when WRITE_WAIT_ACK =>
|
when WRITE_WAIT_ACK =>
|
if wb_inputs.ack = '1' then
|
if wb_inputs.ack = '1' then
|
wb_outputs.cyc <= '0';
|
wb_outputs.cyc <= '0';
|
wb_outputs.stb <= '0';
|
wb_outputs.stb <= '0';
|
wb_outputs.we <= '0';
|
wb_outputs.we <= '0';
|
state <= IDLE;
|
state <= IDLE;
|
end if;
|
end if;
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process wishbone;
|
end process wishbone;
|
|
|
end architecture behaviour;
|
end architecture behaviour;
|
|
|