Archived
1
0
Fork 0

top: add UART for debugging, correctly restart FSM.

This commit is contained in:
Charlotte 2023-08-22 15:27:21 +10:00
parent a9977c3398
commit 1078a55c9f
6 changed files with 165 additions and 63 deletions

View File

@ -2,7 +2,7 @@ import warnings
from argparse import ArgumentParser
from os import makedirs
from . import build, formal, test, cxxsim
from . import build, cxxsim, formal, test
from .base import path
warnings.simplefilter("default")

View File

@ -84,10 +84,8 @@ def main(args: Namespace):
ports=design.ports(platform),
)
main_cc_path = path("cxxsim/main.cc")
cc_o_paths = {
path("cxxsim/main.cc"): "build/main.o",
path("cxxsim/main.cc"): "build/main.o",
}
for cc_path, o_path in cc_o_paths.items():
@ -106,13 +104,16 @@ def main(args: Namespace):
)
exe_o_path = path("build/cxxsim")
subprocess.run([
"c++",
*(["-O3"] if args.optimize.opt_rtl else []),
*cc_o_paths.values(),
"-o",
exe_o_path,
], check=True)
subprocess.run(
[
"c++",
*(["-O3"] if args.optimize.opt_rtl else []),
*cc_o_paths.values(),
"-o",
exe_o_path,
],
check=True,
)
if not args.compile:
cmd = [exe_o_path]

View File

@ -2,7 +2,7 @@ import subprocess
from argparse import ArgumentParser, Namespace
from typing import Tuple
from amaranth import ClockSignal, Module, ResetSignal, Signal, Value
from amaranth import Module, Signal, Value
from amaranth.back import rtlil
from ..base import path

View File

@ -1,7 +1,4 @@
import os
import subprocess
from abc import ABCMeta, abstractmethod
from pathlib import Path
from abc import ABCMeta
from typing import Any, ClassVar, Self, Type
from amaranth.build import Platform as AmaranthPlatform

View File

@ -1,4 +1,4 @@
from typing import Final, Optional, cast
from typing import Final, cast
from amaranth import Elaboratable, Module, Signal
from amaranth.build import Attrs
@ -6,8 +6,9 @@ from amaranth.hdl.ast import Assert, Display
from amaranth.lib.wiring import Component, In, Out
from amaranth_boards.resources import I2CResource
from ..platform import Platform, icebreaker, orangecrab, test, cxxsim
from ..platform import Platform, icebreaker, orangecrab
from .common import ButtonWithHold, Hz
from .uart import UART
__all__ = ["Top"]
@ -40,13 +41,15 @@ class Top(Component):
def ports(self, platform: Platform) -> list[Signal]:
return [getattr(self, name) for name in self.signature.members.keys()]
def elaborate(self, platform: Optional[Platform]) -> Elaboratable:
def elaborate(self, platform: Platform) -> Elaboratable:
m = Module()
m.submodules.button = ButtonWithHold()
m.d.comb += m.submodules.button.i.eq(self.switch)
button_up = m.submodules.button.up
m.submodules.uart = uart = UART()
# I've removed the pull-up resistors here since they should
# be provided by the controller.
match platform:
@ -99,10 +102,7 @@ class Top(Component):
with m.If(m.submodules.button.held):
m.d.sync += cast(Signal, platform.request("program").o).eq(1)
case test():
button_up = self.switch
case cxxsim():
case _:
button_up = self.switch
# Not stretching by default.
@ -117,52 +117,79 @@ class Top(Component):
measured_count = Signal(range(counter_max))
timer_count = Signal(len(measured_count) * 2)
en = Signal()
m.d.comb += self.led.eq(en)
measured_count_report = Signal.like(measured_count)
m.d.sync += uart.wr_en.eq(0)
with m.If(~en):
with m.If(button_up):
m.d.sync += en.eq(1)
with m.FSM() as fsm:
m.d.comb += self.led.eq(~fsm.ongoing("IDLE"))
with m.Else():
with m.If(button_up):
m.d.sync += en.eq(0)
with m.State("IDLE"):
with m.If(button_up):
m.d.sync += [
uart.wr_data.eq(ord("<")),
uart.wr_en.eq(1),
]
m.next = "MEASURE: PRE"
with m.FSM():
with m.State("MEASURE: PRE"):
with m.If(~self.scl_i & (self.scl_i != scl_last)):
m.d.sync += measured_count.eq(0)
m.next = "MEASURE: COUNT"
with m.State("MEASURE: PRE"):
with m.If(~self.scl_i & (self.scl_i != scl_last)):
m.d.sync += measured_count.eq(0)
m.next = "MEASURE: COUNT"
with m.If(button_up):
m.next = "FISH"
with m.State("MEASURE: COUNT"):
m.d.sync += measured_count.eq(measured_count + 1)
with m.If(self.scl_i != scl_last):
if platform.simulation:
m.d.comb += Assert(self.scl_i)
m.d.sync += Display("Measured count: {0:d}", measured_count)
m.next = "HIGH: WAIT"
with m.State("MEASURE: COUNT"):
m.d.sync += measured_count.eq(measured_count + 1)
with m.If(self.scl_i != scl_last):
if platform.simulation:
m.d.comb += Assert(self.scl_i)
m.d.sync += Display("Measured count: {0:d}", measured_count)
m.d.sync += measured_count_report.eq(measured_count + 1)
m.next = "HIGH: WAIT"
with m.If(button_up):
m.next = "FISH"
with m.State("HIGH: WAIT"):
# Falling edge on SCL, hold it low ourselves
# for (measured_count*2)-1.
with m.If(self.scl_i != scl_last):
if platform.simulation:
m.d.comb += Assert(~self.scl_i)
m.d.sync += [
timer_count.eq((measured_count*2)-1),
self.scl_oe.eq(1),
]
m.next = "LOW: HOLD"
with m.State("HIGH: WAIT"):
# Falling edge on SCL, hold it low ourselves
# for (measured_count*2)-1.
with m.If(self.scl_i != scl_last):
if platform.simulation:
m.d.comb += Assert(~self.scl_i)
m.d.sync += [
timer_count.eq((measured_count * 2) - 1),
self.scl_oe.eq(1),
]
m.next = "LOW: HOLD"
with m.If(button_up):
m.next = "FISH"
with m.State("LOW: HOLD"):
m.d.sync += timer_count.eq(timer_count - 1)
with m.If(timer_count == 0):
m.next = "LOW: FINISHED HOLD"
with m.Else():
m.d.sync += self.scl_oe.eq(1)
with m.State("LOW: HOLD"):
m.d.sync += timer_count.eq(timer_count - 1)
with m.If(timer_count == 0):
m.next = "LOW: FINISHED HOLD"
with m.Else():
m.d.sync += self.scl_oe.eq(1)
with m.If(button_up):
m.next = "FISH"
with m.State("LOW: FINISHED HOLD"):
with m.If(self.scl_i):
m.next = "HIGH: WAIT"
with m.State("LOW: FINISHED HOLD"):
with m.If(self.scl_i):
m.next = "HIGH: WAIT"
with m.If(button_up):
m.next = "FISH"
with m.State("FISH"):
m.d.sync += [
uart.wr_data.eq(ord(">")),
uart.wr_en.eq(1),
]
m.next = "IDLE"
with m.If(measured_count_report != 0):
m.d.sync += [
uart.wr_data.eq(measured_count_report[:8]),
uart.wr_en.eq(1),
measured_count_report.eq(measured_count_report >> 8),
]
return m

77
i2c_obs/rtl/uart.py Normal file
View File

@ -0,0 +1,77 @@
from typing import Optional
from amaranth import C, Cat, Elaboratable, Module, Signal
from amaranth.lib.fifo import SyncFIFO
from amaranth.lib.wiring import Component, Out
from ..platform import Platform, icebreaker
from .common import Counter
__all__ = ["UART"]
class UART(Component):
wr_data: Out(8)
wr_en: Out(1)
_baud: int
_c: Counter
_fifo: SyncFIFO
_tx: Signal
def __init__(self, *, baud: int = 9600):
self._baud = baud
super().__init__()
self._c = Counter(hz=self._baud)
self._fifo = SyncFIFO(width=8, depth=6)
self._tx = Signal()
def elaborate(self, platform: Optional[Platform]) -> Elaboratable:
m = Module()
match platform:
case icebreaker():
uart = platform.request("uart")
m.d.comb += uart.tx.eq(self._tx)
case _:
pass
m.submodules.c = self._c
m.submodules.fifo = self._fifo
m.d.comb += [
self._fifo.w_data.eq(self.wr_data),
self._fifo.w_en.eq(self.wr_en),
self._tx.eq(1),
]
m.d.sync += self._fifo.r_en.eq(0)
# Shove the START and STOP bits in here too!
data = Signal(10)
written = Signal(range(10))
with m.FSM():
with m.State("IDLE"):
with m.If(self._fifo.r_rdy):
m.d.sync += [
data.eq(Cat(C(0, 1), self._fifo.r_data, C(1, 1))), # Meow :3
written.eq(0),
self._fifo.r_en.eq(1),
]
m.next = "TX"
with m.State("TX"):
m.d.comb += [
self._c.en.eq(1),
self._tx.eq(data[0]),
]
with m.If(self._c.full):
m.d.sync += [
data.eq(data >> 1),
written.eq(written + 1),
]
with m.If(written == 9):
m.next = "IDLE"
return m