fpga: Add NEORV32 as alternative CPU core
This commit is contained in:
parent
bb7b2a7a10
commit
ba299e537b
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
|||||||
[submodule "fpga/hdl/trashernet"]
|
[submodule "fpga/hdl/trashernet"]
|
||||||
path = fpga/hdl/trashernet
|
path = fpga/hdl/trashernet
|
||||||
url = https://git.notsyncing.net/fpga/trashernet.git
|
url = https://git.notsyncing.net/fpga/trashernet.git
|
||||||
|
[submodule "fpga/hdl/neorv32"]
|
||||||
|
path = fpga/hdl/neorv32
|
||||||
|
url = https://github.com/stnolting/neorv32.git
|
||||||
|
170
fpga/hdl/design/neorv32_top.vhd
Normal file
170
fpga/hdl/design/neorv32_top.vhd
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- TRASHERNET SoC - A Trashy Ethernet SoC for FPGAs --
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- Wrapper for NEORV32
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
-- Author : Markus Koch <markus@notsyncing.net>
|
||||||
|
-- Contributors : None
|
||||||
|
-- License : Mozilla Public License (MPL) Version 2
|
||||||
|
-- -------------------------------------------------------------------------- --
|
||||||
|
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
library generics;
|
||||||
|
use generics.wishbone_pkg.all;
|
||||||
|
|
||||||
|
library neorv32;
|
||||||
|
use neorv32.neorv32_package.all;
|
||||||
|
|
||||||
|
entity neorv32_top_vhdl is
|
||||||
|
port(
|
||||||
|
clk : in std_logic; -- CPU and bus clock
|
||||||
|
clr : in std_logic; -- Synchronous clear (CPU reset)
|
||||||
|
wbi_o : out wishbone_master_out; -- Instruction Wishbone bus (out)
|
||||||
|
wbi_i : in wishbone_master_in; -- Instruction Wishbone bus (in)
|
||||||
|
wbd_o : out wishbone_master_out; -- Data Wishbone bus (out)
|
||||||
|
wbd_i : in wishbone_master_in; -- Data Wishbone bus (in)
|
||||||
|
irq_timer : in std_logic -- System timer interrupt
|
||||||
|
);
|
||||||
|
end entity neorv32_top_vhdl;
|
||||||
|
|
||||||
|
architecture rtl of neorv32_top_vhdl is
|
||||||
|
signal ibus_req_o : bus_req_t;
|
||||||
|
signal ibus_rsp_i : bus_rsp_t;
|
||||||
|
signal dbus_req_o : bus_req_t;
|
||||||
|
signal dbus_rsp_i : bus_rsp_t;
|
||||||
|
|
||||||
|
signal wbi_rsp_latched : std_logic;
|
||||||
|
signal wbd_rsp_latched : std_logic;
|
||||||
|
|
||||||
|
signal ibus_req_mask : std_logic;
|
||||||
|
signal ibus_rsp_mask : std_logic;
|
||||||
|
|
||||||
|
signal dbus_req_mask : std_logic;
|
||||||
|
signal dbus_rsp_mask : std_logic;
|
||||||
|
begin
|
||||||
|
|
||||||
|
neorv32_cpu_inst : entity neorv32.neorv32_cpu
|
||||||
|
generic map(
|
||||||
|
HART_ID => x"00000000",
|
||||||
|
VENDOR_ID => x"00000000",
|
||||||
|
CPU_BOOT_ADDR => x"00000000",
|
||||||
|
CPU_DEBUG_PARK_ADDR => x"00000000",
|
||||||
|
CPU_DEBUG_EXC_ADDR => x"00000000",
|
||||||
|
CPU_EXTENSION_RISCV_A => false,
|
||||||
|
CPU_EXTENSION_RISCV_B => false,
|
||||||
|
CPU_EXTENSION_RISCV_C => false,
|
||||||
|
CPU_EXTENSION_RISCV_E => false,
|
||||||
|
CPU_EXTENSION_RISCV_M => false,
|
||||||
|
CPU_EXTENSION_RISCV_U => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zbkx => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zfinx => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zicntr => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zicond => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zihpm => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zknd => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zkne => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zknh => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zmmul => false,
|
||||||
|
CPU_EXTENSION_RISCV_Zxcfu => false,
|
||||||
|
CPU_EXTENSION_RISCV_Sdext => false,
|
||||||
|
CPU_EXTENSION_RISCV_Sdtrig => false,
|
||||||
|
CPU_EXTENSION_RISCV_Smpmp => false,
|
||||||
|
FAST_MUL_EN => false,
|
||||||
|
FAST_SHIFT_EN => false,
|
||||||
|
REGFILE_HW_RST => true,
|
||||||
|
PMP_NUM_REGIONS => 0,
|
||||||
|
PMP_MIN_GRANULARITY => 0,
|
||||||
|
PMP_TOR_MODE_EN => false,
|
||||||
|
PMP_NAP_MODE_EN => false,
|
||||||
|
HPM_NUM_CNTS => 0,
|
||||||
|
HPM_CNT_WIDTH => 0
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk_i => clk,
|
||||||
|
clk_aux_i => clk,
|
||||||
|
rstn_i => not clr,
|
||||||
|
sleep_o => open,
|
||||||
|
debug_o => open,
|
||||||
|
msi_i => '0',
|
||||||
|
mei_i => '0',
|
||||||
|
mti_i => irq_timer,
|
||||||
|
firq_i => x"0000",
|
||||||
|
dbi_i => '0',
|
||||||
|
ibus_req_o => ibus_req_o,
|
||||||
|
ibus_rsp_i => ibus_rsp_i,
|
||||||
|
dbus_req_o => dbus_req_o,
|
||||||
|
dbus_rsp_i => dbus_rsp_i
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Instruction bus
|
||||||
|
wbi_o.adr <= wishbone_address(ibus_req_o.addr);
|
||||||
|
wbi_o.dat <= wishbone_data(ibus_req_o.data);
|
||||||
|
wbi_o.sel <= wishbone_byte_select(ibus_req_o.ben);
|
||||||
|
wbi_o.we <= ibus_req_o.rw; -- TODO: We should also buffer this like we do stb, but in the current version the CPU holds it for us, so :shrug:
|
||||||
|
wbi_o.cyc <= wbi_o.stb;
|
||||||
|
ibus_rsp_i.data <= std_ulogic_vector(wbi_i.dat);
|
||||||
|
|
||||||
|
wbi_o.stb <= ibus_req_mask;
|
||||||
|
ibus_rsp_i.ack <= wbi_i.ack and not (ibus_rsp_mask);
|
||||||
|
ibus_rsp_i.err <= (wbi_i.err or wbi_i.rty) and not (ibus_rsp_mask);
|
||||||
|
|
||||||
|
wb2bus_i : process(clk) is
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if ibus_req_o.stb then
|
||||||
|
ibus_req_mask <= '1';
|
||||||
|
assert ibus_req_o.rvso = '0' report "Error: IBus RVSO not implemented but requested!" severity FAILURE;
|
||||||
|
end if;
|
||||||
|
if (wbi_i.ack or wbi_i.err or wbi_i.rty) and not ibus_req_o.stb then
|
||||||
|
ibus_req_mask <= '0';
|
||||||
|
ibus_rsp_mask <= '1';
|
||||||
|
|
||||||
|
else
|
||||||
|
ibus_rsp_mask <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if clr then
|
||||||
|
ibus_req_mask <= '0';
|
||||||
|
ibus_rsp_mask <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process wb2bus_i;
|
||||||
|
|
||||||
|
-- Data bus
|
||||||
|
wbd_o.adr <= wishbone_address(dbus_req_o.addr);
|
||||||
|
wbd_o.dat <= wishbone_data(dbus_req_o.data);
|
||||||
|
wbd_o.sel <= wishbone_byte_select(dbus_req_o.ben);
|
||||||
|
wbd_o.we <= dbus_req_o.rw;
|
||||||
|
wbd_o.cyc <= wbd_o.stb;
|
||||||
|
dbus_rsp_i.data <= std_ulogic_vector(wbd_i.dat);
|
||||||
|
|
||||||
|
wbd_o.stb <= dbus_req_mask;
|
||||||
|
dbus_rsp_i.ack <= wbd_i.ack and not (dbus_rsp_mask);
|
||||||
|
dbus_rsp_i.err <= (wbd_i.err or wbd_i.rty) and not (dbus_rsp_mask);
|
||||||
|
|
||||||
|
wb2bus_d : process(clk) is
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if dbus_req_o.stb then
|
||||||
|
dbus_req_mask <= '1';
|
||||||
|
assert dbus_req_o.rvso = '0' report "Error: dbus RVSO not implemented but requested!" severity FAILURE;
|
||||||
|
end if;
|
||||||
|
if (wbd_i.ack or wbd_i.err or wbd_i.rty) and not dbus_req_o.stb then
|
||||||
|
dbus_req_mask <= '0';
|
||||||
|
dbus_rsp_mask <= '1';
|
||||||
|
|
||||||
|
else
|
||||||
|
dbus_rsp_mask <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
if clr then
|
||||||
|
dbus_req_mask <= '0';
|
||||||
|
dbus_rsp_mask <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process wb2bus_d;
|
||||||
|
|
||||||
|
end architecture rtl;
|
@ -23,7 +23,8 @@ entity top is
|
|||||||
F_IN : integer := 50000000;
|
F_IN : integer := 50000000;
|
||||||
F_CLK : integer := 25000000;
|
F_CLK : integer := 25000000;
|
||||||
F_CLK_PHY : integer := 50000000;
|
F_CLK_PHY : integer := 50000000;
|
||||||
UART_BAUD : integer := 250000
|
UART_BAUD : integer := 250000;
|
||||||
|
CPU : string := "serv"
|
||||||
);
|
);
|
||||||
port(
|
port(
|
||||||
clk_in : in std_logic; -- System clock
|
clk_in : in std_logic; -- System clock
|
||||||
@ -201,6 +202,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
end process por;
|
end process por;
|
||||||
|
|
||||||
|
cpu_sel : if CPU = "serv" generate
|
||||||
serv_top_vhdl_inst : entity work.serv_top_vhdl
|
serv_top_vhdl_inst : entity work.serv_top_vhdl
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
@ -212,6 +214,27 @@ begin
|
|||||||
irq_timer => irq_timer
|
irq_timer => irq_timer
|
||||||
);
|
);
|
||||||
|
|
||||||
|
elsif CPU = "neorv32" generate
|
||||||
|
neorv32_top_vhdl_inst : entity work.neorv32_top_vhdl
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
clr => clr,
|
||||||
|
wbi_o => wbi_o,
|
||||||
|
wbi_i => wbi_i,
|
||||||
|
wbd_o => wbd_o,
|
||||||
|
wbd_i => wbd_i,
|
||||||
|
irq_timer => irq_timer
|
||||||
|
);
|
||||||
|
|
||||||
|
else generate
|
||||||
|
cpu_sel_err_p : process is
|
||||||
|
begin
|
||||||
|
report "ERROR: Selected invalid CPU" severity FAILURE;
|
||||||
|
wait;
|
||||||
|
end process cpu_sel_err_p;
|
||||||
|
|
||||||
|
end generate cpu_sel;
|
||||||
|
|
||||||
servant_rom_vhdl_inst : entity work.servant_ram_vhdl
|
servant_rom_vhdl_inst : entity work.servant_ram_vhdl
|
||||||
generic map(
|
generic map(
|
||||||
memfile => "../sw/bootrom/bootrom.vhex",
|
memfile => "../sw/bootrom/bootrom.vhex",
|
||||||
|
1
fpga/hdl/neorv32
Submodule
1
fpga/hdl/neorv32
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit fd79163eb2d49cc57a9d91061a9fd4f6cdc94644
|
@ -14,6 +14,7 @@ libraries = {
|
|||||||
"device_models",
|
"device_models",
|
||||||
"generics",
|
"generics",
|
||||||
"serv",
|
"serv",
|
||||||
|
"neorv32",
|
||||||
"trashernet"
|
"trashernet"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,6 +39,9 @@ for base_path in libraries:
|
|||||||
if library_name == "trashernet": # Special case: Trashernet submodule
|
if library_name == "trashernet": # Special case: Trashernet submodule
|
||||||
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
||||||
libs[library_name].add_source_files(path)
|
libs[library_name].add_source_files(path)
|
||||||
|
elif library_name == "neorv32": # Special case: NEORV32 submodule
|
||||||
|
path = os.path.join(base_path, "hdl", library_name, "rtl", "core", "*.vhd")
|
||||||
|
libs[library_name].add_source_files(path)
|
||||||
elif library_name == "serv": # Special case: SERV submodule
|
elif library_name == "serv": # Special case: SERV submodule
|
||||||
print("Skipping SERV. It's Verilog.")
|
print("Skipping SERV. It's Verilog.")
|
||||||
else: # Normal lib
|
else: # Normal lib
|
||||||
|
@ -13,6 +13,7 @@ libraries = {
|
|||||||
"device_models",
|
"device_models",
|
||||||
"generics",
|
"generics",
|
||||||
"serv",
|
"serv",
|
||||||
|
"neorv32",
|
||||||
"trashernet"
|
"trashernet"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,6 +38,9 @@ for base_path in libraries:
|
|||||||
if library_name == "trashernet": # Special case: Trashernet submodule
|
if library_name == "trashernet": # Special case: Trashernet submodule
|
||||||
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
path = os.path.join(base_path, "hdl", library_name, library_name, "*.vhd")
|
||||||
libs[library_name].add_source_files(path)
|
libs[library_name].add_source_files(path)
|
||||||
|
elif library_name == "neorv32": # Special case: NEORV32 submodule
|
||||||
|
path = os.path.join(base_path, "hdl", library_name, "rtl", "core", "*.vhd")
|
||||||
|
libs[library_name].add_source_files(path)
|
||||||
elif library_name == "serv": # Special case: SERV submodule
|
elif library_name == "serv": # Special case: SERV submodule
|
||||||
print("Skipping SERV. It's Verilog.")
|
print("Skipping SERV. It's Verilog.")
|
||||||
else: # Normal lib
|
else: # Normal lib
|
||||||
|
Loading…
Reference in New Issue
Block a user