Skip to content

Commit 1a20309

Browse files
gatecatrobtaylor
authored andcommitted
Simplify board initialisation and get it back working again
1 parent 7c23626 commit 1a20309

File tree

4 files changed

+86
-154
lines changed

4 files changed

+86
-154
lines changed

mcu_soc/chipflow.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ soc = "design.design:MySoC"
66

77
[chipflow.steps]
88
sim = "design.steps.sim:MySimStep"
9+
board = "design.steps.board:MyBoardStep"
910
silicon = "chipflow_lib.steps.silicon:SiliconStep"
1011
software = "design.steps.software:MySoftwareStep"
1112

mcu_soc/design/steps/board.py

Lines changed: 42 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
from amaranth import *
66
from amaranth.lib import wiring
7-
from amaranth.lib.wiring import connect, flipped
8-
from amaranth.build import Resource, Subsignal, Pins, Attrs
7+
from amaranth.lib.cdc import ResetSynchronizer
98

109
from ..design import MySoC
1110

@@ -17,92 +16,58 @@ def elaborate(self, platform):
1716
m.submodules.soc = soc = MySoC()
1817

1918
m.domains += ClockDomain("sync")
20-
m.submodules.clock_reset_provider = platform.providers.ClockResetProvider()
2119

22-
m.submodules.spiflash_provider = spiflash_provider = platform.providers.QSPIFlashProvider()
23-
connect(m, flipped(spiflash_provider.pins), soc.flash)
24-
25-
m.submodules.led_gpio_provider = led_gpio_provider = platform.providers.LEDGPIOProvider()
26-
connect(m, flipped(led_gpio_provider.pins), soc.gpio_0)
27-
28-
m.submodules.uart_provider = uart_provider = platform.providers.UARTProvider()
29-
connect(m, flipped(uart_provider.pins), soc.uart_0)
30-
31-
# Extra IO on headers
32-
platform.add_resources([
33-
Resource(
34-
"expansion",
35-
0,
36-
Subsignal("user_spi0_sck", Pins("0+", conn=("gpio", 0), dir='o')),
37-
Subsignal("user_spi0_copi", Pins("0-", conn=("gpio", 0), dir='o')),
38-
Subsignal("user_spi0_cipo", Pins("1+", conn=("gpio", 0), dir='i')),
39-
Subsignal("user_spi0_csn", Pins("1-", conn=("gpio", 0), dir='o')),
40-
41-
Subsignal("user_spi1_sck", Pins("2+", conn=("gpio", 0), dir='o')),
42-
Subsignal("user_spi1_copi", Pins("2-", conn=("gpio", 0), dir='o')),
43-
Subsignal("user_spi1_cipo", Pins("3+", conn=("gpio", 0), dir='i')),
44-
Subsignal("user_spi1_csn", Pins("3-", conn=("gpio", 0), dir='o')),
45-
46-
Subsignal("i2c0_sda", Pins("4+", conn=("gpio", 0), dir='io')),
47-
Subsignal("i2c0_scl", Pins("4-", conn=("gpio", 0), dir='io')),
48-
49-
Subsignal("motor_pwm0_pwm", Pins("5+", conn=("gpio", 0), dir='o')),
50-
Subsignal("motor_pwm0_dir", Pins("5-", conn=("gpio", 0), dir='o')),
51-
Subsignal("motor_pwm0_stop", Pins("6+", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")),
52-
53-
Subsignal("motor_pwm1_pwm", Pins("6-", conn=("gpio", 0), dir='o')),
54-
Subsignal("motor_pwm1_dir", Pins("7+", conn=("gpio", 0), dir='o')),
55-
Subsignal("motor_pwm1_stop", Pins("7-", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")),
56-
57-
Subsignal("uart1_rx", Pins("8+", conn=("gpio", 0), dir='i')),
58-
Subsignal("uart1_tx", Pins("8-", conn=("gpio", 0), dir='o')),
59-
60-
Subsignal("cpu_jtag_tck", Pins("9+", conn=("gpio", 0), dir='i')),
61-
Subsignal("cpu_jtag_tms", Pins("9-", conn=("gpio", 0), dir='i')),
62-
Subsignal("cpu_jtag_tdi", Pins("10+", conn=("gpio", 0), dir='i')),
63-
Subsignal("cpu_jtag_tdo", Pins("10-", conn=("gpio", 0), dir='o')),
64-
Subsignal("cpu_jtag_trst", Pins("11+", conn=("gpio", 0), dir='i')),
65-
66-
Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP"),
20+
m.d.comb += ClockSignal("sync").eq(platform.request("clk25").i)
21+
22+
btn_rst = platform.request("button_pwr")
23+
m.submodules.rst_sync = ResetSynchronizer(arst=btn_rst.i, domain="sync")
24+
25+
flash = platform.request("spi_flash", dir=dict(cs='-', copi='-', cipo='-', wp='-', hold='-'))
26+
# Flash clock requires a special primitive to access in ECP5
27+
m.submodules.usrmclk = Instance(
28+
"USRMCLK",
29+
i_USRMCLKI=soc.flash.clk.o,
30+
i_USRMCLKTS=ResetSignal(), # tristate in reset for programmer accesss
31+
a_keep=1,
32+
)
33+
34+
# Flash IO buffers
35+
m.submodules += Instance(
36+
"OBZ",
37+
o_O=flash.cs.io,
38+
i_I=soc.flash.csn.o,
39+
i_T=ResetSignal(),
40+
)
41+
42+
# Connect flash data pins in order
43+
data_pins = ["copi", "cipo", "wp", "hold"]
44+
for i in range(4):
45+
m.submodules += Instance(
46+
"BB",
47+
io_B=getattr(flash, data_pins[i]).io,
48+
i_I=soc.flash.d.o[i],
49+
i_T=~soc.flash.d.oe[i],
50+
o_O=soc.flash.d.i[i]
6751
)
68-
])
69-
70-
exp = platform.request("expansion")
71-
def _connect_interface(interface, name):
72-
pins = dict()
73-
for member in interface.signature.members:
74-
pin, suffix = member.rsplit("_", 2)
75-
assert suffix in ("o", "i", "oe"), suffix
76-
pins[pin] = getattr(interface, member).width
77-
for pin, width in pins.items():
78-
for i in range(width):
79-
platform_pin = getattr(exp, f"{name}_{pin}{'' if width == 1 else str(i)}")
80-
if hasattr(interface, f"{pin}_i"):
81-
m.d.comb += getattr(interface, f"{pin}_i")[i].eq(platform_pin.i)
82-
if hasattr(interface, f"{pin}_o"):
83-
m.d.comb += platform_pin.o.eq(getattr(interface, f"{pin}_o")[i])
84-
if hasattr(interface, f"{pin}_oe"):
85-
m.d.comb += platform_pin.oe.eq(getattr(interface, f"{pin}_oe")[i])
86-
87-
_connect_interface(soc.user_spi_0, "user_spi0")
88-
_connect_interface(soc.user_spi_1, "user_spi1")
89-
90-
_connect_interface(soc.i2c_0, "i2c0")
91-
92-
_connect_interface(soc.motor_pwm0, "motor_pwm0")
93-
_connect_interface(soc.motor_pwm1, "motor_pwm1")
9452

95-
_connect_interface(soc.uart_1, "uart1")
53+
# Connect LEDs to GPIO0
54+
for i in range(8):
55+
led = platform.request("led", i)
56+
m.d.comb += led.o.eq(soc.gpio_0.gpio.o[i])
9657

97-
_connect_interface(soc.cpu_jtag, "cpu_jtag")
58+
# Connect UART0
59+
uart = platform.request("uart")
60+
m.d.comb += [
61+
uart.tx.o.eq(soc.uart_0.tx.o),
62+
soc.uart_0.rx.i.eq(uart.rx.i),
63+
]
9864

9965
return m
10066

10167
class MyBoardStep(BoardStep):
10268
def __init__(self, config):
10369

10470
platform = ULX3S_85F_Platform()
105-
platform.providers = board_ulx3s_providers
10671

10772
super().__init__(config, platform)
10873

minimal/chipflow.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ soc = "design.design:MySoC"
66

77
[chipflow.steps]
88
sim = "design.steps.sim:MySimStep"
9+
board = "design.steps.board:MyBoardStep"
910
silicon = "chipflow_lib.steps.silicon:SiliconStep"
1011
software = "design.steps.software:MySoftwareStep"
1112

minimal/design/steps/board.py

Lines changed: 42 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
from amaranth import *
66
from amaranth.lib import wiring
7-
from amaranth.lib.wiring import connect, flipped
8-
from amaranth.build import Resource, Subsignal, Pins, Attrs
7+
from amaranth.lib.cdc import ResetSynchronizer
98

109
from ..design import MySoC
1110

@@ -17,92 +16,58 @@ def elaborate(self, platform):
1716
m.submodules.soc = soc = MySoC()
1817

1918
m.domains += ClockDomain("sync")
20-
m.submodules.clock_reset_provider = platform.providers.ClockResetProvider()
2119

22-
m.submodules.spiflash_provider = spiflash_provider = platform.providers.QSPIFlashProvider()
23-
connect(m, flipped(spiflash_provider.pins), soc.flash)
24-
25-
m.submodules.led_gpio_provider = led_gpio_provider = platform.providers.LEDGPIOProvider()
26-
connect(m, flipped(led_gpio_provider.pins), soc.gpio_0)
27-
28-
m.submodules.uart_provider = uart_provider = platform.providers.UARTProvider()
29-
connect(m, flipped(uart_provider.pins), soc.uart_0)
30-
31-
# Extra IO on headers
32-
platform.add_resources([
33-
Resource(
34-
"expansion",
35-
0,
36-
Subsignal("user_spi0_sck", Pins("0+", conn=("gpio", 0), dir='o')),
37-
Subsignal("user_spi0_copi", Pins("0-", conn=("gpio", 0), dir='o')),
38-
Subsignal("user_spi0_cipo", Pins("1+", conn=("gpio", 0), dir='i')),
39-
Subsignal("user_spi0_csn", Pins("1-", conn=("gpio", 0), dir='o')),
40-
41-
Subsignal("user_spi1_sck", Pins("2+", conn=("gpio", 0), dir='o')),
42-
Subsignal("user_spi1_copi", Pins("2-", conn=("gpio", 0), dir='o')),
43-
Subsignal("user_spi1_cipo", Pins("3+", conn=("gpio", 0), dir='i')),
44-
Subsignal("user_spi1_csn", Pins("3-", conn=("gpio", 0), dir='o')),
45-
46-
Subsignal("i2c0_sda", Pins("4+", conn=("gpio", 0), dir='io')),
47-
Subsignal("i2c0_scl", Pins("4-", conn=("gpio", 0), dir='io')),
48-
49-
Subsignal("motor_pwm0_pwm", Pins("5+", conn=("gpio", 0), dir='o')),
50-
Subsignal("motor_pwm0_dir", Pins("5-", conn=("gpio", 0), dir='o')),
51-
Subsignal("motor_pwm0_stop", Pins("6+", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")),
52-
53-
Subsignal("motor_pwm1_pwm", Pins("6-", conn=("gpio", 0), dir='o')),
54-
Subsignal("motor_pwm1_dir", Pins("7+", conn=("gpio", 0), dir='o')),
55-
Subsignal("motor_pwm1_stop", Pins("7-", conn=("gpio", 0), dir='i'), Attrs(PULLMODE="DOWN")),
56-
57-
Subsignal("uart1_rx", Pins("8+", conn=("gpio", 0), dir='i')),
58-
Subsignal("uart1_tx", Pins("8-", conn=("gpio", 0), dir='o')),
59-
60-
Subsignal("cpu_jtag_tck", Pins("9+", conn=("gpio", 0), dir='i')),
61-
Subsignal("cpu_jtag_tms", Pins("9-", conn=("gpio", 0), dir='i')),
62-
Subsignal("cpu_jtag_tdi", Pins("10+", conn=("gpio", 0), dir='i')),
63-
Subsignal("cpu_jtag_tdo", Pins("10-", conn=("gpio", 0), dir='o')),
64-
Subsignal("cpu_jtag_trst", Pins("11+", conn=("gpio", 0), dir='i')),
65-
66-
Attrs(IO_TYPE="LVCMOS33", PULLMODE="UP"),
20+
m.d.comb += ClockSignal("sync").eq(platform.request("clk25").i)
21+
22+
btn_rst = platform.request("button_pwr")
23+
m.submodules.rst_sync = ResetSynchronizer(arst=btn_rst.i, domain="sync")
24+
25+
flash = platform.request("spi_flash", dir=dict(cs='-', copi='-', cipo='-', wp='-', hold='-'))
26+
# Flash clock requires a special primitive to access in ECP5
27+
m.submodules.usrmclk = Instance(
28+
"USRMCLK",
29+
i_USRMCLKI=soc.flash.clk.o,
30+
i_USRMCLKTS=ResetSignal(), # tristate in reset for programmer accesss
31+
a_keep=1,
32+
)
33+
34+
# Flash IO buffers
35+
m.submodules += Instance(
36+
"OBZ",
37+
o_O=flash.cs.io,
38+
i_I=soc.flash.csn.o,
39+
i_T=ResetSignal(),
40+
)
41+
42+
# Connect flash data pins in order
43+
data_pins = ["copi", "cipo", "wp", "hold"]
44+
for i in range(4):
45+
m.submodules += Instance(
46+
"BB",
47+
io_B=getattr(flash, data_pins[i]).io,
48+
i_I=soc.flash.d.o[i],
49+
i_T=~soc.flash.d.oe[i],
50+
o_O=soc.flash.d.i[i]
6751
)
68-
])
69-
70-
exp = platform.request("expansion")
71-
def _connect_interface(interface, name):
72-
pins = dict()
73-
for member in interface.signature.members:
74-
pin, suffix = member.rsplit("_", 2)
75-
assert suffix in ("o", "i", "oe"), suffix
76-
pins[pin] = getattr(interface, member).width
77-
for pin, width in pins.items():
78-
for i in range(width):
79-
platform_pin = getattr(exp, f"{name}_{pin}{'' if width == 1 else str(i)}")
80-
if hasattr(interface, f"{pin}_i"):
81-
m.d.comb += getattr(interface, f"{pin}_i")[i].eq(platform_pin.i)
82-
if hasattr(interface, f"{pin}_o"):
83-
m.d.comb += platform_pin.o.eq(getattr(interface, f"{pin}_o")[i])
84-
if hasattr(interface, f"{pin}_oe"):
85-
m.d.comb += platform_pin.oe.eq(getattr(interface, f"{pin}_oe")[i])
86-
87-
_connect_interface(soc.user_spi_0, "user_spi0")
88-
_connect_interface(soc.user_spi_1, "user_spi1")
89-
90-
_connect_interface(soc.i2c_0, "i2c0")
91-
92-
_connect_interface(soc.motor_pwm0, "motor_pwm0")
93-
_connect_interface(soc.motor_pwm1, "motor_pwm1")
9452

95-
_connect_interface(soc.uart_1, "uart1")
53+
# Connect LEDs to GPIO0
54+
for i in range(8):
55+
led = platform.request("led", i)
56+
m.d.comb += led.o.eq(soc.gpio_0.gpio.o[i])
9657

97-
_connect_interface(soc.cpu_jtag, "cpu_jtag")
58+
# Connect UART0
59+
uart = platform.request("uart")
60+
m.d.comb += [
61+
uart.tx.o.eq(soc.uart_0.tx.o),
62+
soc.uart_0.rx.i.eq(uart.rx.i),
63+
]
9864

9965
return m
10066

10167
class MyBoardStep(BoardStep):
10268
def __init__(self, config):
10369

10470
platform = ULX3S_85F_Platform()
105-
platform.providers = board_ulx3s_providers
10671

10772
super().__init__(config, platform)
10873

0 commit comments

Comments
 (0)