HeavyX/heavycomps/heavycomps/cores/timer.py

69 lines
2.4 KiB
Python

from nmigen import *
from nmigen_soc import csr
from nmigen.utils import *
__all__ = ["TimerCore"]
class TimerCore(Elaboratable):
def __init__(self, *, width, bus_data_width,
clk_domain="sync", bus_granularity=None):
self.width = width
bus_dw = bus_data_width
if bus_granularity is None:
bus_granularity = bus_data_width
bus_gr = bus_granularity
with csr.Bank(name="timer",
addr_width=log2_int(-(-(bus_dw+3*max(width, bus_dw))//bus_gr), need_pow2=False),
data_width=bus_gr) as self.csr:
self.csr.r += [
csr.Register(
"control", "rw", width=bus_dw,
fields=[csr.Field("enable", startbit=0),
csr.Field("update_enable", startbit=4)]
),
csr.Register(
"load", "rw", width=max(width, bus_dw),
fields=[csr.Field("value", width=self.width)]
),
csr.Register(
"reload", "rw", width=max(width, bus_dw),
fields=[csr.Field("value", width=self.width)]
),
csr.Register(
"current", "r", width=max(width, bus_dw),
fields=[csr.Field("value", width=self.width)]
)
]
self.wb2csr = csr.WishboneCSRBridge(self.csr.dec.bus, data_width=bus_data_width)
self.csr_bus = self.wb2csr.wb_bus
def elaborate(self, platform):
m = Module()
m.submodules += self.csr, self.wb2csr
# Value right now
value = Signal(self.width)
# When Timer is enabled, start counting
with m.If(self.csr.r.control.f.enable.s):
with m.If(value == 0):
m.d.sync += value.eq(self.csr.r.reload.s)
with m.Else():
m.d.sync += value.eq(value - 1)
# Otherwise, load Timer value to .value
with m.Else():
m.d.sync += value.eq(self.csr.r.load.s)
# If Timer allows updating value in memory, update
m.d.comb += self.csr.r.current.set_val.eq(value)
with m.If(self.csr.r.control.f.update_enable.s):
m.d.sync += self.csr.r.current.set_stb.eq(1)
with m.Else():
m.d.sync += self.csr.r.current.set_stb.eq(0)
return m