Added Debouncer ToggleButton and PulseButton
This commit is contained in:
parent
eea189ae61
commit
ac755932d5
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1 +1,2 @@
|
||||
docs/media/SP1-picture-with-pin-numbers.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
docs/media/pinouts.png filter=lfs diff=lfs merge=lfs -text
|
||||
|
195
PulseButton.vcd
Normal file
195
PulseButton.vcd
Normal file
@ -0,0 +1,195 @@
|
||||
$comment Generated by Amaranth $end
|
||||
$date 2025-09-20 22:27:02.816595 $end
|
||||
$timescale 1 fs $end
|
||||
$scope module bench $end
|
||||
$scope module top $end
|
||||
$var wire 1 ! clk $end
|
||||
$var wire 1 " rst $end
|
||||
$var wire 1 # i $end
|
||||
$var wire 1 $ i$3 $end
|
||||
$var wire 14 % counter $end
|
||||
$var wire 1 & o $end
|
||||
$var wire 1 ' o$6 $end
|
||||
$var wire 1 ( last_seen $end
|
||||
$scope module U$0 $end
|
||||
$var wire 1 ! clk $end
|
||||
$var wire 1 " rst $end
|
||||
$var wire 1 # i $end
|
||||
$var wire 1 ' o $end
|
||||
$var wire 1 ) prevInValid $end
|
||||
$var wire 14 * count $end
|
||||
$var wire 1 + state $end
|
||||
$var wire 1 , prevIn $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
#0
|
||||
$dumpvars
|
||||
0!
|
||||
0"
|
||||
0#
|
||||
0$
|
||||
b0 %
|
||||
0&
|
||||
0'
|
||||
0(
|
||||
0)
|
||||
b10011100010000 *
|
||||
0+
|
||||
0,
|
||||
$end
|
||||
#500000000
|
||||
1!
|
||||
1)
|
||||
b0 *
|
||||
#1000000000
|
||||
0!
|
||||
#1500000000
|
||||
1!
|
||||
1$
|
||||
1#
|
||||
#2000000000
|
||||
0!
|
||||
#2500000000
|
||||
1!
|
||||
1+
|
||||
1,
|
||||
b10011100010000 *
|
||||
1'
|
||||
#3000000000
|
||||
0!
|
||||
#3500000000
|
||||
1!
|
||||
1&
|
||||
1(
|
||||
#4000000000
|
||||
0!
|
||||
#4500000000
|
||||
1!
|
||||
0&
|
||||
b10011100010000 %
|
||||
#5000000000
|
||||
0!
|
||||
#5500000000
|
||||
1!
|
||||
b10011100001111 %
|
||||
#6000000000
|
||||
0!
|
||||
#6500000000
|
||||
1!
|
||||
b10011100001110 %
|
||||
0$
|
||||
0#
|
||||
#7000000000
|
||||
0!
|
||||
#7500000000
|
||||
1!
|
||||
0,
|
||||
b10011100001111 *
|
||||
b10011100001101 %
|
||||
#8000000000
|
||||
0!
|
||||
#8500000000
|
||||
1!
|
||||
b10011100001110 *
|
||||
b10011100001100 %
|
||||
#9000000000
|
||||
0!
|
||||
#9500000000
|
||||
1!
|
||||
b10011100001101 *
|
||||
b10011100001011 %
|
||||
#10000000000
|
||||
0!
|
||||
#10500000000
|
||||
1!
|
||||
b10011100001100 *
|
||||
b10011100001010 %
|
||||
#11000000000
|
||||
0!
|
||||
#11500000000
|
||||
1!
|
||||
b10011100001011 *
|
||||
b10011100001001 %
|
||||
1$
|
||||
1#
|
||||
#12000000000
|
||||
0!
|
||||
#12500000000
|
||||
1!
|
||||
1,
|
||||
b10011100010000 *
|
||||
b10011100001000 %
|
||||
#13000000000
|
||||
0!
|
||||
#13500000000
|
||||
1!
|
||||
b10011100000111 %
|
||||
#14000000000
|
||||
0!
|
||||
#14500000000
|
||||
1!
|
||||
b10011100000110 %
|
||||
#15000000000
|
||||
0!
|
||||
#15500000000
|
||||
1!
|
||||
b10011100000101 %
|
||||
#16000000000
|
||||
0!
|
||||
#16500000000
|
||||
1!
|
||||
b10011100000100 %
|
||||
0$
|
||||
0#
|
||||
#17000000000
|
||||
0!
|
||||
#17500000000
|
||||
1!
|
||||
0,
|
||||
b10011100001111 *
|
||||
b10011100000011 %
|
||||
#18000000000
|
||||
0!
|
||||
#18500000000
|
||||
1!
|
||||
b10011100001110 *
|
||||
b10011100000010 %
|
||||
#19000000000
|
||||
0!
|
||||
#19500000000
|
||||
1!
|
||||
b10011100001101 *
|
||||
b10011100000001 %
|
||||
#20000000000
|
||||
0!
|
||||
#20500000000
|
||||
1!
|
||||
b10011100001100 *
|
||||
b10011100000000 %
|
||||
#21000000000
|
||||
0!
|
||||
#21500000000
|
||||
1!
|
||||
b10011100001011 *
|
||||
b10011011111111 %
|
||||
#22000000000
|
||||
0!
|
||||
#22500000000
|
||||
1!
|
||||
b10011100001010 *
|
||||
b10011011111110 %
|
||||
#23000000000
|
||||
0!
|
||||
#23500000000
|
||||
1!
|
||||
b10011100001001 *
|
||||
b10011011111101 %
|
||||
#24000000000
|
||||
0!
|
||||
#24500000000
|
||||
1!
|
||||
b10011100001000 *
|
||||
b10011011111100 %
|
||||
#25000000000
|
171
ToggleButton.vcd
Normal file
171
ToggleButton.vcd
Normal file
@ -0,0 +1,171 @@
|
||||
$comment Generated by Amaranth $end
|
||||
$date 2025-09-20 22:27:02.809849 $end
|
||||
$timescale 1 fs $end
|
||||
$scope module bench $end
|
||||
$scope module top $end
|
||||
$var wire 1 ! clk $end
|
||||
$var wire 1 " rst $end
|
||||
$var wire 1 # i $end
|
||||
$var wire 1 $ i$3 $end
|
||||
$var wire 1 % o $end
|
||||
$var wire 1 & last_seen $end
|
||||
$var wire 1 ' o$6 $end
|
||||
$scope module U$0 $end
|
||||
$var wire 1 ! clk $end
|
||||
$var wire 1 " rst $end
|
||||
$var wire 1 # i $end
|
||||
$var wire 1 % o $end
|
||||
$var wire 1 ( prevInValid $end
|
||||
$var wire 14 ) count $end
|
||||
$var wire 1 * state $end
|
||||
$var wire 1 + prevIn $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
#0
|
||||
$dumpvars
|
||||
0!
|
||||
0"
|
||||
0#
|
||||
0$
|
||||
0%
|
||||
0&
|
||||
0'
|
||||
0(
|
||||
b10011100010000 )
|
||||
0*
|
||||
0+
|
||||
$end
|
||||
#500000000
|
||||
1!
|
||||
b0 )
|
||||
1(
|
||||
#1000000000
|
||||
0!
|
||||
#1500000000
|
||||
1!
|
||||
1$
|
||||
1#
|
||||
#2000000000
|
||||
0!
|
||||
#2500000000
|
||||
1!
|
||||
b10011100010000 )
|
||||
1*
|
||||
1+
|
||||
1%
|
||||
#3000000000
|
||||
0!
|
||||
#3500000000
|
||||
1!
|
||||
1&
|
||||
1'
|
||||
#4000000000
|
||||
0!
|
||||
#4500000000
|
||||
1!
|
||||
#5000000000
|
||||
0!
|
||||
#5500000000
|
||||
1!
|
||||
#6000000000
|
||||
0!
|
||||
#6500000000
|
||||
1!
|
||||
0$
|
||||
0#
|
||||
#7000000000
|
||||
0!
|
||||
#7500000000
|
||||
1!
|
||||
b10011100001111 )
|
||||
0+
|
||||
#8000000000
|
||||
0!
|
||||
#8500000000
|
||||
1!
|
||||
b10011100001110 )
|
||||
#9000000000
|
||||
0!
|
||||
#9500000000
|
||||
1!
|
||||
b10011100001101 )
|
||||
#10000000000
|
||||
0!
|
||||
#10500000000
|
||||
1!
|
||||
b10011100001100 )
|
||||
#11000000000
|
||||
0!
|
||||
#11500000000
|
||||
1!
|
||||
b10011100001011 )
|
||||
1$
|
||||
1#
|
||||
#12000000000
|
||||
0!
|
||||
#12500000000
|
||||
1!
|
||||
b10011100010000 )
|
||||
1+
|
||||
#13000000000
|
||||
0!
|
||||
#13500000000
|
||||
1!
|
||||
#14000000000
|
||||
0!
|
||||
#14500000000
|
||||
1!
|
||||
#15000000000
|
||||
0!
|
||||
#15500000000
|
||||
1!
|
||||
#16000000000
|
||||
0!
|
||||
#16500000000
|
||||
1!
|
||||
0$
|
||||
0#
|
||||
#17000000000
|
||||
0!
|
||||
#17500000000
|
||||
1!
|
||||
b10011100001111 )
|
||||
0+
|
||||
#18000000000
|
||||
0!
|
||||
#18500000000
|
||||
1!
|
||||
b10011100001110 )
|
||||
#19000000000
|
||||
0!
|
||||
#19500000000
|
||||
1!
|
||||
b10011100001101 )
|
||||
#20000000000
|
||||
0!
|
||||
#20500000000
|
||||
1!
|
||||
b10011100001100 )
|
||||
#21000000000
|
||||
0!
|
||||
#21500000000
|
||||
1!
|
||||
b10011100001011 )
|
||||
#22000000000
|
||||
0!
|
||||
#22500000000
|
||||
1!
|
||||
b10011100001010 )
|
||||
#23000000000
|
||||
0!
|
||||
#23500000000
|
||||
1!
|
||||
b10011100001001 )
|
||||
#24000000000
|
||||
0!
|
||||
#24500000000
|
||||
1!
|
||||
b10011100001000 )
|
||||
#25000000000
|
21
docs/.obsidian/workspace.json
vendored
21
docs/.obsidian/workspace.json
vendored
@ -11,17 +11,12 @@
|
||||
"id": "be20a2e02f2b6437",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "canvas",
|
||||
"type": "image",
|
||||
"state": {
|
||||
"file": "GameCube/Sp1 physical connector.canvas",
|
||||
"viewState": {
|
||||
"x": 72,
|
||||
"y": -20,
|
||||
"zoom": 0
|
||||
}
|
||||
"file": "media/pinouts.png"
|
||||
},
|
||||
"icon": "lucide-layout-dashboard",
|
||||
"title": "Sp1 physical connector"
|
||||
"icon": "lucide-image",
|
||||
"title": "pinouts"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -174,9 +169,13 @@
|
||||
},
|
||||
"active": "be20a2e02f2b6437",
|
||||
"lastOpenFiles": [
|
||||
"GameCube/SP1.md",
|
||||
"GameCube/Sp1 physical connector.canvas",
|
||||
"media/SP1-picture-with-pin-numbers.jpg",
|
||||
"IceBreaker FPGA/Pinouts for PMODs.md",
|
||||
"media/pinouts.png",
|
||||
"Pasted image 20250920193353.png",
|
||||
"GameCube/Sp1 physical connector.canvas",
|
||||
"IceBreaker FPGA",
|
||||
"GameCube/SP1.md",
|
||||
"media/Unconfirmed 13874.crdownload",
|
||||
"media",
|
||||
"Environment/Amaranth-Hdl project setup.md",
|
||||
|
2
docs/IceBreaker FPGA/Pinouts for PMODs.md
Normal file
2
docs/IceBreaker FPGA/Pinouts for PMODs.md
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
![[pinouts.png]]
|
BIN
docs/media/pinouts.png
Normal file
BIN
docs/media/pinouts.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 MiB |
1
rebbarb/.gitignore
vendored
1
rebbarb/.gitignore
vendored
@ -1 +1,2 @@
|
||||
build
|
||||
__pycache__
|
||||
|
0
rebbarb/__init__.py
Normal file
0
rebbarb/__init__.py
Normal file
38
rebbarb/debouncer.py
Normal file
38
rebbarb/debouncer.py
Normal file
@ -0,0 +1,38 @@
|
||||
from amaranth.build import Platform
|
||||
from amaranth import *
|
||||
|
||||
class Debouncer(Elaboratable):
|
||||
|
||||
def __init__(self, cycles: int):
|
||||
#signals
|
||||
self.i = Signal()
|
||||
self.o = Signal()
|
||||
|
||||
#state
|
||||
self.count = Signal(range(0, cycles+1), reset=cycles)
|
||||
self.state = Signal()
|
||||
self.prevInValid = Signal()
|
||||
self.prevIn = Signal()
|
||||
|
||||
def elaborate(self, platform: Platform):
|
||||
m = Module()
|
||||
|
||||
with m.If(self.prevInValid):
|
||||
with m.If(self.count == 0):
|
||||
with m.If(self.prevIn ^ self.i):
|
||||
m.d.sync += self.count.eq(self.count.reset)
|
||||
m.d.sync += self.state.eq(self.i)
|
||||
with m.Elif(self.i == self.state):
|
||||
m.d.sync += self.count.eq(self.count.reset)
|
||||
m.d.sync += self.state.eq(self.i)
|
||||
with m.Else():
|
||||
m.d.sync += self.count.eq(self.count - 1)
|
||||
with m.Else():
|
||||
m.d.sync += self.count.eq(0)
|
||||
m.d.sync += self.prevInValid.eq(Const(1))
|
||||
m.d.sync += self.state.eq(self.i)
|
||||
|
||||
m.d.sync += self.prevIn.eq(self.i)
|
||||
m.d.comb += self.o.eq(self.state)
|
||||
|
||||
return m
|
59
rebbarb/pulse_button.py
Normal file
59
rebbarb/pulse_button.py
Normal file
@ -0,0 +1,59 @@
|
||||
from amaranth.build import Platform
|
||||
from amaranth import *
|
||||
|
||||
from debouncer import Debouncer
|
||||
|
||||
class PulseButton(Elaboratable):
|
||||
|
||||
def __init__(self):
|
||||
#signals
|
||||
self.i = Signal()
|
||||
self.o = Signal()
|
||||
|
||||
#state
|
||||
self.last_seen = Signal()
|
||||
self.counter = Signal(range(10000 + 1))
|
||||
|
||||
def elaborate(self, platform: Platform):
|
||||
m = Module()
|
||||
|
||||
debouncer = Debouncer(10000)
|
||||
|
||||
m.submodules += debouncer
|
||||
|
||||
m.d.comb += debouncer.i.eq(self.i)
|
||||
|
||||
with m.If(self.counter != 0):
|
||||
m.d.sync += self.counter.eq(self.counter - 1)
|
||||
with m.Else():
|
||||
with m.If(self.o):
|
||||
m.d.sync += self.o.eq(~self.o)
|
||||
m.d.sync += self.counter.eq(10000)
|
||||
|
||||
with m.If((debouncer.o != self.last_seen) & (debouncer.o == 1)):
|
||||
m.d.sync += self.o.eq(~self.o)
|
||||
|
||||
m.d.sync += self.last_seen.eq(debouncer.o)
|
||||
|
||||
return m
|
||||
|
||||
|
||||
from amaranth.sim import Simulator, Period
|
||||
|
||||
dut = PulseButton()
|
||||
|
||||
async def testbench(ctx):
|
||||
await ctx.tick().repeat(2)
|
||||
ctx.set(dut.i, True)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, False)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, True)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, False)
|
||||
|
||||
sim = Simulator(dut)
|
||||
sim.add_clock(Period(MHz=1))
|
||||
sim.add_testbench(testbench)
|
||||
with sim.write_vcd("PulseButton.vcd"):
|
||||
sim.run_until(Period(MHz=1) * 25)
|
@ -1,20 +1,21 @@
|
||||
from amaranth import *
|
||||
|
||||
class LEDBlinker(Elaboratable):
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
from toggle_button import ToggleButton
|
||||
from pulse_button import PulseButton
|
||||
|
||||
class ReBbaRb(Elaboratable):
|
||||
def setup_pll(self, module, platform):
|
||||
cd_sync = ClockDomain("sync")
|
||||
m.domains += cd_sync
|
||||
module.domains += cd_sync
|
||||
platform.lookup(platform.default_clk).attrs['GLOBAL'] = False
|
||||
|
||||
locked = Signal()
|
||||
pllout = Signal()
|
||||
|
||||
m.submodules.pll = Instance("SB_PLL40_PAD",
|
||||
module.submodules.pll = Instance("SB_PLL40_PAD",
|
||||
p_FEEDBACK_PATH = "SIMPLE",
|
||||
p_DIVR = 0,
|
||||
p_DIVF = 7,
|
||||
p_DIVF = 5,
|
||||
p_DIVQ = 1,
|
||||
p_FILTER_RANGE = 1,
|
||||
|
||||
@ -25,6 +26,11 @@ class LEDBlinker(Elaboratable):
|
||||
o_PLLOUTCORE = cd_sync.clk
|
||||
)
|
||||
|
||||
def elaborate(self, platform):
|
||||
m = Module()
|
||||
|
||||
self.setup_pll(m, platform)
|
||||
|
||||
ledr0 = platform.request("led_r")
|
||||
ledg0 = platform.request("led_g")
|
||||
|
||||
@ -34,13 +40,34 @@ class LEDBlinker(Elaboratable):
|
||||
ledg3 = platform.request("led_g", 3)
|
||||
ledg4 = platform.request("led_g", 4)
|
||||
|
||||
half_freq = int(42e6 // 2)
|
||||
timer = Signal(range(half_freq + 1))
|
||||
btn1 = platform.request("button", 1)
|
||||
btn2 = platform.request("button", 2)
|
||||
btn3 = platform.request("button", 3)
|
||||
|
||||
disabled = Signal()
|
||||
|
||||
toggle1 = ToggleButton()
|
||||
m.d.comb += toggle1.i.eq(btn2.i)
|
||||
m.d.comb += disabled.eq(toggle1.o)
|
||||
m.submodules += toggle1
|
||||
|
||||
pulse1 = PulseButton()
|
||||
m.d.comb += pulse1.i.eq(btn1.i)
|
||||
m.submodules += pulse1
|
||||
|
||||
pulse2 = PulseButton()
|
||||
m.d.comb += pulse2.i.eq(btn3.i)
|
||||
m.submodules += pulse2
|
||||
|
||||
init_half_freq = int(36e6 // 2)
|
||||
half_freq = Signal(range((init_half_freq + 1) * 32), init=init_half_freq // 2)
|
||||
timer = Signal(range((init_half_freq + 1) * 32))
|
||||
|
||||
init = Signal()
|
||||
|
||||
with m.If(init == 0):
|
||||
m.d.sync += ledg0.o.eq(255)
|
||||
m.d.sync += half_freq.eq(init_half_freq)
|
||||
m.d.sync += init.eq(1)
|
||||
|
||||
with m.If(timer == half_freq):
|
||||
@ -48,13 +75,151 @@ class LEDBlinker(Elaboratable):
|
||||
m.d.sync += ledg0.o.eq(~ledg0.o)
|
||||
m.d.sync += timer.eq(0)
|
||||
with m.Else():
|
||||
m.d.sync += timer.eq(timer + 1)
|
||||
with m.If(~disabled):
|
||||
m.d.sync += timer.eq(timer + 1)
|
||||
|
||||
with m.If(pulse1.o):
|
||||
m.d.sync += half_freq.eq(half_freq << 1)
|
||||
m.d.sync += timer.eq(0)
|
||||
|
||||
with m.If(pulse2.o):
|
||||
m.d.sync += half_freq.eq(half_freq >> 1)
|
||||
m.d.sync += timer.eq(0)
|
||||
|
||||
return m
|
||||
|
||||
from amaranth_boards.icebreaker import ICEBreakerPlatform
|
||||
from amaranth.vendor import SiliconBluePlatform;
|
||||
import os
|
||||
import subprocess
|
||||
from amaranth.build import *
|
||||
from amaranth.vendor import LatticeICE40Platform
|
||||
|
||||
platform = ICEBreakerPlatform()
|
||||
platform.add_resources(platform.break_off_pmod)
|
||||
platform.build(LEDBlinker(), do_program=True, verbose=True, nextpnr_opts='--freq 48')
|
||||
def _SplitResources(*args, pins, invert=False, conn=None, attrs=None, default_name, dir):
|
||||
assert isinstance(pins, (str, list, dict))
|
||||
|
||||
if isinstance(pins, str):
|
||||
pins = pins.split()
|
||||
if isinstance(pins, list):
|
||||
pins = dict(enumerate(pins))
|
||||
|
||||
resources = []
|
||||
for number, pin in pins.items():
|
||||
ios = [Pins(pin, dir=dir, invert=invert, conn=conn)]
|
||||
if attrs is not None:
|
||||
ios.append(attrs)
|
||||
resources.append(Resource.family(*args, number, default_name=default_name, ios=ios))
|
||||
return resources
|
||||
|
||||
def UARTResource(*args, rx, tx, rts=None, cts=None, dtr=None, dsr=None, dcd=None, ri=None,
|
||||
conn=None, attrs=None, role=None):
|
||||
if any(line is not None for line in (rts, cts, dtr, dsr, dcd, ri)):
|
||||
assert role in ("dce", "dte")
|
||||
if role == "dte":
|
||||
dce_to_dte = "i"
|
||||
dte_to_dce = "o"
|
||||
else:
|
||||
dce_to_dte = "o"
|
||||
dte_to_dce = "i"
|
||||
|
||||
io = []
|
||||
io.append(Subsignal("rx", Pins(rx, dir="i", conn=conn, assert_width=1)))
|
||||
io.append(Subsignal("tx", Pins(tx, dir="o", conn=conn, assert_width=1)))
|
||||
if rts is not None:
|
||||
io.append(Subsignal("rts", Pins(rts, dir=dte_to_dce, conn=conn, assert_width=1)))
|
||||
if cts is not None:
|
||||
io.append(Subsignal("cts", Pins(cts, dir=dce_to_dte, conn=conn, assert_width=1)))
|
||||
if dtr is not None:
|
||||
io.append(Subsignal("dtr", Pins(dtr, dir=dte_to_dce, conn=conn, assert_width=1)))
|
||||
if dsr is not None:
|
||||
io.append(Subsignal("dsr", Pins(dsr, dir=dce_to_dte, conn=conn, assert_width=1)))
|
||||
if dcd is not None:
|
||||
io.append(Subsignal("dcd", Pins(dcd, dir=dce_to_dte, conn=conn, assert_width=1)))
|
||||
if ri is not None:
|
||||
io.append(Subsignal("ri", Pins(ri, dir=dce_to_dte, conn=conn, assert_width=1)))
|
||||
if attrs is not None:
|
||||
io.append(attrs)
|
||||
return Resource.family(*args, default_name="uart", ios=io)
|
||||
|
||||
def SPIFlashResources(*args, cs_n, clk, copi, cipo, wp_n=None, hold_n=None,
|
||||
conn=None, attrs=None):
|
||||
resources = []
|
||||
|
||||
io_all = []
|
||||
if attrs is not None:
|
||||
io_all.append(attrs)
|
||||
io_all.append(Subsignal("cs", PinsN(cs_n, dir="o", conn=conn)))
|
||||
io_all.append(Subsignal("clk", Pins(clk, dir="o", conn=conn, assert_width=1)))
|
||||
|
||||
io_1x = list(io_all)
|
||||
io_1x.append(Subsignal("copi", Pins(copi, dir="o", conn=conn, assert_width=1)))
|
||||
io_1x.append(Subsignal("cipo", Pins(cipo, dir="i", conn=conn, assert_width=1)))
|
||||
if wp_n is not None and hold_n is not None:
|
||||
io_1x.append(Subsignal("wp", PinsN(wp_n, dir="o", conn=conn, assert_width=1)))
|
||||
io_1x.append(Subsignal("hold", PinsN(hold_n, dir="o", conn=conn, assert_width=1)))
|
||||
resources.append(Resource.family(*args, default_name="spi_flash", ios=io_1x,
|
||||
name_suffix="1x"))
|
||||
|
||||
io_2x = list(io_all)
|
||||
io_2x.append(Subsignal("dq", Pins(" ".join([copi, cipo]), dir="io", conn=conn,
|
||||
assert_width=2)))
|
||||
resources.append(Resource.family(*args, default_name="spi_flash", ios=io_2x,
|
||||
name_suffix="2x"))
|
||||
|
||||
if wp_n is not None and hold_n is not None:
|
||||
io_4x = list(io_all)
|
||||
io_4x.append(Subsignal("dq", Pins(" ".join([copi, cipo, wp_n, hold_n]), dir="io", conn=conn,
|
||||
assert_width=4)))
|
||||
resources.append(Resource.family(*args, default_name="spi_flash", ios=io_4x,
|
||||
name_suffix="4x"))
|
||||
|
||||
return resources
|
||||
|
||||
def LEDResources(*args, **kwargs):
|
||||
return _SplitResources(*args, **kwargs, default_name="led", dir="o")
|
||||
|
||||
def ButtonResources(*args, **kwargs):
|
||||
return _SplitResources(*args, **kwargs, default_name="button", dir="i")
|
||||
|
||||
class IceBreakerPlatform(LatticeICE40Platform):
|
||||
device = "iCE40UP5K"
|
||||
package = "SG48"
|
||||
default_clk = "clk12"
|
||||
resources = [
|
||||
Resource("clk12", 0, Pins("35", dir="i"), Clock(12e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
|
||||
|
||||
*LEDResources(pins="11 37", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
# Semantic aliases
|
||||
Resource("led_r", 0, PinsN("11", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("led_g", 0, PinsN("37", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
|
||||
*ButtonResources(pins="10", invert=True, attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
|
||||
UARTResource(0, rx="6", tx="9", attrs=Attrs(IO_STANDARD="SB_LVTTL", PULLUP=1)),
|
||||
|
||||
*SPIFlashResources(0, cs_n="16", clk="15", copi="14", cipo="17", wp_n="12", hold_n="13", attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
|
||||
*LEDResources(pins={2: "7", 3: "1", 4: "2", 5: "8", 6: "3"}, conn=("pmod", 0), attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
# Semantic aliases
|
||||
Resource("led_r", 1, Pins("7", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("led_g", 1, Pins("1", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("led_g", 2, Pins("2", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("led_g", 3, Pins("8", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
Resource("led_g", 4, Pins("3", dir="o", conn=("pmod", 0)), Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
*ButtonResources(pins={1: "9", 2: "4", 3: "10"}, conn=("pmod", 0), attrs=Attrs(IO_STANDARD="SB_LVCMOS")),
|
||||
]
|
||||
|
||||
connectors = [
|
||||
Connector("pmod", 0, " 4 2 47 45 - - 3 48 46 44 - -"), # PMOD1A
|
||||
Connector("pmod", 1, "43 38 34 31 - - 42 36 32 28 - -"), # PMOD1B
|
||||
Connector("pmod", 2, "27 25 21 19 - - 26 23 20 18 - -"), # PMOD2
|
||||
]
|
||||
|
||||
def toolchain_program(self, products, name):
|
||||
iceprog = os.environ.get("ICEPROG", "iceprog")
|
||||
with products.extract("{}.bin".format(name)) as bitstream_filename:
|
||||
subprocess.check_call([iceprog, bitstream_filename])
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
platform = IceBreakerPlatform()
|
||||
platform.build(ReBbaRb(), do_program=True, verbose=True)
|
51
rebbarb/toggle_button.py
Normal file
51
rebbarb/toggle_button.py
Normal file
@ -0,0 +1,51 @@
|
||||
from amaranth.build import Platform
|
||||
from amaranth import *
|
||||
|
||||
from debouncer import Debouncer
|
||||
|
||||
class ToggleButton(Elaboratable):
|
||||
|
||||
def __init__(self):
|
||||
#signals
|
||||
self.i = Signal()
|
||||
self.o = Signal()
|
||||
|
||||
#state
|
||||
self.last_seen = Signal()
|
||||
|
||||
def elaborate(self, platform: Platform):
|
||||
m = Module()
|
||||
|
||||
debouncer = Debouncer(10000)
|
||||
|
||||
m.submodules += debouncer
|
||||
|
||||
m.d.comb += debouncer.i.eq(self.i)
|
||||
|
||||
with m.If((debouncer.o != self.last_seen) & (debouncer.o == 1)):
|
||||
m.d.sync += self.o.eq(~self.o)
|
||||
|
||||
m.d.sync += self.last_seen.eq(debouncer.o)
|
||||
|
||||
return m
|
||||
|
||||
|
||||
from amaranth.sim import Simulator, Period
|
||||
|
||||
dut = ToggleButton()
|
||||
|
||||
async def testbench(ctx):
|
||||
await ctx.tick().repeat(2)
|
||||
ctx.set(dut.i, True)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, False)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, True)
|
||||
await ctx.tick().repeat(5)
|
||||
ctx.set(dut.i, False)
|
||||
|
||||
sim = Simulator(dut)
|
||||
sim.add_clock(Period(MHz=1))
|
||||
sim.add_testbench(testbench)
|
||||
with sim.write_vcd("ToggleButton.vcd"):
|
||||
sim.run_until(Period(MHz=1) * 25)
|
@ -1,4 +1,4 @@
|
||||
amaranth==0.5.7
|
||||
amaranth @ git+https://github.com/amaranth-lang/amaranth@main
|
||||
amaranth-boards @ git+https://github.com/amaranth-lang/amaranth-boards.git@7e24efe2f6e95afddd0c1b56f1a9423c48caa472
|
||||
amaranth-yosys==0.50.0.0.post115
|
||||
importlib_resources==6.5.2
|
||||
|
Loading…
x
Reference in New Issue
Block a user