complete refactor to InternalBus()

This commit is contained in:
Fischer Moseley 2024-01-07 22:35:15 -08:00
parent a7625ce0a4
commit 487b11f155
9 changed files with 77 additions and 164 deletions

View File

@ -87,16 +87,9 @@ class IOCore(Elaboratable):
)
def define_signals(self):
# Bus Ports
self.addr_i = Signal(16)
self.data_i = Signal(16)
self.rw_i = Signal()
self.valid_i = Signal()
self.addr_o = Signal(16)
self.data_o = Signal(16)
self.rw_o = Signal()
self.valid_o = Signal()
# Bus Input/Output
self.bus_i = Signal(InternalBus())
self.bus_o = Signal(InternalBus())
# Input Probes (and buffers)
if "inputs" in self.config:
@ -187,10 +180,7 @@ class IOCore(Elaboratable):
m = Module()
# Shuffle bus transactions along
m.d.sync += self.addr_o.eq(self.addr_i)
m.d.sync += self.data_o.eq(self.data_i)
m.d.sync += self.rw_o.eq(self.rw_i)
m.d.sync += self.valid_o.eq(self.valid_i)
m.d.sync += self.bus_o.eq(self.bus_i)
# Update buffers from probes
with m.If(self.strobe):
@ -209,17 +199,17 @@ class IOCore(Elaboratable):
m.d.sync += output_probe.eq(output_probe_buf)
# Handle register reads and writes
with m.If((self.addr_i >= self.base_addr)):
with m.If((self.addr_o <= self.max_addr)):
with m.If((self.bus_i.addr >= self.base_addr)):
with m.If((self.bus_o.addr <= self.max_addr)):
for entry in self.mmap.values():
for addr, signal in zip(entry["addrs"], entry["signals"]):
with m.If(self.rw_i):
with m.If(self.addr_i == addr):
m.d.sync += signal.eq(self.data_i)
with m.If(self.bus_i.rw):
with m.If(self.bus_i.addr == addr):
m.d.sync += signal.eq(self.bus_i.data)
with m.Else():
with m.If(self.addr_i == addr):
m.d.sync += self.data_o.eq(signal)
with m.If(self.bus_i.addr == addr):
m.d.sync += self.bus_o.data.eq(signal)
return m

View File

@ -36,17 +36,9 @@ class LogicAnalyzerCore(Elaboratable):
self.config = config
self.check_config(config)
# Bus Input
self.addr_i = Signal(16)
self.data_i = Signal(16)
self.rw_i = Signal(1)
self.valid_i = Signal(1)
# Bus Output
self.addr_o = Signal(16)
self.data_o = Signal(16)
self.rw_o = Signal(1)
self.valid_o = Signal(1)
# Bus Input/Output
self.bus_i = Signal(InternalBus())
self.bus_o = Signal(InternalBus())
self.probes = [
Signal(width, name=name) for name, width in self.config["probes"].items()
@ -177,26 +169,15 @@ class LogicAnalyzerCore(Elaboratable):
# Wire bus connections between internal modules
m.d.comb += [
# Bus Connections
fsm.addr_i.eq(self.addr_i),
fsm.data_i.eq(self.data_i),
fsm.rw_i.eq(self.rw_i),
fsm.valid_i.eq(self.valid_i),
trig_blk.addr_i.eq(fsm.addr_o),
trig_blk.data_i.eq(fsm.data_o),
trig_blk.rw_i.eq(fsm.rw_o),
trig_blk.valid_i.eq(fsm.valid_o),
sample_mem.addr_i.eq(trig_blk.addr_o),
sample_mem.data_i.eq(trig_blk.data_o),
sample_mem.rw_i.eq(trig_blk.rw_o),
sample_mem.valid_i.eq(trig_blk.valid_o),
self.addr_o.eq(sample_mem.addr_o),
self.data_o.eq(sample_mem.data_o),
self.rw_o.eq(sample_mem.rw_o),
self.valid_o.eq(sample_mem.valid_o),
fsm.bus_i.eq(self.bus_i),
trig_blk.bus_i.eq(self.fsm.bus_o),
sample_mem.bus_i.eq(trig_blk.bus_o),
self.bus_o.eq(sample_mem.bus_o),
# Non-bus Connections
fsm.trigger.eq(trig_blk.trig),
sample_mem.user_addr.eq(fsm.r.write_pointer),
sample_mem.user_we.eq(fsm.write_enable),
sample_mem.user_we.eq(fsm.write_enable)
]
return m

View File

@ -37,17 +37,9 @@ class LogicAnalyzerFSM(Elaboratable):
self.r = IOCore(register_config, base_addr, interface)
# Bus Input
self.addr_i = self.r.addr_i
self.data_i = self.r.data_i
self.rw_i = self.r.rw_i
self.valid_i = self.r.valid_i
# Bus Output
self.addr_o = self.r.addr_o
self.data_o = self.r.data_o
self.rw_o = self.r.rw_o
self.valid_o = self.r.valid_o
# Bus Input/Output
self.bus_i = self.r.bus_i
self.bus_o = self.r.bus_o
def get_max_addr(self):
return self.r.get_max_addr()

View File

@ -18,17 +18,9 @@ class LogicAnalyzerTriggerBlock(Elaboratable):
self.r = IOCore({"outputs": outputs}, base_addr, interface)
# Bus Input
self.addr_i = self.r.addr_i
self.data_i = self.r.data_i
self.rw_i = self.r.rw_i
self.valid_i = self.r.valid_i
# Bus Output
self.addr_o = self.r.addr_o
self.data_o = self.r.data_o
self.rw_o = self.r.rw_o
self.valid_o = self.r.valid_o
# Bus Input/Output
self.bus_i = self.r.bus_i
self.bus_o = self.r.bus_o
# Global trigger. High if any probe is triggered.
self.trig = Signal(1)

View File

@ -136,28 +136,16 @@ class Manta(Elaboratable):
core_instances = list(self.cores.values())
first_core = core_instances[0]
last_core = core_instances[-1]
m.d.comb += [
first_core.addr_i.eq(self.interface.addr_o),
first_core.data_i.eq(self.interface.data_o),
first_core.rw_i.eq(self.interface.rw_o),
first_core.valid_i.eq(self.interface.valid_o),
self.interface.addr_i.eq(last_core.addr_o),
self.interface.data_i.eq(last_core.data_o),
self.interface.rw_i.eq(last_core.rw_o),
self.interface.valid_i.eq(last_core.valid_o),
]
m.d.comb += first_core.bus_i.eq(self.interface.bus_o)
m.d.comb += self.interface.bus_i.eq(last_core.bus_o)
# Connect output of ith core to input of (i+1)th core
for i in range(len(core_instances) - 1):
ith_core = core_instances[i]
i_plus_oneth_core = core_instances[i + 1]
m.d.comb += [
i_plus_oneth_core.addr_i.eq(ith_core.addr_o),
i_plus_oneth_core.data_i.eq(ith_core.data_o),
i_plus_oneth_core.rw_i.eq(ith_core.rw_o),
i_plus_oneth_core.valid_i.eq(ith_core.valid_o),
]
m.d.comb += i_plus_oneth_core.bus_i.eq(ith_core.bus_o)
return m

View File

@ -47,23 +47,10 @@ class ReadOnlyMemoryCore(Elaboratable):
raise ValueError("Width of memory core must be positive. ")
def define_signals(self):
# Bus Input
self.addr_i = Signal(16)
self.data_i = Signal(16)
self.rw_i = Signal(1)
self.valid_i = Signal(1)
# Bus Pipelining
self.addr_pipe = [Signal(16) for _ in range(3)]
self.data_pipe = [Signal(16) for _ in range(3)]
self.rw_pipe = [Signal(1) for _ in range(3)]
self.valid_pipe = [Signal(1) for _ in range(3)]
# Bus Output
self.addr_o = Signal(16, reset=0)
self.data_o = Signal(16, reset=0)
self.rw_o = Signal(1, reset=0)
self.valid_o = Signal(1, reset=0)
# Bus Input/Pipelining/Output
self.bus_i = Signal(InternalBus())
self.bus_pipe = [Signal(InternalBus()) for _ in range(3)]
self.bus_o = Signal(InternalBus())
# User Port
self.user_addr = Signal(range(self.depth))
@ -71,22 +58,12 @@ class ReadOnlyMemoryCore(Elaboratable):
self.user_we = Signal(1)
def pipeline_bus(self, m):
# Pipelining
m.d.sync += self.addr_pipe[0].eq(self.addr_i)
m.d.sync += self.data_pipe[0].eq(self.data_i)
m.d.sync += self.rw_pipe[0].eq(self.rw_i)
m.d.sync += self.valid_pipe[0].eq(self.valid_i)
m.d.sync += self.bus_pipe[0].eq(self.bus_i)
for i in range(1, 3):
m.d.sync += self.addr_pipe[i].eq(self.addr_pipe[i - 1])
m.d.sync += self.data_pipe[i].eq(self.data_pipe[i - 1])
m.d.sync += self.rw_pipe[i].eq(self.rw_pipe[i - 1])
m.d.sync += self.valid_pipe[i].eq(self.valid_pipe[i - 1])
m.d.sync += self.bus_pipe[i].eq(self.bus_pipe[i-1])
m.d.sync += self.addr_o.eq(self.addr_pipe[2])
m.d.sync += self.data_o.eq(self.data_pipe[2])
m.d.sync += self.rw_o.eq(self.rw_pipe[2])
m.d.sync += self.valid_o.eq(self.valid_pipe[2])
m.d.sync += self.bus_o.eq(self.bus_pipe[2])
def define_mems(self):
# ok there's three cases:
@ -122,21 +99,21 @@ class ReadOnlyMemoryCore(Elaboratable):
# Throw BRAM operations into the front of the pipeline
with m.If(
(self.valid_i)
& (~self.rw_i)
& (self.addr_i >= start_addr)
& (self.addr_i <= stop_addr)
(self.bus_i.valid)
& (~self.bus_i.rw)
& (self.bus_i.addr >= start_addr)
& (self.bus_i.addr <= stop_addr)
):
m.d.sync += read_port.addr.eq(self.addr_i - start_addr)
m.d.sync += read_port.addr.eq(self.bus_i.addr - start_addr)
# Pull BRAM reads from the back of the pipeline
with m.If(
(self.valid_pipe[2])
& (~self.rw_pipe[2])
& (self.addr_pipe[2] >= start_addr)
& (self.addr_pipe[2] <= stop_addr)
(self.bus_pipe[2].valid)
& (~self.bus_pipe[2].rw)
& (self.bus_pipe[2].addr >= start_addr)
& (self.bus_pipe[2].addr <= stop_addr)
):
m.d.sync += self.data_o.eq(read_port.data)
m.d.sync += self.bus_o.data.eq(read_port.data)
def handle_write_ports(self, m):
# These are given to the user

View File

@ -225,15 +225,8 @@ class UARTInterface(Elaboratable):
self.rx = Signal()
self.tx = Signal()
self.addr_o = Signal(16)
self.data_o = Signal(16)
self.rw_o = Signal()
self.valid_o = Signal()
self.addr_i = Signal(16)
self.data_i = Signal(16)
self.rw_i = Signal()
self.valid_i = Signal()
self.bus_o = Signal(InternalBus())
self.bus_i = Signal(InternalBus())
def elaborate(self, platform):
# fancy submoduling and such goes in here
@ -249,14 +242,14 @@ class UARTInterface(Elaboratable):
uart_rx.rx.eq(self.rx),
bridge_rx.data_i.eq(uart_rx.data_o),
bridge_rx.valid_i.eq(uart_rx.valid_o),
self.data_o.eq(bridge_rx.data_o),
self.addr_o.eq(bridge_rx.addr_o),
self.rw_o.eq(bridge_rx.rw_o),
self.valid_o.eq(bridge_rx.valid_o),
self.bus_o.data.eq(bridge_rx.data_o),
self.bus_o.addr.eq(bridge_rx.addr_o),
self.bus_o.rw.eq(bridge_rx.rw_o),
self.bus_o.valid.eq(bridge_rx.valid_o),
# Internal Bus -> UART TX
bridge_tx.data_i.eq(self.data_i),
bridge_tx.rw_i.eq(self.rw_i),
bridge_tx.valid_i.eq(self.valid_i),
bridge_tx.data_i.eq(self.bus_i.data),
bridge_tx.rw_i.eq(self.bus_i.rw),
bridge_tx.valid_i.eq(self.bus_i.valid),
uart_tx.data_i.eq(bridge_tx.data_o),
uart_tx.start_i.eq(bridge_tx.start_o),
bridge_tx.done_i.eq(uart_tx.done_o),

View File

@ -83,20 +83,20 @@ def verify_register(module, addr, expected_data):
"""
# place read transaction on the bus
yield module.addr_i.eq(addr)
yield module.data_i.eq(0)
yield module.rw_i.eq(0)
yield module.valid_i.eq(1)
yield module.bus_i.addr.eq(addr)
yield module.bus_i.data.eq(0)
yield module.bus_i.rw.eq(0)
yield module.bus_i.valid.eq(1)
yield
yield module.addr_i.eq(0)
yield module.valid_i.eq(0)
yield module.bus_i.addr.eq(0)
yield module.bus_i.valid.eq(0)
# wait for output to be valid
while not (yield module.valid_o):
while not (yield module.bus_o.valid):
yield
# compare returned value with expected
data = yield (module.data_o)
data = yield (module.bus_o.data)
if data != expected_data:
raise ValueError(f"Read from {addr} yielded {data} instead of {expected_data}")
@ -107,12 +107,12 @@ def write_register(module, addr, data):
at `addr`.
"""
yield module.addr_i.eq(addr)
yield module.data_i.eq(data)
yield module.rw_i.eq(1)
yield module.valid_i.eq(1)
yield module.bus_i.addr.eq(addr)
yield module.bus_i.data.eq(data)
yield module.bus_i.rw.eq(1)
yield module.bus_i.valid.eq(1)
yield
yield module.valid_i.eq(0)
yield module.bus_i.valid.eq(0)
yield

View File

@ -16,19 +16,19 @@ la = LogicAnalyzerCore(config, base_addr=0, interface=None)
def print_data_at_addr(addr):
# place read transaction on the bus
yield la.addr_i.eq(addr)
yield la.data_i.eq(0)
yield la.rw_i.eq(0)
yield la.valid_i.eq(1)
yield la.bus_i.addr.eq(addr)
yield la.bus_i.data.eq(0)
yield la.bus_i.rw.eq(0)
yield la.bus_i.valid.eq(1)
yield
yield la.addr_i.eq(0)
yield la.valid_i.eq(0)
yield la.bus_i.addr.eq(0)
yield la.bus_i.valid.eq(0)
# wait for output to be valid
while not (yield la.valid_o):
while not (yield la.bus_o.valid):
yield
print(f"addr: {hex(addr)} data: {hex((yield la.data_o))}")
print(f"addr: {hex(addr)} data: {hex((yield la.bus_o.data))}")
def set_fsm_register(name, data):