Added Uart.
This commit is contained in:
+52
-21
@@ -12,14 +12,15 @@ See CLAUDE.md "Module Breakdown" and "CDC Signal Inventory" for the full list.
|
||||
|
||||
from amaranth import *
|
||||
|
||||
from exi_bba.exi_capture import ExiCapture
|
||||
from exi_bba.bba_register_file import BBARegisterFile
|
||||
from exi_bba.spram_arbiter import SPRAMArbiter
|
||||
from exi_bba.rx_frame_assembler import RXFrameAssembler
|
||||
from exi_bba.tx_frame_drain import TXFrameDrain
|
||||
from exi_bba.w5500_spi_master import W5500SPIMaster
|
||||
from exi_bba.exi_capture import ExiCapture
|
||||
from exi_bba.bba_register_file import BBARegisterFile
|
||||
from exi_bba.spram_arbiter import SPRAMArbiter
|
||||
from exi_bba.rx_frame_assembler import RXFrameAssembler
|
||||
from exi_bba.tx_frame_drain import TXFrameDrain
|
||||
from exi_bba.w5500_spi_master import W5500SPIMaster
|
||||
from exi_bba.w5100_parallel_master import W5100ParallelMaster
|
||||
from exi_bba.status_panel import StatusPanel
|
||||
from exi_bba.status_panel import StatusPanel
|
||||
from exi_bba.uart_console import UARTConsole
|
||||
|
||||
from amaranth.lib.cdc import FFSynchronizer
|
||||
|
||||
@@ -43,7 +44,8 @@ class BBATop(Elaboratable):
|
||||
w5500_rst_n : W5500 hardware reset (output, active low)
|
||||
"""
|
||||
|
||||
def __init__(self, eth="w5100", reset_cycles=24000, status_panel=False):
|
||||
def __init__(self, eth="w5100", reset_cycles=24000,
|
||||
status_panel=False, uart_console=False):
|
||||
# Ethernet back-end: "w5100" (indirect parallel bus, reaches the EXI
|
||||
# ceiling) or "w5500" (SPI, ~12 Mbit/s). Both expose the identical
|
||||
# tx/rx/init/par interface, so only the physical pins differ.
|
||||
@@ -54,6 +56,9 @@ class BBATop(Elaboratable):
|
||||
# Optional bring-up status panel (drives onboard LEDs/button on the
|
||||
# iCEbreaker — see synth.py). panel_led bit order matches StatusPanel.
|
||||
self._status_panel = status_panel
|
||||
# Optional UART debug console (8N1 115200, sync domain).
|
||||
# uart_tx → FT2232H Channel B pin 9; uart_rx ← pin 6.
|
||||
self._uart_console = uart_console
|
||||
|
||||
# EXI (GC side)
|
||||
self.exi_clk = Signal(init=1)
|
||||
@@ -89,6 +94,10 @@ class BBATop(Elaboratable):
|
||||
self.panel_led = Signal(5) # to onboard LEDs (see StatusPanel)
|
||||
self.panel_btn = Signal(3) # from onboard button(s)
|
||||
|
||||
if uart_console:
|
||||
self.uart_tx = Signal(init=1) # FPGA → PC (FT2232H Channel B)
|
||||
self.uart_rx = Signal(init=1) # PC → FPGA
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
@@ -277,25 +286,28 @@ class BBATop(Elaboratable):
|
||||
# The RX ring-buffer path is active only after the GC sets NCRA[3].
|
||||
m.d.comb += asm.rx_enabled.eq(reg.ncra_sr)
|
||||
|
||||
# ── Optional bring-up status panel (sync domain) ──────────────────
|
||||
# init_req = NCRA reset (exi→sync PS), OR'd with the panel's manual
|
||||
# re-init button when the panel is present.
|
||||
# ── Optional bring-up peripherals (sync domain) ───────────────────
|
||||
# Build init_req as an OR of all reinit sources (NCRA pulse plus any
|
||||
# manual re-init from the status panel and/or the UART 'r' command).
|
||||
# "ready" is latched high by eth.init_done and cleared by any init_req.
|
||||
# It is computed only when at least one peripheral needs it.
|
||||
|
||||
init_req = reg.ncra_rst_o # base: GC-issued NCRA reset
|
||||
|
||||
need_ready = self._status_panel or self._uart_console
|
||||
if need_ready:
|
||||
ready = Signal()
|
||||
|
||||
if self._status_panel:
|
||||
panel = StatusPanel()
|
||||
m.submodules.panel = panel
|
||||
init_req = init_req | panel.reinit
|
||||
|
||||
# cs_active lives in the exi domain; bring it to sync for the LED.
|
||||
cs_a_sync = Signal()
|
||||
m.submodules.panel_cs = FFSynchronizer(
|
||||
cap.cs_active, cs_a_sync, o_domain="sync")
|
||||
|
||||
# "ready" = ethernet init complete (latched until the next init).
|
||||
ready = Signal()
|
||||
with m.If(eth.init_done):
|
||||
m.d.sync += ready.eq(1)
|
||||
with m.Elif(reg.ncra_rst_o | panel.reinit):
|
||||
m.d.sync += ready.eq(0)
|
||||
|
||||
m.d.comb += [
|
||||
panel.cs_active.eq(cs_a_sync),
|
||||
panel.rx_pulse .eq(asm.rx_irq),
|
||||
@@ -303,10 +315,29 @@ class BBATop(Elaboratable):
|
||||
panel.ready .eq(ready),
|
||||
panel.btn .eq(self.panel_btn),
|
||||
self.panel_led .eq(panel.led),
|
||||
eth.init_req .eq(reg.ncra_rst_o | panel.reinit),
|
||||
]
|
||||
else:
|
||||
m.d.comb += eth.init_req.eq(reg.ncra_rst_o)
|
||||
|
||||
if self._uart_console:
|
||||
console = UARTConsole()
|
||||
m.submodules.console = console
|
||||
init_req = init_req | console.reinit
|
||||
|
||||
m.d.comb += [
|
||||
console.ncra_rst.eq(reg.ncra_rst_o),
|
||||
console.rx_pulse.eq(asm.rx_irq),
|
||||
console.tx_pulse.eq(drain.tx_irq),
|
||||
console.ready .eq(ready),
|
||||
self.uart_tx .eq(console.uart_tx),
|
||||
console.uart_rx .eq(self.uart_rx),
|
||||
]
|
||||
|
||||
if need_ready:
|
||||
with m.If(eth.init_done):
|
||||
m.d.sync += ready.eq(1)
|
||||
with m.Elif(init_req):
|
||||
m.d.sync += ready.eq(0)
|
||||
|
||||
m.d.comb += eth.init_req.eq(init_req)
|
||||
|
||||
return m
|
||||
|
||||
|
||||
Reference in New Issue
Block a user