Compare commits

...

6 Commits

Author SHA1 Message Date
925a605af9 hw: revision A gerbers 2023-03-05 11:53:18 -07:00
fdf3ddeb4a hw: added some notes on RevA bringup issues 2023-03-05 11:52:41 -07:00
54ac22429e add jtagdap submodule for now
(need to update it to use amaranth to do debug in minerva)
2023-03-05 11:52:16 -07:00
6ef410786e fw: moving forward a bit 2023-03-05 11:48:08 -07:00
cc763a3e9b requirements.tx: amaranth-community-unofficial -> amaranth-farm 2023-03-05 11:47:09 -07:00
8d00e15835 gateware: fix dumb mistakes
Bus widths should now all be correct. (addresses and sizes in amaranth
take into account the granularity selection, so granularity acts like
two extra bits on the bus address line)

Also don't ignore a warning about undriven resets. Turns out that can
gate *everything* off in your design.
2023-03-05 11:43:59 -07:00
14 changed files with 74 additions and 37 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "gateware/amaranth-boards"]
path = gateware/amaranth-boards
url = https://github.com/amaranth-lang/amaranth-boards
[submodule "gateware/jtagtap"]
path = gateware/jtagtap
url = git@github.com:davidlenfesty/jtagtap

View File

@ -11,4 +11,4 @@ fn main() {
println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rerun-if-changed=build.rs");
}
}

4
firmware/build_and_strip.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/sh
cargo build --release
riscv64-unknown-elf-objcopy -S -O binary target/riscv32i-unknown-none-elf/release/fw fw.bin

17
firmware/openocd.cfg Normal file
View File

@ -0,0 +1,17 @@
set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x21000000
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME
$_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1
#flash bank spi0 fespi 0x40000000 0 0 0 $_TARGETNAME.0 0x20004000
init
if {[ info exists pulse_srst]} {
ftdi_set_signal nSRST 0
ftdi_set_signal nSRST z
}
halt
#flash protect 0 64 last off
echo "Ready for Remote Connections"

View File

@ -1,7 +1,6 @@
//! Quick and hacky ethernet thing to test
const LITEETH_BASE: u32 = 0x0050_0000;
const LITEETH_BASE: u32 = 0x0200_0000;
const ETHMAC_SRAM_WRITER_EV_PENDING: u32 = LITEETH_BASE + 0x810;
const ETHMAC_SRAM_WRITER_EV_ENABLE: u32 = LITEETH_BASE + 0x814;
@ -9,12 +8,16 @@ const ETHMAC_SRAM_READER_EV_PENDING: u32 = LITEETH_BASE + 0x830;
const ETHMAC_SRAM_READER_EV_ENABLE: u32 = LITEETH_BASE + 0x834;
fn write_u32_reg(addr: u32, value: u32) {
unsafe { *(addr as *mut u32) = value; }
use core::ptr::write;
unsafe {
write(addr as *mut u32, value);
}
}
fn read_u32_reg(addr: u32) -> u32 {
use core::ptr::read;
unsafe {
return *(addr as *mut u32);
return read(addr as *mut u32);
}
}
@ -35,7 +38,4 @@ pub fn init() {
write_u32_reg(ETHMAC_SRAM_READER_EV_ENABLE, 0);
}
pub fn tranmsit() {
}
pub fn tranmsit() {}

View File

@ -21,13 +21,12 @@ fn main() -> ! {
500_000
};
// do something here
loop {
unsafe {
write(0x01002000 as *mut u32, 0);
write_led(0);
busy_wait(blink_period);
write(0x01002000 as *mut u32, 1);
write_led(1);
busy_wait(blink_period);
}
}
@ -35,10 +34,14 @@ fn main() -> ! {
fn busy_wait(num_nops: u32) {
for _ in 0..num_nops {
unsafe { asm!("nop"); }
unsafe {
asm!("nop");
}
}
}
fn write_led(val: u32) {
unsafe { write(0x01002000 as *mut u32, val); }
}
unsafe {
write(0x01002000 as *mut u32, val);
}
}

View File

@ -12,10 +12,10 @@ class LiteEth(Elaboratable, Interface):
def __init__(self, eth_interface):
self.eth_interface = eth_interface
# Addr width is 13 bits to accomodate 0x1FFF, which is well p
Interface.__init__(self, addr_width=13, data_width=32, granularity=8, features=["cti", "bte", "err"])
# Addr width is 13 bits to accomodate 0x1FFF, which is well past what we care about
Interface.__init__(self, addr_width=15, data_width=32, granularity=8, features=["cti", "bte", "err"])
# TODO I need to understand the semantics here better
memory_map = MemoryMap(addr_width=15, data_width=8)
memory_map = MemoryMap(addr_width=17, data_width=8)
#memory_map.add_resource(self, name="LiteETH", size=0x2000)
self.memory_map = memory_map
@ -25,7 +25,8 @@ class LiteEth(Elaboratable, Interface):
# TODO this really shouldn't technically happen here, because we can elaborate one module multiple times,
# but since I use it once it isn't actually a problem.
def elaborate(self, platform):
platform.add_file("liteeth_core.v", open("liteeth/gateware/liteeth_core.v", 'r').read())
if platform is not None:
platform.add_file("liteeth_core.v", open("liteeth/gateware/liteeth_core.v", 'r').read())
m = Module()
@ -34,6 +35,7 @@ class LiteEth(Elaboratable, Interface):
core = Instance(
"liteeth_core",
i_sys_clock=ClockSignal(),
i_sys_reset=Const(0),
# RGMII signals
o_rgmii_eth_clocks_tx=self.eth_interface.tx_clk,
@ -54,6 +56,7 @@ class LiteEth(Elaboratable, Interface):
o_wishbone_dat_r=self.dat_r,
i_wishbone_sel=self.sel,
i_wishbone_cyc=self.cyc,
i_wishbone_stb=self.stb,
o_wishbone_ack=self.ack,
i_wishbone_we=self.we,
i_wishbone_cti=self.cti,

1
gateware/jtagtap Submodule

@ -0,0 +1 @@
Subproject commit 851b71bb8bab68b082405170f0e3f3464609a297

View File

@ -5,8 +5,8 @@ from amaranth_soc.memory import *
class LEDPeripheral(Elaboratable, Interface):
def __init__(self, led_signal):
Interface.__init__(self, addr_width=1, data_width=32)
memory_map = MemoryMap(addr_width=1, data_width=32)
Interface.__init__(self, addr_width=1, data_width=32, granularity=8)
memory_map = MemoryMap(addr_width=3, data_width=8)
#memory_map.add_resource("my_led", name="led_peripheral", size=1)
self.memory_map = memory_map

View File

@ -41,9 +41,9 @@ def load_firmware_for_mem() -> List[int]:
class Core(Elaboratable):
def __init__(self, clk25, led_signal, eth_interface):
self.count = Signal(64)
self.cpu = Minerva(reset_address=0x01000000)
self.arbiter = Arbiter(addr_width=32, data_width=32)
self.decoder = Decoder(addr_width=32, data_width=32, features=["err"])
self.cpu = Minerva(reset_address=0x01000000, with_debug=False)
self.arbiter = Arbiter(addr_width=30, data_width=32, granularity=8)
self.decoder = Decoder(addr_width=30, data_width=32, granularity=8, features=["err"])
self.clk25 = clk25
self.led_signal = led_signal
self.eth_interface = eth_interface
@ -55,7 +55,8 @@ class Core(Elaboratable):
m.submodules.decoder = self.decoder
# Create main and sampling clock, using PLL and 25MHz input clock
platform.add_file("pll.v", open("pll.v", "r").read())
if platform is not None:
platform.add_file("pll.v", open("pll.v", "r").read())
sys_clk = Signal()
sample_clk = Signal()
pll = Instance(
@ -79,16 +80,15 @@ class Core(Elaboratable):
# Connect ibus and dbus together for simplicity for now
minerva_wb_features = ["cti", "bte", "err"]
self.ibus = Interface(addr_width=32, data_width=32, features=minerva_wb_features)
self.ibus = Interface(addr_width=30, data_width=32, granularity=8, features=minerva_wb_features)
# Note this is a set of statements! without assigning to the comb domain, this will do nothing
m.d.comb += self.cpu.ibus.connect(self.ibus)
self.arbiter.add(self.ibus)
self.dbus = Interface(addr_width=32, data_width=32, features=minerva_wb_features)
self.dbus = Interface(addr_width=30, data_width=32, granularity=8, features=minerva_wb_features)
m.d.comb += self.cpu.dbus.connect(self.dbus) # Don't use .eq, use .connect, which will appropriately assign signals
# using .eq() gave me Multiple Driven errors
self.arbiter.add(self.dbus)
# TODO do something with interrupts
# These are interrupts headed into the CPU
self.interrupts = Signal(32)
@ -111,7 +111,7 @@ class Core(Elaboratable):
m.submodules.rom = self.rom
# Problem: not sure to handle how we do byte vs word addressing properly
# So doing this shift is a bit of a hacky way to impl anything
start, _stop, _step = self.decoder.add(self.rom, addr=(0x01000000 >> 2))
start, _stop, _step = self.decoder.add(self.rom, addr=0x01000000)
print(f"ROM added at 0x{start:08x}")
self.ram = RAM()
@ -129,7 +129,7 @@ class Core(Elaboratable):
# Ethernet
self.eth = LiteEth(self.eth_interface)
m.submodules.eth = self.eth
start, _stop, _step = self.decoder.add(self.eth, addr=0x00500000)
start, _stop, _step = self.decoder.add(self.eth, addr=0x02000000)
print(f"LiteETH added at 0x{start:08x}")
# Connect arbiter to decoder
@ -167,12 +167,12 @@ def run_sim():
sim = Simulator(dut)
def proc():
for i in range(10000):
for i in range(1000):
yield Tick()
sim.add_clock(1e-6)
sim.add_sync_process(proc)
with sim.write_vcd('test.vcd', gtkw_file='test.gtkw'):
with sim.write_vcd('sim.vcd', gtkw_file='sim.gtkw'):
sim.reset()
sim.run()
@ -184,6 +184,7 @@ if __name__ == "__main__":
# TODO maybe allow an optional arg to specify an individual test to run?
args.add_argument("--test", action="store_true", help="Run RTL test suite and report results.")
args.add_argument("--save-vcd", action="store_true", help="Save VCD waveforms from test(s).")
args.add_argument("--sim", action="store_true", help="Run overall simulation")
args = args.parse_args()
if args.build:
@ -203,3 +204,6 @@ if __name__ == "__main__":
for mod in test_modules:
unittest.main(module=mod, argv=[sys.argv[0]])
if args.sim:
run_sim()

View File

@ -2,6 +2,8 @@ from amaranth import *
from amaranth_soc.wishbone import *
from amaranth_soc.memory import *
# TODO impl select
# We sub-class wishbone.Interface here because it needs to be a bus object to be added as a window to Wishbone stuff
class ROM(Elaboratable, Interface):
@ -11,11 +13,11 @@ class ROM(Elaboratable, Interface):
self.r = self.data.read_port()
# Need to init Interface
Interface.__init__(self, addr_width=10, data_width=32)
Interface.__init__(self, addr_width=10, data_width=32, granularity=8)
# This is effectively a "window", and it has a certain set of resources
# 12 = log2(4096)
memory_map = MemoryMap(addr_width=10, data_width=32)
memory_map = MemoryMap(addr_width=12, data_width=8)
# TODO need to unify how I deal with size
# In this case, one resource, which is out memory
memory_map.add_resource(self.data, name="rom_data", size=(4096 >> 2))
@ -57,11 +59,11 @@ class RAM(Elaboratable, Interface):
self.w = self.data.write_port()
# Need to init Interface
Interface.__init__(self, addr_width=10, data_width=32)
Interface.__init__(self, addr_width=10, data_width=32, granularity=8)
# This is effectively a "window", and it has a certain set of resources
# 12 = log2(4096)
memory_map = MemoryMap(addr_width=10, data_width=32)
memory_map = MemoryMap(addr_width=12, data_width=8)
# TODO need to unify how I deal with size
# In this case, one resource, which is out memory
memory_map.add_resource(self.data, name="ram_data", size=(4096 >> 2))

Binary file not shown.

View File

@ -1,6 +1,6 @@
git+https://github.com/amaranth-lang/amaranth
git+https://github.com/amaranth-lang/amaranth-soc
git+https://github.com/minerva-cpu/minerva
git+https://github.com/amaranth-community-unofficial/amlib
git+https://github.com/amaranth-farm/amlib
sphinx
sphinxcontrib-wavedrom