Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added gatemate_a1_evb board #249

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 305 additions & 0 deletions amaranth_boards/gatemate_a1_evb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
import os
import argparse
import subprocess
import shutil
import unittest

from amaranth.build import *
from amaranth.vendor import GateMatePlatform
from .resources import *


__all__ = [
"GateMate_A1_EVB"
]

class _GateMate_A1_EVB(GateMatePlatform):
whitequark marked this conversation as resolved.
Show resolved Hide resolved
device = "GateMate_A1_EVB"
package = "CCGM1A1"
default_clk = "clk0"

resources = [
Resource("clk0", 0, Pins("IO_SB_A8", dir = "i"), Clock(10e6), Attrs(SCHMITT_TRIGGER="true")),
Resource("clk1", 0, Pins("IO_SB_A7", dir = "i"), Clock(10e6)), # GPIO23
Resource("clk2", 0, Pins("IO_SB_A6", dir = "i"), Clock(10e6)), # GPIO24
Resource("clk3", 0, Pins("IO_SB_A5", dir = "i"), Clock(10e6)),
Comment on lines +21 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Resource("clk0", 0, Pins("IO_SB_A8", dir = "i"), Clock(10e6), Attrs(SCHMITT_TRIGGER="true")),
Resource("clk1", 0, Pins("IO_SB_A7", dir = "i"), Clock(10e6)), # GPIO23
Resource("clk2", 0, Pins("IO_SB_A6", dir = "i"), Clock(10e6)), # GPIO24
Resource("clk3", 0, Pins("IO_SB_A5", dir = "i"), Clock(10e6)),
Resource("clk", 0, Pins("IO_SB_A8", dir = "i"), Clock(10e6), Attrs(SCHMITT_TRIGGER="true")),
Resource("clk", 1, Pins("IO_SB_A7", dir = "i"), Clock(10e6)), # GPIO23
Resource("clk", 2, Pins("IO_SB_A6", dir = "i"), Clock(10e6)), # GPIO24
Resource("clk", 3, Pins("IO_SB_A5", dir = "i"), Clock(10e6)),

(Why is only the first one configured with a Schmitt trigger?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good question. Generaly the board is new, and this general constraint file is written by me. In the official constraint file the clk0 resource has SCHMITT_TRIGGER="true" so I placed it here aswell. I will look into the other clocks aswell.


*LEDResources(pins = "IO_SB_B6", attrs=Attrs()),
*ButtonResources("fpga_but", pins="IO_SB_B7", attrs=Attrs()),


# Note: The documentation flipped the rx and tx pins
UARTResource(0,
rx="IO_SA_A6", tx="IO_SA_B6", role="dce" , attrs=Attrs()
),

# TODO: Check what is copi and cipo?
# TODO: Check where to place SPI_D0, SPI_D1, SPI_D2, SPI_D3 and FPGA_SPI_FWD?
#SPIResource(0,
# cs_n="IO_WA_A8", clk="IO_WA_B8"
#),

PS2Resource(0,
clk="IO_WB_A0", dat="IO_WB_B0"
),

Resource("psram", 0,
Subsignal("psram_cs", Pins("IO_WC_A4", dir="o")),
Subsignal("psram_sclk", Pins("IO_WC_B4", dir="o")),
Subsignal("psram_data", Pins("IO_WC_A5 IO_WC_B5 IO_WC_A6 IO_WC_B6 "
"IO_WC_A7 IO_WC_B7 IO_WC_A8 IO_WC_B8",
dir="io"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The subsignals are already namespaced:

Suggested change
Subsignal("psram_cs", Pins("IO_WC_A4", dir="o")),
Subsignal("psram_sclk", Pins("IO_WC_B4", dir="o")),
Subsignal("psram_data", Pins("IO_WC_A5 IO_WC_B5 IO_WC_A6 IO_WC_B6 "
"IO_WC_A7 IO_WC_B7 IO_WC_A8 IO_WC_B8",
dir="io"))
Subsignal("cs", Pins("IO_WC_A4", dir="o")),
Subsignal("sclk", Pins("IO_WC_B4", dir="o")),
Subsignal("data", Pins("IO_WC_A5 IO_WC_B5 IO_WC_A6 IO_WC_B6 "
"IO_WC_A7 IO_WC_B7 IO_WC_A8 IO_WC_B8",
dir="io"))

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the psram prefix.

),

Resource("vga", 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use VGAResource.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use VGAResource

Suggested change
Resource("vga", 0,
VGAResource("vga", 0,
r="IO_WB_B3 IO_WB_A3 IO_WB_B2 IO_WB_A2",
g="IO_WB_B5 IO_WB_A5 IO_WB_B4 IO_WB_A4",
b="IO_WB_B7 IO_WB_A7 IO_WB_B6 IO_WB_A6",
vs= "IO_WB_B1",
hs="IO_WB_A1"
),

Subsignal("hsync", Pins("IO_WB_A1", dir="o")),
Subsignal("vsync", Pins("IO_WB_B1", dir="o")),
Subsignal("red", Pins(
"IO_WB_B3" # Red_0
"IO_WB_A3" # Red_1
"IO_WB_B2" # Red_2
"IO_WB_A2", # Red_3
dir="o"
)),
Subsignal("green", Pins(
"IO_WB_B5" # Green_0
"IO_WB_A5" # Green_1
"IO_WB_B4" # Green_2
"IO_WB_A4", # Green_3
dir="o"
)),
Subsignal("blue", Pins(
"IO_WB_B7" # Blue_0
"IO_WB_A7" # Blue_1
"IO_WB_B6" # Blue_2
"IO_WB_A6", # Blue_3
dir="o"
))
),

Resource("jtag", 0,
Subsignal("led", Pins("IO_SB_B5", dir="o")),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LED?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
This is what it says in the schematic.

Subsignal("tck", Pins("IO_WA_A5", dir="i")),
Subsignal("tms", Pins("IO_WA_B4", dir="i")),
Subsignal("tdi", Pins("IO_WA_A4", dir="i")),
Subsignal("tdo", Pins("IO_WA_B3", dir="o"))
),

# TODO: Mybe the d Resource needs to be different input/output
Resource("spi", 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use SPIResource.

Copy link
Author

@TarikHamedovic TarikHamedovic Jul 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem was I didn't know how to map the 'd' signals to the copi cipo signals of the SPIResource.

Subsignal("clk", Pins("IO_WA_B8", dir="o")),
Subsignal("csn", Pins("IO_WA_A8", dir="o")),
Subsignal("d", Pins("IO_WA_B7 IO_WA_A7 IO_WA_B6 IO_WA_A6" , dir="io")),
Subsignal("fwd", Pins("IO_WA_B5", dir="o")),
),

# TODO: Check how to declare LVDS pins
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're looking for DiffPairs("true", "complement").

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed serdes to use DiffPairs and removed the ser prefix.

# TODO: Check direction of serdes pins
Resource("serdes", 0,
Subsignal("ser_clk_n", Pins("IO_SER_CLK_N", dir="io")),
Subsignal("ser_clk_p", Pins("IO_SER_CLK_P", dir="io")),
Subsignal("ser_tx_p", Pins("IO_SER_TX_P", dir="io")),
Subsignal("ser_tx_n", Pins("IO_SER_TX_N", dir="io")),
Subsignal("ser_rx_n", Pins("IO_SER_RX_N", dir="io")),
Subsignal("ser_rx_p", Pins("IO_SER_RX_P", dir="io"))
),

Resource("uext", 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a Connector, not a Resource.

Copy link
Author

@TarikHamedovic TarikHamedovic Jul 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it from a Resource to a Connector.

Subsignal("txd", Pins("IO_EA_A0", dir ="o" )),
Subsignal("rxd", Pins("IO_EA_B0", dir ="i" )),
Subsignal("scl", Pins("IO_EA_A1", dir ="io")),
Subsignal("sda", Pins("IO_EA_B1", dir ="io")),
Subsignal("miso", Pins("IO_EA_A2", dir ="i" )),
Subsignal("mosi", Pins("IO_EA_B2", dir ="o" )),
Subsignal("sck", Pins("IO_EA_A3", dir ="o" )),
Subsignal("cs", Pins("IO_EA_B3", dir ="o" )),
),

Resource("pmod", 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a Connector.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed from Resource to Connector

Subsignal("1", Pins("IO_EA_A4", dir ="io")),
Subsignal("7", Pins("IO_EA_B4", dir ="io")),
Subsignal("2", Pins("IO_EA_A5", dir ="io")),
Subsignal("8", Pins("IO_EA_B5", dir ="io")),
Subsignal("3", Pins("IO_EA_A6", dir ="io")),
Subsignal("9", Pins("IO_EA_B6", dir ="io")),
Subsignal("4", Pins("IO_EA_A7", dir ="io")),
Subsignal("10", Pins("IO_EA_B7", dir ="io")),
),


# Mostly used for RP2040
Resource("gpio", 0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also looks like a Connector.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used for RP2040, and there are no external connections to these pins here. Are they still connectors?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of a Connector isn't necessarily that it's a physical connector, but that it's an extension point where a downstream user of this platform can attach project specific resources. A project using SPI to communicate with the RP2040 could e.g. want to attach a SPIResource to some of those signals.

Subsignal("0", Pins("IO_SA_A0", dir ="io")),
Subsignal("1", Pins("IO_SA_B0", dir ="io")),
Subsignal("2", Pins("IO_SA_A1", dir ="io")),
Subsignal("3", Pins("IO_SA_B1", dir ="io")),
Subsignal("4", Pins("IO_SA_A2", dir ="io")),
Subsignal("5", Pins("IO_SA_B2", dir ="io")),
Subsignal("6", Pins("IO_SA_A3", dir ="io")),
Subsignal("7", Pins("IO_SA_B3", dir ="io")),
Subsignal("8", Pins("IO_SA_A4", dir ="io")),
Subsignal("9", Pins("IO_SA_B4", dir ="io")),
Subsignal("10", Pins("IO_SA_A5", dir ="io")),
Subsignal("11", Pins("IO_SA_B5", dir ="io")),
Subsignal("14", Pins("IO_SA_A7", dir ="io")),
Subsignal("15", Pins("IO_SA_B7", dir ="io")),
Subsignal("21", Pins("IO_SB_B8", dir ="io")), # GPIN1
Subsignal("26", Pins("IO_SB_B4", dir ="io")),
Subsignal("27", Pins("IO_SB_A4", dir ="io")),
Subsignal("28", Pins("IO_SB_A8", dir ="io")),
Subsignal("29", Pins("IO_SB_B8", dir ="io")),
),
]


connectors = [
Connector("bank_na1", 0, {
whitequark marked this conversation as resolved.
Show resolved Hide resolved
# Lower Row (BOTTOM LEFT PIN IS VDD)
#"1" : "VDD"
"3": "IO_NA_A0",
"5": "IO_NA_A1",
"7": "IO_NA_A2",
"9": "IO_NA_A3",
"11": "IO_NA_A4",
"13": "IO_NA_A5",
"15": "IO_NA_A6",
"17": "IO_NA_A7",
"19": "IO_NA_A8",
# Upper Row (TOP LEFT PIN IS GND)
#"2" : "GND"
"4": "IO_NA_B0",
"6": "IO_NA_B1",
"8": "IO_NA_B2",
"10": "IO_NA_B3",
"12": "IO_NA_B4",
"14": "IO_NA_B5",
"16": "IO_NA_B6",
"18": "IO_NA_B7",
"20": "IO_NA_B8",
}),

Connector("bank_nb1", 0, {
# Lower Row (BOTTOM LEFT PIN IS VDD)
#"1" : "VDD"
"3": "IO_NB_A0",
"5": "IO_NB_A1",
"7": "IO_NB_A2",
"9": "IO_NB_A3",
"11": "IO_NB_A4",
"13": "IO_NB_A5",
"15": "IO_NB_A6",
"17": "IO_NB_A7",
"19": "IO_NB_A8",
# Upper Row (TOP LEFT PIN IS GND)
#"2" : "GND"
"4": "IO_NB_B0",
"6": "IO_NB_B1",
"8": "IO_NB_B2",
"10": "IO_NB_B3",
"12": "IO_NB_B4",
"14": "IO_NB_B5",
"16": "IO_NB_B6",
"18": "IO_NB_B7",
"20": "IO_NB_B8",
}),

Connector("bank_eb1", 0, {
# Lower Row (BOTTOM LEFT PIN IS VDD)
#"1" : "VDD"
"3": "IO_EB_A0",
"5": "IO_EB_A1",
"7": "IO_EB_A2",
"9": "IO_EB_A3",
"11": "IO_EB_A4",
"13": "IO_EB_A5",
"15": "IO_EB_A6",
"17": "IO_EB_A7",
"19": "IO_EB_A8",
# Upper Row (TOP LEFT PIN IS GND)
#"2" : "GND"
"4": "IO_EB_B0",
"6": "IO_EB_B1",
"8": "IO_EB_B2",
"10": "IO_EB_B3",
"12": "IO_EB_B4",
"14": "IO_EB_B5",
"16": "IO_EB_B6",
"18": "IO_EB_B7",
"20": "IO_EB_B8",
}),

Connector("bank_misc1", 0, {
# Left Row (TOP LEFT PIN IS 2.5V)
#"1" : "2.5V"
"fpga_spi_fwd": "IO_WA_B5", # 3
"5": "IO_EA_A8",
"7": "IO_EA_B8",
"9": "IO_WB_A8",
"11": "IO_WB_B8",
"13": "IO_SB_B3",
"15": "IO_SB_A3",
"17": "IO_SB_B2",
"19": "IO_SB_A2",
"21": "IO_SB_B1",
"23": "IO_SB_A1",
"25": "IO_SB_B0",
"27": "IO_SB_A0",
"fpga_reset_in": "RST_N",
# Right Row (TOP RIGHT PIN IS 1.8V)
#"2" : "1.8V"
"4": "IO_WC_B3",
"6": "IO_WC_A3",
"8": "IO_WC_B2",
"10": "IO_WC_A2",
"12": "IO_WC_B1",
"14": "IO_WC_A1",
"16": "IO_WC_B0",
"18": "IO_WC_A0",
# SerDes
"18": "IO_SER_CLK_N",
"20": "IO_SER_CLK_P",
"22": "IO_SER_TX_P",
"24": "IO_SER_TX_N",
"26": "IO_SER_RX_N",
"28": "IO_SER_RX_P"
})
]

@property
def required_tools(self):
return super().required_tools + [
"openFPGALoader"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it's not currently documented, required_tools is only for the tools required to produce the bitstream. Programming tools should not included and it will cause issues if they are.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will remove that, but just to point out that ulx3s.py has the same line aswell.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's also wrong (I missed it during review previously).

]

def toolchain_prepare(self, fragment, name, **kwargs):
overrides = dict(yosys_opts="-p 'synth_gatemate -top {} -nomx8 -vlog'".format(name),
pr_opts="-v -ccP",
Copy link
Member

@whitequark whitequark Jul 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While these could and should be valid overrides in principle, they currently aren't: you are not doing anything with yosys_opts or pr_opts in your Amaranth PR. In addition, basic options like this should not be in a board file at all.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I remove toolchain_prepare ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see a reason why one would be needed here.

openfpgaloader_opts="-b gatemate_evb_jtag --cable dirtyJtag")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since overrides only affect the build process, not the programming process, this option will never be used.

overrides.update(kwargs)
return super().toolchain_prepare(fragment, name, **overrides)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(In this particular case I don't think you need any toolchain overrides.)



def toolchain_program(self, products, name):
tool = os.environ.get("OPENFPGALOADER", "openFPGALoader")
with products.extract("{}_00.cfg.bit".format(name)) as bitstream_filename:
subprocess.check_call([tool, "-b", "gatemate_evb_jtag", "--cable", "dirtyJtag", bitstream_filename])

class GateMate_A1_EVB(_GateMate_A1_EVB):
name = "Olimex GateMateA1-EVB"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class GateMate_A1_EVB(_GateMate_A1_EVB):
name = "Olimex GateMateA1-EVB"


class TestCase(unittest.TestCase):
def test_smoke(self):
from .test.blinky import Blinky
GateMate_A1_EVB().build(Blinky(), do_build= False)



if __name__ == "__main__":
from .test.blinky import *

variants = [] # No variants so far
whitequark marked this conversation as resolved.
Show resolved Hide resolved

platform = GateMate_A1_EVB()
platform.build(Blinky(), do_program=True)


Loading