complete refactor to InternalBus()
This commit is contained in:
parent
a7625ce0a4
commit
487b11f155
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in New Issue