Skip to content

Instantly share code, notes, and snippets.

@lachlansneff
Last active March 2, 2022 00:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lachlansneff/ee2969f91db45a5cc45bc62260eae47f to your computer and use it in GitHub Desktop.
Save lachlansneff/ee2969f91db45a5cc45bc62260eae47f to your computer and use it in GitHub Desktop.
from amaranth import *
class ClockEnableDivider(Elaboratable):
"""A fixed-point clock enable divider.
Parameters
----------
integer_width : int
The width, in bits, of the integer part of the number.
fraction_width : int
The width, in bits, of the fractional part of the number.
Attributes
----------
integer_width : int
fraction_width : int
integer : Signal(integer_width), in
The integer part of the clock divisor.
fraction : Signal(fraction_width), in
The fraction part of the clock divisor.
en : Signal(), in
Enable/disable clock divider.
clk_en: Signal(), out
Asserted when the attached block should be enabled.
"""
def __init__(self, integer_width: int, fraction_width: int):
if integer_width < 0 or integer_width < 0:
raise TypeError("Bit width of the integer and fractional parts of the fixed-point number must be positive integers")
self.integer_width = integer_width
self.fraction_width = fraction_width
self.integer = Signal(integer_width, reset = 1)
self.fraction = Signal(fraction_width)
self.clk_en = Signal()
self.en = Signal()
def elaborate(self, platform):
m = Module()
int_divisor = Signal(self.integer_width)
frac_divisor = Signal(self.fraction_width)
frac_overflow = Signal()
increase_divisor = Signal()
m.d.sync += [
self.clk_en.eq(0),
int_divisor.eq(self.integer),
frac_divisor.eq(self.fraction),
]
with m.If(self.en):
m.d.sync += [
Cat(frac_divisor, frac_overflow).eq(frac_divisor + self.fraction),
int_divisor.eq(int_divisor - 1),
]
with m.If(frac_overflow):
m.d.sync += increase_divisor.eq(1)
with m.If(int_divisor == 1):
m.d.sync += [
self.clk_en.eq(1),
int_divisor.eq(self.integer + increase_divisor),
increase_divisor.eq(0),
]
return m
if __name__ == "__main__":
from amaranth.sim import Simulator
dut = ClockEnableDivider(16, 8)
def bench():
# Set divisor to 1.0
yield dut.integer.eq(1)
yield dut.fraction.eq(0)
yield dut.en.eq(1)
for _ in range(12):
yield
yield dut.en.eq(0)
yield
# Set divisor to 2.0
yield dut.integer.eq(2)
yield dut.fraction.eq(0)
yield dut.en.eq(1)
for _ in range(12):
yield
yield dut.en.eq(0)
yield
# Set divisor to 2.5
yield dut.integer.eq(2)
yield dut.fraction.eq(((2**8) - 1) // 2)
yield dut.en.eq(1)
for _ in range(12):
yield
sim = Simulator(dut)
sim.add_clock(1e-6) # 1 Mhz
sim.add_sync_process(bench)
with sim.write_vcd("clock_en_divider.vcd"):
sim.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment