Restructured Amaranth code to be able to import sibling modules
This commit is contained in:
1 parent
7780e14887
commit
4a2d2b4881
91 files changed
+518
-356
No files matched your search
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
*.vcd
|
*.vcd
|
||||||
*.v
|
*.v
|
||||||
**/__pycache__
|
**/__pycache__
|
||||||
|
venv
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
from amaranth import *
|
|
||||||
|
|
||||||
class UpCounter(Elaboratable):
|
|
||||||
"""
|
|
||||||
A 16-bit up counter with a fixed limit.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
limit : int
|
|
||||||
The value at which the counter overflows.
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
en : Signal, in
|
|
||||||
The counter is incremented if ``en`` is asserted, and retains
|
|
||||||
its value otherwise.
|
|
||||||
ovf : Signal, out
|
|
||||||
``ovf`` is asserted when the counter reaches its limit.
|
|
||||||
"""
|
|
||||||
def __init__(self, limit):
|
|
||||||
self.limit = limit
|
|
||||||
|
|
||||||
# Ports
|
|
||||||
self.en = Signal()
|
|
||||||
self.ovf = Signal()
|
|
||||||
|
|
||||||
# State
|
|
||||||
self.count = Signal(16)
|
|
||||||
|
|
||||||
def elaborate(self, platform):
|
|
||||||
m = Module()
|
|
||||||
|
|
||||||
m.d.comb += self.ovf.eq(self.count == self.limit)
|
|
||||||
|
|
||||||
with m.If(self.en):
|
|
||||||
with m.If(self.ovf):
|
|
||||||
m.d.sync += self.count.eq(0)
|
|
||||||
with m.Else():
|
|
||||||
m.d.sync += self.count.eq(self.count + 1)
|
|
||||||
|
|
||||||
return m
|
|
||||||
|
|
||||||
from amaranth.sim import Simulator
|
|
||||||
|
|
||||||
dut = UpCounter(25)
|
|
||||||
def bench():
|
|
||||||
# Disabled counter should not overflow.
|
|
||||||
yield dut.en.eq(0)
|
|
||||||
for _ in range(30):
|
|
||||||
yield
|
|
||||||
assert not (yield dut.ovf)
|
|
||||||
|
|
||||||
# Once enabled, the counter should overflow in 25 cycles.
|
|
||||||
yield dut.en.eq(1)
|
|
||||||
for _ in range(25):
|
|
||||||
yield
|
|
||||||
assert not (yield dut.ovf)
|
|
||||||
yield
|
|
||||||
assert (yield dut.ovf)
|
|
||||||
|
|
||||||
# The overflow should clear in one cycle.
|
|
||||||
yield
|
|
||||||
assert not (yield dut.ovf)
|
|
||||||
|
|
||||||
|
|
||||||
sim = Simulator(dut)
|
|
||||||
sim.add_clock(1e-6) # 1 MHz
|
|
||||||
sim.add_sync_process(bench)
|
|
||||||
with sim.write_vcd("up_counter.vcd"):
|
|
||||||
sim.run()
|
|
||||||
|
|
||||||
from amaranth_boards.icebreaker import *
|
|
||||||
|
|
||||||
ICEBreakerPlatform().build(UpCounter(25), do_program=True)
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
|
|
||||||
import enum
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
|
|
||||||
from amaranth.build import Platform
|
|
||||||
from amaranth import *
|
|
||||||
from amaranth.sim import Simulator
|
|
||||||
|
|
||||||
class ClockState(enum.Enum):
|
|
||||||
LOW = 0
|
|
||||||
FALLING = 1
|
|
||||||
HIGH = 2
|
|
||||||
RISING = 3
|
|
||||||
|
|
||||||
class ExiClock(Elaboratable):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
# Ports
|
|
||||||
self.exiClk = Signal()
|
|
||||||
self.exiClkState = Signal(2)
|
|
||||||
|
|
||||||
# State
|
|
||||||
self.prevExiClkValid = Signal()
|
|
||||||
self.prevExiClk = Signal()
|
|
||||||
self.prevExiClkState = Signal(2)
|
|
||||||
|
|
||||||
|
|
||||||
def elaborate(self, platform: Platform):
|
|
||||||
m = Module()
|
|
||||||
|
|
||||||
with m.If(self.prevExiClkValid):
|
|
||||||
with m.If(self.prevExiClkState == ClockState.FALLING):
|
|
||||||
m.d.comb += self.exiClkState.eq(ClockState.LOW)
|
|
||||||
with m.Elif(self.prevExiClkState == ClockState.RISING):
|
|
||||||
m.d.comb += self.exiClkState.eq(ClockState.HIGH)
|
|
||||||
with m.Else():
|
|
||||||
with m.If(self.prevExiClk ^ self.exiClk):
|
|
||||||
m.d.comb += self.exiClkState.eq(Cat(1, self.exiClk))
|
|
||||||
with m.Else():
|
|
||||||
m.d.comb += self.exiClkState.eq(Cat(0, self.exiClk))
|
|
||||||
|
|
||||||
m.d.sync += self.prevExiClkState.eq(self.exiClkState)
|
|
||||||
|
|
||||||
m.d.sync += self.prevExiClk.eq(self.exiClk)
|
|
||||||
m.d.sync += self.prevExiClkValid.eq(1)
|
|
||||||
|
|
||||||
return m
|
|
||||||
|
|
||||||
#####
|
|
||||||
# TestBench
|
|
||||||
#####
|
|
||||||
class TestBench:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def FlipExiClock(self, dut):
|
|
||||||
yield dut.exiClk.eq(~dut.exiClk)
|
|
||||||
|
|
||||||
def clockTest(self):
|
|
||||||
dut = self.dut
|
|
||||||
|
|
||||||
yield dut.exiClk.eq(0)
|
|
||||||
yield
|
|
||||||
yield from self.FlipExiClock(dut)
|
|
||||||
yield
|
|
||||||
assert (yield dut.exiClkState) == ClockState.RISING.value
|
|
||||||
yield
|
|
||||||
assert (yield dut.exiClkState) == ClockState.HIGH.value
|
|
||||||
yield
|
|
||||||
yield from self.FlipExiClock(dut)
|
|
||||||
yield
|
|
||||||
assert (yield dut.exiClkState) == ClockState.FALLING.value
|
|
||||||
yield
|
|
||||||
assert (yield dut.exiClkState) == ClockState.LOW.value
|
|
||||||
yield
|
|
||||||
|
|
||||||
|
|
||||||
def simulate(self):
|
|
||||||
self.dut = ExiClock()
|
|
||||||
|
|
||||||
sim = Simulator(self.dut)
|
|
||||||
sim.add_clock(1e-6) # 1 MHz
|
|
||||||
sim.add_sync_process(self.clockTest)
|
|
||||||
|
|
||||||
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ExiClock.vcd"):
|
|
||||||
sim.run()
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Main portion
|
|
||||||
#####
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if(len(sys.argv) == 2):
|
|
||||||
|
|
||||||
if sys.argv[1] == "s":
|
|
||||||
bench = TestBench()
|
|
||||||
bench.simulate()
|
|
||||||
|
|
||||||
if sys.argv[1] == "v":
|
|
||||||
mod = ExiClock()
|
|
||||||
with open(os.path.dirname(os.path.abspath(__file__)) + "/ExiClock.v", "w") as f:
|
|
||||||
f.write(verilog.convert(mod, ports=[mod.exiClk, mod.exiClkState]))
|
|
||||||
|
|
||||||
else:
|
|
||||||
bench = TestBench()
|
|
||||||
bench.simulate()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
from amaranth import *
|
|
||||||
|
|
||||||
class LEDBlinker(Elaboratable):
|
|
||||||
def elaborate(self, platform):
|
|
||||||
m = Module()
|
|
||||||
|
|
||||||
led = platform.request("led")
|
|
||||||
|
|
||||||
half_freq = int(platform.default_clk_frequency // 2)
|
|
||||||
timer = Signal(range(half_freq + 1))
|
|
||||||
|
|
||||||
with m.If(timer == half_freq):
|
|
||||||
m.d.sync += led.eq(~led)
|
|
||||||
m.d.sync += timer.eq(0)
|
|
||||||
with m.Else():
|
|
||||||
m.d.sync += timer.eq(timer + 1)
|
|
||||||
|
|
||||||
return m
|
|
||||||
|
|
||||||
from amaranth_boards.icebreaker import *
|
|
||||||
|
|
||||||
ICEBreakerPlatform().build(LEDBlinker(), do_program=True)
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
from amaranth.build import Platform
|
||||||
|
from amaranth import *
|
||||||
|
|
||||||
|
class Debouncer(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self, cycles: int):
|
||||||
|
#signals
|
||||||
|
self.input = Signal()
|
||||||
|
self.output = 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.input):
|
||||||
|
m.d.sync += self.count.eq(self.count.reset)
|
||||||
|
m.d.sync += self.state.eq(self.input)
|
||||||
|
with m.Elif(self.input == self.state):
|
||||||
|
m.d.sync += self.count.eq(self.count.reset)
|
||||||
|
m.d.sync += self.state.eq(self.input)
|
||||||
|
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.input)
|
||||||
|
|
||||||
|
m.d.sync += self.prevIn.eq(self.input)
|
||||||
|
m.d.comb += self.output.eq(self.state)
|
||||||
|
|
||||||
|
return m
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
import enum
|
||||||
|
|
||||||
|
from amaranth.build import Platform
|
||||||
|
from amaranth import *
|
||||||
|
|
||||||
|
class ClockState(enum.Enum):
|
||||||
|
LOW = 0
|
||||||
|
FALLING = 1
|
||||||
|
HIGH = 2
|
||||||
|
RISING = 3
|
||||||
|
|
||||||
|
class ExiClock(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Ports
|
||||||
|
self.exiClk = Signal()
|
||||||
|
self.exiClkState = Signal(2)
|
||||||
|
|
||||||
|
# State
|
||||||
|
self.prevExiClkValid = Signal()
|
||||||
|
self.prevExiClk = Signal()
|
||||||
|
self.prevExiClkState = Signal(2)
|
||||||
|
|
||||||
|
|
||||||
|
def elaborate(self, platform: Platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
with m.If(self.prevExiClkValid):
|
||||||
|
with m.If(self.prevExiClkState == ClockState.FALLING):
|
||||||
|
m.d.comb += self.exiClkState.eq(ClockState.LOW)
|
||||||
|
with m.Elif(self.prevExiClkState == ClockState.RISING):
|
||||||
|
m.d.comb += self.exiClkState.eq(ClockState.HIGH)
|
||||||
|
with m.Else():
|
||||||
|
with m.If(self.prevExiClk ^ self.exiClk):
|
||||||
|
m.d.comb += self.exiClkState.eq(Cat(1, self.exiClk))
|
||||||
|
with m.Else():
|
||||||
|
m.d.comb += self.exiClkState.eq(Cat(0, self.exiClk))
|
||||||
|
|
||||||
|
m.d.sync += self.prevExiClkState.eq(self.exiClkState)
|
||||||
|
|
||||||
|
m.d.sync += self.prevExiClk.eq(self.exiClk)
|
||||||
|
m.d.sync += self.prevExiClkValid.eq(1)
|
||||||
|
|
||||||
|
return m
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from amaranth.build import Platform
|
||||||
|
from amaranth import *
|
||||||
|
|
||||||
|
from ExiDecoders.GetId import GetId
|
||||||
|
|
||||||
|
class ExiDecoder(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
#ports
|
||||||
|
self.request = Signal(16)
|
||||||
|
self.request_type = Signal(1)
|
||||||
|
#state
|
||||||
|
|
||||||
|
def elaborate(self, platform: Platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
getId = GetId()
|
||||||
|
m.submodules += getId
|
||||||
|
|
||||||
|
m.d.comb += getId.request.eq(self.request)
|
||||||
|
m.d.comb += self.request_type[0].eq(getId.isGetId)
|
||||||
|
|
||||||
|
return m
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
from ReBba.Components.ShiftRegister import ShiftRegister
|
||||||
|
from ReBba.Components.ExiClock import ClockState
|
||||||
|
|
||||||
|
from amaranth import Const, Elaboratable, Module, Signal
|
||||||
|
from amaranth.build import Platform
|
||||||
|
|
||||||
|
|
||||||
|
class ExiRequest(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
#ports
|
||||||
|
self.request = Signal(16)
|
||||||
|
self.nen = Signal(1)
|
||||||
|
self.rst = Signal(1)
|
||||||
|
self.exiClkState = Signal(2)
|
||||||
|
self.exiIn = Signal(1)
|
||||||
|
self.requestComplete = Signal(1)
|
||||||
|
|
||||||
|
#state
|
||||||
|
self.disableShift = Signal(1, reset=0)
|
||||||
|
self.shiftRegister = ShiftRegister(16)
|
||||||
|
self.clockCount = Signal(5, reset=0)
|
||||||
|
|
||||||
|
def elaborate(self, platform: Platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
m.submodules += self.shiftRegister
|
||||||
|
|
||||||
|
m.d.comb += self.request.eq(self.shiftRegister.data)
|
||||||
|
m.d.comb += self.shiftRegister.inb.eq(self.exiIn)
|
||||||
|
m.d.comb += self.shiftRegister.exiClkState.eq(self.exiClkState)
|
||||||
|
m.d.comb += self.shiftRegister.nen.eq(self.disableShift)
|
||||||
|
|
||||||
|
with m.If(~self.nen):
|
||||||
|
with m.If(self.clockCount != 16):
|
||||||
|
with m.If(self.exiClkState == ClockState.FALLING):
|
||||||
|
m.d.sync += self.clockCount.eq(self.clockCount + 1)
|
||||||
|
|
||||||
|
with m.If(self.clockCount == 16):
|
||||||
|
m.d.comb += self.disableShift.eq(Const(1))
|
||||||
|
m.d.comb += self.requestComplete.eq(Const(1))
|
||||||
|
|
||||||
|
with m.If(self.rst):
|
||||||
|
m.d.comb += self.request.eq(self.request.reset)
|
||||||
|
m.d.sync += self.clockCount.eq(self.clockCount.reset)
|
||||||
|
m.d.comb += self.disableShift.eq(self.disableShift.reset)
|
||||||
|
|
||||||
|
m.d.comb += self.shiftRegister.rst.eq(self.rst)
|
||||||
|
|
||||||
|
return m
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
from ReBba.Components.ExiClock import ClockState
|
||||||
|
|
||||||
|
from amaranth import *
|
||||||
|
from amaranth.build import Platform
|
||||||
|
|
||||||
|
class ShiftRegister(Elaboratable):
|
||||||
|
def __init__(self, width):
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
self.nen = Signal()
|
||||||
|
self.exiClkState = Signal(2)
|
||||||
|
self.rst = Signal()
|
||||||
|
self.inb = Signal()
|
||||||
|
self.data = Signal(self.width, reset=0)
|
||||||
|
|
||||||
|
def elaborate(self, platform: Platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
with m.If(self.rst):
|
||||||
|
m.d.sync += self.data.eq(self.data.reset)
|
||||||
|
|
||||||
|
with m.If(~self.nen):
|
||||||
|
with m.If(self.exiClkState == ClockState.FALLING):
|
||||||
|
m.d.sync += self.data.eq(self.data.shift_left(1) | self.inb )
|
||||||
|
|
||||||
|
return m
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from amaranth.build import Platform
|
||||||
|
from amaranth import Signal, Const, Module, Elaboratable
|
||||||
|
|
||||||
|
class GetId(Elaboratable):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.request = Signal(16)
|
||||||
|
self.isGetId = Signal()
|
||||||
|
pass
|
||||||
|
|
||||||
|
def elaborate(self, platform: Platform):
|
||||||
|
m = Module()
|
||||||
|
|
||||||
|
with m.If(self.request == 0):
|
||||||
|
m.d.comb += self.isGetId.eq(Const(1))
|
||||||
|
with m.Else():
|
||||||
|
m.d.comb += self.isGetId.eq(Const(0))
|
||||||
|
|
||||||
|
return m
|
||||||
@@ -7,7 +7,9 @@ from amaranth.sim import Simulator
|
|||||||
from amaranth_boards.icebreaker import *
|
from amaranth_boards.icebreaker import *
|
||||||
|
|
||||||
from ExiClock import ExiClock
|
from ExiClock import ExiClock
|
||||||
from ShiftRegister import ShiftRegister
|
from ExiRequest import ExiRequest
|
||||||
|
from Debouncer import Debouncer
|
||||||
|
from ExiDecoder import ExiDecoder
|
||||||
|
|
||||||
class ReBba(Elaboratable):
|
class ReBba(Elaboratable):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -16,6 +18,9 @@ class ReBba(Elaboratable):
|
|||||||
def elaborate(self, platform: Platform):
|
def elaborate(self, platform: Platform):
|
||||||
m = Module()
|
m = Module()
|
||||||
|
|
||||||
|
uledg = platform.request("led_g", 0)
|
||||||
|
uledr = platform.request("led_r", 0)
|
||||||
|
|
||||||
led1 = platform.request("led_g", 1)
|
led1 = platform.request("led_g", 1)
|
||||||
led2 = platform.request("led_g", 4)
|
led2 = platform.request("led_g", 4)
|
||||||
led3 = platform.request("led_g", 2)
|
led3 = platform.request("led_g", 2)
|
||||||
@@ -26,23 +31,36 @@ class ReBba(Elaboratable):
|
|||||||
btn2 = platform.request("button", 2)
|
btn2 = platform.request("button", 2)
|
||||||
btn3 = platform.request("button", 3)
|
btn3 = platform.request("button", 3)
|
||||||
|
|
||||||
|
debounce1 = Debouncer(10000)
|
||||||
|
m.submodules += debounce1
|
||||||
|
|
||||||
|
m.d.comb += debounce1.input.eq(btn3)
|
||||||
|
|
||||||
exiClk = ExiClock()
|
exiClk = ExiClock()
|
||||||
m.submodules += exiClk
|
m.submodules += exiClk
|
||||||
sr = ShiftRegister(5)
|
|
||||||
m.submodules += sr
|
m.d.comb += exiClk.exiClk.eq(debounce1.output)
|
||||||
|
|
||||||
|
exiReq = ExiRequest()
|
||||||
|
m.submodules += exiReq
|
||||||
|
|
||||||
m.d.comb += led1.eq(sr.data[0])
|
m.d.comb += exiReq.exiClkState.eq(exiClk.exiClkState)
|
||||||
m.d.comb += led2.eq(sr.data[1])
|
m.d.comb += exiReq.exiIn.eq(btn1)
|
||||||
m.d.comb += led3.eq(sr.data[2])
|
m.d.comb += exiReq.rst.eq(btn2)
|
||||||
m.d.comb += led4.eq(sr.data[3])
|
|
||||||
m.d.comb += led5.eq(sr.data[4])
|
|
||||||
|
|
||||||
m.d.comb += exiClk.exiClk.eq(btn3)
|
m.d.comb += led1.eq(exiReq.request[0])
|
||||||
|
m.d.comb += led2.eq(exiReq.request[1])
|
||||||
|
m.d.comb += led3.eq(exiReq.request[2])
|
||||||
|
m.d.comb += led4.eq(exiReq.request[3])
|
||||||
|
|
||||||
m.d.comb += sr.rst.eq(btn2)
|
m.d.comb += led5.eq(exiReq.requestComplete)
|
||||||
m.d.comb += sr.inb.eq(btn1)
|
|
||||||
m.d.comb += sr.nen.eq(Const(0))
|
exiDec = ExiDecoder()
|
||||||
m.d.comb += sr.exiClkState.eq(exiClk.exiClkState)
|
m.submodules += exiDec
|
||||||
|
|
||||||
|
m.d.comb += exiDec.request.eq(exiReq.request)
|
||||||
|
m.d.comb += uledr.eq(exiDec.request_type[0])
|
||||||
|
m.d.comb += uledg.eq(exiReq.requestComplete)
|
||||||
|
|
||||||
return m
|
return m
|
||||||
|
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
from ReBba.Components.Debouncer import Debouncer
|
||||||
|
|
||||||
|
from amaranth import Const
|
||||||
|
from amaranth.sim import Simulator
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class TestBench:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def holdTest(self):
|
||||||
|
dut = self.dut
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
|
||||||
|
yield dut.input.eq(Const(1))
|
||||||
|
yield
|
||||||
|
yield dut.input.eq(Const(0))
|
||||||
|
yield
|
||||||
|
|
||||||
|
for _ in range(5):
|
||||||
|
assert(yield(dut.output) == 1)
|
||||||
|
yield
|
||||||
|
|
||||||
|
yield dut.input.eq(Const(1))
|
||||||
|
yield
|
||||||
|
yield dut.input.eq(Const(0))
|
||||||
|
yield
|
||||||
|
|
||||||
|
for _ in range(16):
|
||||||
|
assert(yield(dut.output) == 1)
|
||||||
|
yield
|
||||||
|
|
||||||
|
assert(yield(dut.output) == 0)
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
self.dut = Debouncer(15)
|
||||||
|
|
||||||
|
sim = Simulator(self.dut)
|
||||||
|
sim.add_clock(1e-6) # 1 MHz
|
||||||
|
sim.add_sync_process(self.holdTest)
|
||||||
|
|
||||||
|
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/Debouncer.vcd"):
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bench = TestBench()
|
||||||
|
bench.simulate()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
from ReBba.Components.ExiClock import ClockState, ExiClock
|
||||||
|
from ReBba.TestBenches.SimHelpers.ExiSimHelper import exiClockCycle
|
||||||
|
|
||||||
|
from amaranth.sim import Simulator
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class TestBench:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def FlipExiClock(self, dut):
|
||||||
|
yield dut.exiClk.eq(~dut.exiClk)
|
||||||
|
|
||||||
|
def clockTest(self):
|
||||||
|
dut = self.dut
|
||||||
|
|
||||||
|
yield dut.exiClk.eq(0)
|
||||||
|
yield
|
||||||
|
yield from self.FlipExiClock(dut)
|
||||||
|
yield
|
||||||
|
assert (yield dut.exiClkState) == ClockState.RISING.value
|
||||||
|
yield
|
||||||
|
assert (yield dut.exiClkState) == ClockState.HIGH.value
|
||||||
|
yield
|
||||||
|
yield from self.FlipExiClock(dut)
|
||||||
|
yield
|
||||||
|
assert (yield dut.exiClkState) == ClockState.FALLING.value
|
||||||
|
yield
|
||||||
|
assert (yield dut.exiClkState) == ClockState.LOW.value
|
||||||
|
yield
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
self.dut = ExiClock()
|
||||||
|
|
||||||
|
sim = Simulator(self.dut)
|
||||||
|
sim.add_clock(1e-6) # 1 MHz
|
||||||
|
sim.add_sync_process(self.clockTest)
|
||||||
|
|
||||||
|
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ExiClock.vcd"):
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bench = TestBench()
|
||||||
|
bench.simulate()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
from ReBba.Components.ExiRequest import ExiRequest
|
||||||
|
|
||||||
|
from SimHelpers.ExiSimHelper import exiClockCycle, resetDut
|
||||||
|
|
||||||
|
from amaranth import Const
|
||||||
|
from amaranth.sim import Simulator
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class TestBench:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def requestTest(self):
|
||||||
|
dut = self.dut
|
||||||
|
|
||||||
|
yield dut.nen.eq(Const(0))
|
||||||
|
|
||||||
|
def afterLow0():
|
||||||
|
assert((yield dut.requestComplete) == 0)
|
||||||
|
|
||||||
|
def afterLow1():
|
||||||
|
assert((yield dut.requestComplete) == 1)
|
||||||
|
|
||||||
|
|
||||||
|
for i in range(15):
|
||||||
|
yield dut.exiIn.eq(~dut.exiIn)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterLow=afterLow0)
|
||||||
|
|
||||||
|
yield dut.exiIn.eq(~dut.exiIn)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterLow=afterLow1)
|
||||||
|
|
||||||
|
assert((yield dut.requestComplete) == 1)
|
||||||
|
yield from exiClockCycle(dut.exiClkState)
|
||||||
|
assert((yield dut.requestComplete) == 1)
|
||||||
|
|
||||||
|
yield from resetDut(dut.rst)
|
||||||
|
|
||||||
|
for i in range(15):
|
||||||
|
yield dut.exiIn.eq(~dut.exiIn)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterLow=afterLow0)
|
||||||
|
|
||||||
|
yield dut.exiIn.eq(~dut.exiIn)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterLow=afterLow1)
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
self.dut = ExiRequest()
|
||||||
|
|
||||||
|
sim = Simulator(self.dut)
|
||||||
|
sim.add_clock(1e-6) # 1 MHz
|
||||||
|
sim.add_sync_process(self.requestTest)
|
||||||
|
|
||||||
|
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ExiRequest.vcd"):
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
#####
|
||||||
|
# Main portion
|
||||||
|
#####
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bench = TestBench()
|
||||||
|
bench.simulate()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
from amaranth import Elaboratable
|
||||||
|
from ReBba.Components.ShiftRegister import ShiftRegister
|
||||||
|
|
||||||
|
from ReBba.TestBenches.SimHelpers.ExiSimHelper import exiClockCycle
|
||||||
|
|
||||||
|
from amaranth.sim import Simulator
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class TestBench:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def enabled_test(self):
|
||||||
|
dut = self.dut
|
||||||
|
|
||||||
|
def afterAny():
|
||||||
|
assert not (yield dut.data)
|
||||||
|
|
||||||
|
# Disabled ShiftRegister should not Change.
|
||||||
|
yield dut.nen.eq(1)
|
||||||
|
for _ in range(10):
|
||||||
|
yield dut.inb.eq(~dut.inb)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterHigh=afterAny, AfterFalling=afterAny, AfterLow=afterAny, AfterRising=afterAny)
|
||||||
|
|
||||||
|
def normal_operation(self):
|
||||||
|
dut = self.dut
|
||||||
|
|
||||||
|
def oracle(i):
|
||||||
|
if i == 0: return 0x01
|
||||||
|
if i == 1: return 0x02
|
||||||
|
if i == 2: return 0x05
|
||||||
|
if i == 3: return 0x0A
|
||||||
|
if i == 4: return 0x15
|
||||||
|
if i == 5: return 0x2A
|
||||||
|
if i == 6: return 0x55
|
||||||
|
if i == 7: return 0xAA
|
||||||
|
if i == 8: return 0x55
|
||||||
|
if i == 9: return 0xAA
|
||||||
|
|
||||||
|
expectedOutput = 0
|
||||||
|
|
||||||
|
def afterLow():
|
||||||
|
assert (yield dut.data) == expectedOutput
|
||||||
|
|
||||||
|
yield dut.nen.eq(0)
|
||||||
|
for i in range(10):
|
||||||
|
expectedOutput = oracle(i)
|
||||||
|
yield dut.inb.eq(~dut.inb)
|
||||||
|
yield from exiClockCycle(dut.exiClkState, AfterLow=afterLow)
|
||||||
|
|
||||||
|
def simulate(self):
|
||||||
|
self.dut = ShiftRegister(8)
|
||||||
|
|
||||||
|
sim = Simulator(self.dut)
|
||||||
|
sim.add_clock(1e-6) # 1 MHz
|
||||||
|
sim.add_sync_process(self.enabled_test)
|
||||||
|
|
||||||
|
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_enable.vcd"):
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
self.dut = ShiftRegister(8)
|
||||||
|
|
||||||
|
sim = Simulator(self.dut)
|
||||||
|
sim.add_clock(1e-6) # 1 MHz
|
||||||
|
sim.add_sync_process(self.normal_operation)
|
||||||
|
|
||||||
|
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_shift.vcd"):
|
||||||
|
sim.run()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
bench = TestBench()
|
||||||
|
bench.simulate()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
from typing import Callable
|
||||||
|
from ReBba.Components.ExiClock import ClockState
|
||||||
|
from amaranth import Const, Elaboratable, Signal
|
||||||
|
|
||||||
|
def empty():
|
||||||
|
yield None
|
||||||
|
|
||||||
|
def exiClockCycle(exiClock: Signal, AfterHigh: Callable = empty, AfterFalling: Callable = empty, AfterLow: Callable = empty, AfterRising: Callable = empty):
|
||||||
|
yield exiClock.eq(ClockState.HIGH)
|
||||||
|
yield
|
||||||
|
yield from AfterHigh()
|
||||||
|
yield
|
||||||
|
|
||||||
|
yield exiClock.eq(ClockState.FALLING)
|
||||||
|
yield from AfterFalling()
|
||||||
|
|
||||||
|
yield exiClock.eq(ClockState.LOW)
|
||||||
|
yield
|
||||||
|
yield from AfterLow()
|
||||||
|
yield
|
||||||
|
|
||||||
|
yield exiClock.eq(ClockState.RISING)
|
||||||
|
yield from AfterRising()
|
||||||
|
|
||||||
|
def resetDut(rst: Signal):
|
||||||
|
yield
|
||||||
|
yield rst.eq(Const(1))
|
||||||
|
yield
|
||||||
|
yield rst.eq(Const(0))
|
||||||
|
yield
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,136 +0,0 @@
|
|||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
from amaranth import *
|
|
||||||
from amaranth.build import Platform
|
|
||||||
from amaranth.back import verilog
|
|
||||||
from amaranth.sim import Simulator
|
|
||||||
from ExiClock import ClockState
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Hardware Description.
|
|
||||||
#####
|
|
||||||
|
|
||||||
class ShiftRegister(Elaboratable):
|
|
||||||
def __init__(self, width):
|
|
||||||
self.width = width
|
|
||||||
|
|
||||||
# Ports
|
|
||||||
self.nen = Signal()
|
|
||||||
self.exiClkState = Signal(2)
|
|
||||||
self.rst = Signal()
|
|
||||||
self.inb = Signal()
|
|
||||||
self.data = Signal(self.width, reset=0)
|
|
||||||
|
|
||||||
def elaborate(self, platform: Platform):
|
|
||||||
m = Module()
|
|
||||||
|
|
||||||
with m.If(self.rst):
|
|
||||||
m.d.sync += self.data.eq(self.data.reset)
|
|
||||||
|
|
||||||
with m.If(~self.nen):
|
|
||||||
with m.If(self.exiClkState == ClockState.FALLING):
|
|
||||||
m.d.sync += self.data.eq(self.data.shift_left(1) | self.inb )
|
|
||||||
|
|
||||||
return m
|
|
||||||
|
|
||||||
#####
|
|
||||||
# TestBench
|
|
||||||
#####
|
|
||||||
class TestBench:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def simExiClock(self, dut):
|
|
||||||
yield dut.exiClk.eq(~dut.exiClk)
|
|
||||||
|
|
||||||
def enabled_test(self):
|
|
||||||
dut = self.dut
|
|
||||||
|
|
||||||
# Disabled ShiftRegister should not Change.
|
|
||||||
yield dut.nen.eq(1)
|
|
||||||
for _ in range(10):
|
|
||||||
yield dut.inb.eq(~dut.inb)
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
assert not (yield dut.data)
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
assert not (yield dut.data)
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
|
|
||||||
def normal_operation(self):
|
|
||||||
dut = self.dut
|
|
||||||
|
|
||||||
def oracle(i):
|
|
||||||
if i == 0: return 0x01
|
|
||||||
if i == 1: return 0x02
|
|
||||||
if i == 2: return 0x05
|
|
||||||
if i == 3: return 0x0A
|
|
||||||
if i == 4: return 0x15
|
|
||||||
if i == 5: return 0x2A
|
|
||||||
if i == 6: return 0x55
|
|
||||||
if i == 7: return 0xAA
|
|
||||||
if i == 8: return 0x55
|
|
||||||
if i == 9: return 0xAA
|
|
||||||
|
|
||||||
yield dut.nen.eq(0)
|
|
||||||
for i in range(10):
|
|
||||||
yield dut.inb.eq(~dut.inb)
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
yield from self.simExiClock(dut)
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
assert (yield dut.data) == oracle(i)
|
|
||||||
|
|
||||||
def simulate(self):
|
|
||||||
self.dut = ShiftRegister(8)
|
|
||||||
|
|
||||||
sim = Simulator(self.dut)
|
|
||||||
sim.add_clock(1e-6) # 1 MHz
|
|
||||||
sim.add_sync_process(self.enabled_test)
|
|
||||||
|
|
||||||
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_enable.vcd"):
|
|
||||||
sim.run()
|
|
||||||
|
|
||||||
self.dut = ShiftRegister(8)
|
|
||||||
|
|
||||||
sim = Simulator(self.dut)
|
|
||||||
sim.add_clock(1e-6) # 1 MHz
|
|
||||||
sim.add_sync_process(self.normal_operation)
|
|
||||||
|
|
||||||
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_shift.vcd"):
|
|
||||||
sim.run()
|
|
||||||
|
|
||||||
#####
|
|
||||||
# Main portion
|
|
||||||
#####
|
|
||||||
|
|
||||||
def main():
|
|
||||||
if(len(sys.argv) == 2):
|
|
||||||
|
|
||||||
if sys.argv[1] == "s":
|
|
||||||
bench = TestBench()
|
|
||||||
bench.simulate()
|
|
||||||
|
|
||||||
if sys.argv[1] == "v":
|
|
||||||
mod = ShiftRegister(8)
|
|
||||||
with open(os.path.dirname(os.path.abspath(__file__)) + "/shift_register.v", "w") as f:
|
|
||||||
f.write(verilog.convert(mod, ports=[mod.exiClk, mod.inb, mod.data]))
|
|
||||||
|
|
||||||
else:
|
|
||||||
bench = TestBench()
|
|
||||||
bench.simulate()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
|
|||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
setup(name='ReBba', version='0.1', packages=find_packages())
|
||||||
Reference in new issue
Block a user