amaranth-lang / amaranth

A modern hardware definition language and toolchain based on Python
https://amaranth-lang.org/docs/amaranth/
BSD 2-Clause "Simplified" License
1.55k stars 170 forks source link

A little help with defining platform pins? #278

Closed nmigen-issue-migration closed 4 years ago

nmigen-issue-migration commented 4 years ago

Issue by RobertBaruch Saturday Nov 30, 2019 at 23:21 GMT Originally opened as https://github.com/m-labs/nmigen/issues/278


I'm looking at the ice40hx8k, and I vaguely understand the blinky example, but it's not really clear from that, nor from the source, how to define and use my own resources and pins.

  1. It seems there must be a default clock defined, and it seems to be used for a reset delay. Also, it vaguely seems to be connected to the sync domain.

    a. What if I don't have a sync domain? What if I have instead two clock domains named ph1 and ph2? I can define these resources, but how do I say which is connected to ph1.clk and which is ph2.clk? And what about their resets -- how are pins configured as the resets (not talking about CRESET_B which seems to reload the entire FPGA configuration)?

    # For ice40hx8k ball functions, see 
    # https://www.latticesemi.com/view_document?document_id=49386
    # also https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/EI/EB85.ashx?document_id=50373

    default_clk = "clk_J3"
    resources = [
        Resource("clk_J3", 0, Pins("J3", dir="i"), Clock(12e6),
                 Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")), # GBIN6
        Resource("clk_G1", 0, Pins("G1", dir="i"), Clock(12e6),
                 Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")), # GBIN7
    ]
    ...
    ph1 = ClockDomain("ph1")
    ph2 = ClockDomain("ph2", clk_edge="neg")
    ...
    m.domains.ph1 = ph1
    m.domains.ph2 = ph2
    ...
    # How do I connect clk_J3 to ph1, and clk_G1 to ph2?
  1. How do I declare a pin to be used as an input? Like this?
    resources = [
        ...
        Resource("mice", 0, Pins("H1", dir="i"),
                 Attrs(IO_STANDARD="SB_LVCMOS")), # IOL_14B
        ...
    ]

And do I use it like this?

    rodent0 = platform.request("mice", 0)
    i_eated_it = Signal()
    kitten_present = Signal()
    ...
    m.d.comb += i_eated_it.eq(rodent0.i & kitten_present)

I'm pretty sure I understand the following correctly, but I'd like some confirmation:

  1. It seems the directions are i, o, io, oe. Going from what I think I see in plat.py, I think these mean input, output, bidirectional, and tristate output, right?

  2. Is an input accessed via <signal>.i? Output via <signal>.o? A tristate via <signal>.o for the output and <signal>.oe for the output enable? And a bidirectional via <signal>.o for the output, <signal>.i for the input, and <signal>.oe for the direction (0 = input, 1 = output)?

  3. For pins with invert=True, is it correct that <signal>.i is the invert of the signal present on the physical pin? And that <signal>.o is likewise the invert of the signal that will be output to the physical pin?

nmigen-issue-migration commented 4 years ago

Comment by whitequark Sunday Dec 01, 2019 at 00:26 GMT


  1. It seems there must be a default clock defined, and it seems to be used for a reset delay. Also, it vaguely seems to be connected to the sync domain.

Correct. The default clock/reset mechanism works as follows. If your HDL uses the sync domain, and this domain does not already exist, it is created, its clock is connected to the resource designated default_clk, and its reset is connected to a device-specific synchronization mechanism that coordinates power-on reset, and (if any) the resource designated default_rst. On Xilinx this mechanism is a BUFGCE (as recommended), on iCE40 it works around a silicon bug, elsewhere it's just a reset synchronizer.

What if I don't have a sync domain?

If your HDL never uses the sync domain, or if you explicitly define a sync domain using m.domains += ClockDomain("sync", ...) then nothing happens on its own. You should connect the clocks of your domain(s) to pins or perhaps oscillator instances.

If you do not have a default_clk, your HDL uses the sync domain, and does not define it, then an exception will stop the build.

  1. I can define these resources, but how do I say which is connected to ph1.clk and which is ph2.clk? And what about their resets -- how are pins configured as the resets (not talking about CRESET_B which seems to reload the entire FPGA configuration)?

There is fundamentally nothing special about clocks and resets. You can do something like

m.domains.ph1 = ph1 = ClockDomain("ph1", clk_edge="pos")
m.domains.ph1 = ph2 = ClockDomain("ph2", clk_edge="neg")
clk = platform.request("some_clk")
rst = platform.request("some_rst")
m.d.comb += [
  ph1.clk.eq(clk.i),
  ph2.clk.eq(clk.i),
  ph1.rst.eq(rst.i),
  ph2.rst.eq(rst.i),
]
  1. How do I declare a pin to be used as an input? Like this?

Yes, if the pin will always be an input (in most cases, the pin direction is well-known). In the rare case where for some reason you want to have a GPIO resource (not a connector), you can omit dir in the board file, and provide it to platform.request, like platform.request("foo", dir="i"). It is recommended to always declare the direction in the board file, since this reduces opportunity for a mistake.

And do I use it like this?

Yes. The default resource number is 0, so for singleton resources (one you're pretty sure you will only have one of), you can omit it.

  • It seems the directions are i, o, io, oe. Going from what I think I see in plat.py, I think these mean input, output, bidirectional, and tristate output, right?
  • Is an input accessed via <signal>.i? Output via <signal>.o? A tristate via <signal>.o for the output and <signal>.oe for the output enable? And a bidirectional via <signal>.o for the output, <signal>.i for the input, and <signal>.oe for the direction (0 = input, 1 = output)?
  • For pins with invert=True, is it correct that <signal>.i is the invert of the signal present on the physical pin? And that <signal>.o is likewise the invert of the signal that will be output to the physical pin?

All correct.

nmigen-issue-migration commented 4 years ago

Comment by RobertBaruch Sunday Dec 01, 2019 at 16:10 GMT


Thank you, that definitely helps me, especially the hint about default_rst.