Makes a seperate component that handles the ExiClk

This commit is contained in:
Dennis Brentjes 2022-01-09 22:42:14 +01:00
parent f7106abe87
commit 43fb4beb6e
5 changed files with 133 additions and 40 deletions

115
re-bba/ExiClock.py Normal file
View File

@ -0,0 +1,115 @@
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.sync += self.exiClkState.eq(ClockState.LOW)
with m.Elif(self.prevExiClkState == ClockState.RISING):
m.d.sync += self.exiClkState.eq(ClockState.HIGH)
with m.Else():
with m.If(self.prevExiClk ^ self.exiClk):
m.d.sync += self.exiClkState.eq(Cat(1, self.exiClk))
with m.Else():
m.d.sync += 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
yield
assert (yield dut.exiClkState) == ClockState.RISING.value
yield
yield
assert (yield dut.exiClkState) == ClockState.HIGH.value
yield
yield
yield from self.FlipExiClock(dut)
yield
yield
assert (yield dut.exiClkState) == ClockState.FALLING.value
yield
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()

View File

@ -1,61 +1,36 @@
import enum
import sys
import os import os
from amaranth import * from amaranth import *
from amaranth.build import Platform
from amaranth.back import verilog from amaranth.back import verilog
from amaranth.sim import Simulator from amaranth.sim import Simulator
from ExiClock import ClockState
##### #####
# Hardware Description. # Hardware Description.
##### #####
class ClockState(enum.Enum):
LOW = 0
FALLING = 1
HIGH = 2
RISING = 3
class ShiftRegister(Elaboratable): class ShiftRegister(Elaboratable):
def __init__(self, width): def __init__(self, width):
self.width = width self.width = width
# Ports # Ports
self.nen = Signal() self.nen = Signal()
self.exiClkState = Signal(2)
self.rst = Signal() self.rst = Signal()
self.inb = Signal() self.inb = Signal()
self.exiClk = Signal()
self.data = Signal(self.width, reset=0) self.data = Signal(self.width, reset=0)
# State def elaborate(self, platform: Platform):
self.prevExiClkValid = Signal()
self.prevExiClk = Signal()
self.prevExiClkState = Signal(2)
self.exiClkState = Signal(2)
def elaborate(self, platform):
m = Module() m = Module()
with m.If(self.rst): with m.If(self.rst):
m.d.sync += self.data.eq(self.data.reset) m.d.sync += self.data.eq(self.data.reset)
with m.If(~self.nen): with m.If(~self.nen):
with m.If(self.prevExiClkValid): with m.If(self.exiClkState == ClockState.FALLING):
m.d.sync += self.prevExiClkState.eq(self.exiClkState) m.d.sync += self.data.eq(self.data.shift_left(1) | self.inb )
with m.If(self.prevExiClk ^ self.exiClk):
m.d.sync += self.exiClkState.eq(Cat(self.exiClk, 1))
with m.Else():
m.d.sync += self.exiClkState.eq(Cat(self.exiClk, 0))
with m.If((self.exiClkState == ClockState.FALLING).bool() & (self.exiClkState != self.prevExiClkState).bool()):
m.d.sync += self.data.eq(self.data.shift_left(1) | self.inb )
m.d.sync += self.prevExiClkValid.eq(1)
m.d.sync += self.prevExiClk.eq(self.exiClk)
with m.Else():
m.d.sync += self.prevExiClkValid.eq(0)
return m return m
##### #####
@ -133,6 +108,10 @@ class TestBench:
with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_shift.vcd"): with sim.write_vcd(os.path.dirname(os.path.abspath(__file__)) + "/ShiftRegister_shift.vcd"):
sim.run() sim.run()
#####
# Main portion
#####
def main(): def main():
if(len(sys.argv) == 2): if(len(sys.argv) == 2):
@ -149,11 +128,6 @@ def main():
bench = TestBench() bench = TestBench()
bench.simulate() bench.simulate()
#####
# Main portion
#####
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -4,9 +4,10 @@ from amaranth import *
from amaranth.back import verilog from amaranth.back import verilog
from amaranth.build.plat import Platform from amaranth.build.plat import Platform
from amaranth.sim import Simulator from amaranth.sim import Simulator
from amaranth_boards.icebreaker import *; from amaranth_boards.icebreaker import *
from ShiftRegister.ShiftRegister import *; from ExiClock import ExiClock
from ShiftRegister import ShiftRegister
class ReBba(Elaboratable): class ReBba(Elaboratable):
def __init__(self): def __init__(self):
@ -25,6 +26,8 @@ class ReBba(Elaboratable):
btn2 = platform.request("button", 2) btn2 = platform.request("button", 2)
btn3 = platform.request("button", 3) btn3 = platform.request("button", 3)
exiClk = ExiClock()
m.submodules += exiClk
sr = ShiftRegister(5) sr = ShiftRegister(5)
m.submodules += sr m.submodules += sr
@ -34,11 +37,12 @@ class ReBba(Elaboratable):
m.d.comb += led4.eq(sr.data[3]) m.d.comb += led4.eq(sr.data[3])
m.d.comb += led5.eq(sr.data[4]) m.d.comb += led5.eq(sr.data[4])
m.d.comb += sr.exiClk.eq(btn3) m.d.comb += exiClk.exiClk.eq(btn3)
m.d.comb += sr.rst.eq(btn2) m.d.comb += sr.rst.eq(btn2)
m.d.comb += sr.inb.eq(btn1) m.d.comb += sr.inb.eq(btn1)
m.d.comb += sr.nen.eq(Const(0)) m.d.comb += sr.nen.eq(Const(0))
m.d.comb += sr.exiClkState.eq(exiClk.exiClkState)
return m return m