complete refactor to InternalBus()
This commit is contained in:
parent
a7625ce0a4
commit
487b11f155
|
|
@ -87,16 +87,9 @@ class IOCore(Elaboratable):
|
||||||
)
|
)
|
||||||
|
|
||||||
def define_signals(self):
|
def define_signals(self):
|
||||||
# Bus Ports
|
# Bus Input/Output
|
||||||
self.addr_i = Signal(16)
|
self.bus_i = Signal(InternalBus())
|
||||||
self.data_i = Signal(16)
|
self.bus_o = Signal(InternalBus())
|
||||||
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()
|
|
||||||
|
|
||||||
# Input Probes (and buffers)
|
# Input Probes (and buffers)
|
||||||
if "inputs" in self.config:
|
if "inputs" in self.config:
|
||||||
|
|
@ -187,10 +180,7 @@ class IOCore(Elaboratable):
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
||||||
# Shuffle bus transactions along
|
# Shuffle bus transactions along
|
||||||
m.d.sync += self.addr_o.eq(self.addr_i)
|
m.d.sync += self.bus_o.eq(self.bus_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)
|
|
||||||
|
|
||||||
# Update buffers from probes
|
# Update buffers from probes
|
||||||
with m.If(self.strobe):
|
with m.If(self.strobe):
|
||||||
|
|
@ -209,17 +199,17 @@ class IOCore(Elaboratable):
|
||||||
m.d.sync += output_probe.eq(output_probe_buf)
|
m.d.sync += output_probe.eq(output_probe_buf)
|
||||||
|
|
||||||
# Handle register reads and writes
|
# Handle register reads and writes
|
||||||
with m.If((self.addr_i >= self.base_addr)):
|
with m.If((self.bus_i.addr >= self.base_addr)):
|
||||||
with m.If((self.addr_o <= self.max_addr)):
|
with m.If((self.bus_o.addr <= self.max_addr)):
|
||||||
for entry in self.mmap.values():
|
for entry in self.mmap.values():
|
||||||
for addr, signal in zip(entry["addrs"], entry["signals"]):
|
for addr, signal in zip(entry["addrs"], entry["signals"]):
|
||||||
with m.If(self.rw_i):
|
with m.If(self.bus_i.rw):
|
||||||
with m.If(self.addr_i == addr):
|
with m.If(self.bus_i.addr == addr):
|
||||||
m.d.sync += signal.eq(self.data_i)
|
m.d.sync += signal.eq(self.bus_i.data)
|
||||||
|
|
||||||
with m.Else():
|
with m.Else():
|
||||||
with m.If(self.addr_i == addr):
|
with m.If(self.bus_i.addr == addr):
|
||||||
m.d.sync += self.data_o.eq(signal)
|
m.d.sync += self.bus_o.data.eq(signal)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,17 +36,9 @@ class LogicAnalyzerCore(Elaboratable):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.check_config(config)
|
self.check_config(config)
|
||||||
|
|
||||||
# Bus Input
|
# Bus Input/Output
|
||||||
self.addr_i = Signal(16)
|
self.bus_i = Signal(InternalBus())
|
||||||
self.data_i = Signal(16)
|
self.bus_o = Signal(InternalBus())
|
||||||
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)
|
|
||||||
|
|
||||||
self.probes = [
|
self.probes = [
|
||||||
Signal(width, name=name) for name, width in self.config["probes"].items()
|
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
|
# Wire bus connections between internal modules
|
||||||
m.d.comb += [
|
m.d.comb += [
|
||||||
# Bus Connections
|
# Bus Connections
|
||||||
fsm.addr_i.eq(self.addr_i),
|
fsm.bus_i.eq(self.bus_i),
|
||||||
fsm.data_i.eq(self.data_i),
|
trig_blk.bus_i.eq(self.fsm.bus_o),
|
||||||
fsm.rw_i.eq(self.rw_i),
|
sample_mem.bus_i.eq(trig_blk.bus_o),
|
||||||
fsm.valid_i.eq(self.valid_i),
|
self.bus_o.eq(sample_mem.bus_o),
|
||||||
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),
|
|
||||||
# Non-bus Connections
|
# Non-bus Connections
|
||||||
fsm.trigger.eq(trig_blk.trig),
|
fsm.trigger.eq(trig_blk.trig),
|
||||||
sample_mem.user_addr.eq(fsm.r.write_pointer),
|
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
|
return m
|
||||||
|
|
|
||||||
|
|
@ -37,17 +37,9 @@ class LogicAnalyzerFSM(Elaboratable):
|
||||||
|
|
||||||
self.r = IOCore(register_config, base_addr, interface)
|
self.r = IOCore(register_config, base_addr, interface)
|
||||||
|
|
||||||
# Bus Input
|
# Bus Input/Output
|
||||||
self.addr_i = self.r.addr_i
|
self.bus_i = self.r.bus_i
|
||||||
self.data_i = self.r.data_i
|
self.bus_o = self.r.bus_o
|
||||||
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
|
|
||||||
|
|
||||||
def get_max_addr(self):
|
def get_max_addr(self):
|
||||||
return self.r.get_max_addr()
|
return self.r.get_max_addr()
|
||||||
|
|
|
||||||
|
|
@ -18,17 +18,9 @@ class LogicAnalyzerTriggerBlock(Elaboratable):
|
||||||
|
|
||||||
self.r = IOCore({"outputs": outputs}, base_addr, interface)
|
self.r = IOCore({"outputs": outputs}, base_addr, interface)
|
||||||
|
|
||||||
# Bus Input
|
# Bus Input/Output
|
||||||
self.addr_i = self.r.addr_i
|
self.bus_i = self.r.bus_i
|
||||||
self.data_i = self.r.data_i
|
self.bus_o = self.r.bus_o
|
||||||
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
|
|
||||||
|
|
||||||
# Global trigger. High if any probe is triggered.
|
# Global trigger. High if any probe is triggered.
|
||||||
self.trig = Signal(1)
|
self.trig = Signal(1)
|
||||||
|
|
|
||||||
|
|
@ -136,28 +136,16 @@ class Manta(Elaboratable):
|
||||||
core_instances = list(self.cores.values())
|
core_instances = list(self.cores.values())
|
||||||
first_core = core_instances[0]
|
first_core = core_instances[0]
|
||||||
last_core = core_instances[-1]
|
last_core = core_instances[-1]
|
||||||
m.d.comb += [
|
|
||||||
first_core.addr_i.eq(self.interface.addr_o),
|
m.d.comb += first_core.bus_i.eq(self.interface.bus_o)
|
||||||
first_core.data_i.eq(self.interface.data_o),
|
m.d.comb += self.interface.bus_i.eq(last_core.bus_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),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Connect output of ith core to input of (i+1)th core
|
# Connect output of ith core to input of (i+1)th core
|
||||||
for i in range(len(core_instances) - 1):
|
for i in range(len(core_instances) - 1):
|
||||||
ith_core = core_instances[i]
|
ith_core = core_instances[i]
|
||||||
i_plus_oneth_core = core_instances[i + 1]
|
i_plus_oneth_core = core_instances[i + 1]
|
||||||
|
|
||||||
m.d.comb += [
|
m.d.comb += i_plus_oneth_core.bus_i.eq(ith_core.bus_o)
|
||||||
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),
|
|
||||||
]
|
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,23 +47,10 @@ class ReadOnlyMemoryCore(Elaboratable):
|
||||||
raise ValueError("Width of memory core must be positive. ")
|
raise ValueError("Width of memory core must be positive. ")
|
||||||
|
|
||||||
def define_signals(self):
|
def define_signals(self):
|
||||||
# Bus Input
|
# Bus Input/Pipelining/Output
|
||||||
self.addr_i = Signal(16)
|
self.bus_i = Signal(InternalBus())
|
||||||
self.data_i = Signal(16)
|
self.bus_pipe = [Signal(InternalBus()) for _ in range(3)]
|
||||||
self.rw_i = Signal(1)
|
self.bus_o = Signal(InternalBus())
|
||||||
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)
|
|
||||||
|
|
||||||
# User Port
|
# User Port
|
||||||
self.user_addr = Signal(range(self.depth))
|
self.user_addr = Signal(range(self.depth))
|
||||||
|
|
@ -71,22 +58,12 @@ class ReadOnlyMemoryCore(Elaboratable):
|
||||||
self.user_we = Signal(1)
|
self.user_we = Signal(1)
|
||||||
|
|
||||||
def pipeline_bus(self, m):
|
def pipeline_bus(self, m):
|
||||||
# Pipelining
|
m.d.sync += self.bus_pipe[0].eq(self.bus_i)
|
||||||
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)
|
|
||||||
|
|
||||||
for i in range(1, 3):
|
for i in range(1, 3):
|
||||||
m.d.sync += self.addr_pipe[i].eq(self.addr_pipe[i - 1])
|
m.d.sync += self.bus_pipe[i].eq(self.bus_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.addr_o.eq(self.addr_pipe[2])
|
m.d.sync += self.bus_o.eq(self.bus_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])
|
|
||||||
|
|
||||||
def define_mems(self):
|
def define_mems(self):
|
||||||
# ok there's three cases:
|
# ok there's three cases:
|
||||||
|
|
@ -122,21 +99,21 @@ class ReadOnlyMemoryCore(Elaboratable):
|
||||||
|
|
||||||
# Throw BRAM operations into the front of the pipeline
|
# Throw BRAM operations into the front of the pipeline
|
||||||
with m.If(
|
with m.If(
|
||||||
(self.valid_i)
|
(self.bus_i.valid)
|
||||||
& (~self.rw_i)
|
& (~self.bus_i.rw)
|
||||||
& (self.addr_i >= start_addr)
|
& (self.bus_i.addr >= start_addr)
|
||||||
& (self.addr_i <= stop_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
|
# Pull BRAM reads from the back of the pipeline
|
||||||
with m.If(
|
with m.If(
|
||||||
(self.valid_pipe[2])
|
(self.bus_pipe[2].valid)
|
||||||
& (~self.rw_pipe[2])
|
& (~self.bus_pipe[2].rw)
|
||||||
& (self.addr_pipe[2] >= start_addr)
|
& (self.bus_pipe[2].addr >= start_addr)
|
||||||
& (self.addr_pipe[2] <= stop_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):
|
def handle_write_ports(self, m):
|
||||||
# These are given to the user
|
# These are given to the user
|
||||||
|
|
|
||||||
|
|
@ -225,15 +225,8 @@ class UARTInterface(Elaboratable):
|
||||||
self.rx = Signal()
|
self.rx = Signal()
|
||||||
self.tx = Signal()
|
self.tx = Signal()
|
||||||
|
|
||||||
self.addr_o = Signal(16)
|
self.bus_o = Signal(InternalBus())
|
||||||
self.data_o = Signal(16)
|
self.bus_i = Signal(InternalBus())
|
||||||
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()
|
|
||||||
|
|
||||||
def elaborate(self, platform):
|
def elaborate(self, platform):
|
||||||
# fancy submoduling and such goes in here
|
# fancy submoduling and such goes in here
|
||||||
|
|
@ -249,14 +242,14 @@ class UARTInterface(Elaboratable):
|
||||||
uart_rx.rx.eq(self.rx),
|
uart_rx.rx.eq(self.rx),
|
||||||
bridge_rx.data_i.eq(uart_rx.data_o),
|
bridge_rx.data_i.eq(uart_rx.data_o),
|
||||||
bridge_rx.valid_i.eq(uart_rx.valid_o),
|
bridge_rx.valid_i.eq(uart_rx.valid_o),
|
||||||
self.data_o.eq(bridge_rx.data_o),
|
self.bus_o.data.eq(bridge_rx.data_o),
|
||||||
self.addr_o.eq(bridge_rx.addr_o),
|
self.bus_o.addr.eq(bridge_rx.addr_o),
|
||||||
self.rw_o.eq(bridge_rx.rw_o),
|
self.bus_o.rw.eq(bridge_rx.rw_o),
|
||||||
self.valid_o.eq(bridge_rx.valid_o),
|
self.bus_o.valid.eq(bridge_rx.valid_o),
|
||||||
# Internal Bus -> UART TX
|
# Internal Bus -> UART TX
|
||||||
bridge_tx.data_i.eq(self.data_i),
|
bridge_tx.data_i.eq(self.bus_i.data),
|
||||||
bridge_tx.rw_i.eq(self.rw_i),
|
bridge_tx.rw_i.eq(self.bus_i.rw),
|
||||||
bridge_tx.valid_i.eq(self.valid_i),
|
bridge_tx.valid_i.eq(self.bus_i.valid),
|
||||||
uart_tx.data_i.eq(bridge_tx.data_o),
|
uart_tx.data_i.eq(bridge_tx.data_o),
|
||||||
uart_tx.start_i.eq(bridge_tx.start_o),
|
uart_tx.start_i.eq(bridge_tx.start_o),
|
||||||
bridge_tx.done_i.eq(uart_tx.done_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
|
# place read transaction on the bus
|
||||||
yield module.addr_i.eq(addr)
|
yield module.bus_i.addr.eq(addr)
|
||||||
yield module.data_i.eq(0)
|
yield module.bus_i.data.eq(0)
|
||||||
yield module.rw_i.eq(0)
|
yield module.bus_i.rw.eq(0)
|
||||||
yield module.valid_i.eq(1)
|
yield module.bus_i.valid.eq(1)
|
||||||
yield
|
yield
|
||||||
yield module.addr_i.eq(0)
|
yield module.bus_i.addr.eq(0)
|
||||||
yield module.valid_i.eq(0)
|
yield module.bus_i.valid.eq(0)
|
||||||
|
|
||||||
# wait for output to be valid
|
# wait for output to be valid
|
||||||
while not (yield module.valid_o):
|
while not (yield module.bus_o.valid):
|
||||||
yield
|
yield
|
||||||
|
|
||||||
# compare returned value with expected
|
# compare returned value with expected
|
||||||
data = yield (module.data_o)
|
data = yield (module.bus_o.data)
|
||||||
if data != expected_data:
|
if data != expected_data:
|
||||||
raise ValueError(f"Read from {addr} yielded {data} instead of {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`.
|
at `addr`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
yield module.addr_i.eq(addr)
|
yield module.bus_i.addr.eq(addr)
|
||||||
yield module.data_i.eq(data)
|
yield module.bus_i.data.eq(data)
|
||||||
yield module.rw_i.eq(1)
|
yield module.bus_i.rw.eq(1)
|
||||||
yield module.valid_i.eq(1)
|
yield module.bus_i.valid.eq(1)
|
||||||
yield
|
yield
|
||||||
yield module.valid_i.eq(0)
|
yield module.bus_i.valid.eq(0)
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,19 +16,19 @@ la = LogicAnalyzerCore(config, base_addr=0, interface=None)
|
||||||
|
|
||||||
def print_data_at_addr(addr):
|
def print_data_at_addr(addr):
|
||||||
# place read transaction on the bus
|
# place read transaction on the bus
|
||||||
yield la.addr_i.eq(addr)
|
yield la.bus_i.addr.eq(addr)
|
||||||
yield la.data_i.eq(0)
|
yield la.bus_i.data.eq(0)
|
||||||
yield la.rw_i.eq(0)
|
yield la.bus_i.rw.eq(0)
|
||||||
yield la.valid_i.eq(1)
|
yield la.bus_i.valid.eq(1)
|
||||||
yield
|
yield
|
||||||
yield la.addr_i.eq(0)
|
yield la.bus_i.addr.eq(0)
|
||||||
yield la.valid_i.eq(0)
|
yield la.bus_i.valid.eq(0)
|
||||||
|
|
||||||
# wait for output to be valid
|
# wait for output to be valid
|
||||||
while not (yield la.valid_o):
|
while not (yield la.bus_o.valid):
|
||||||
yield
|
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):
|
def set_fsm_register(name, data):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue