Skip to content

Commit

Permalink
gateware.clockgen: Fix off-by-one error
Browse files Browse the repository at this point in the history
This addresses GlasgowEmbedded#667.
  • Loading branch information
mbikovitsky committed Aug 16, 2024
1 parent 97f8db8 commit bd8ceb5
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 12 deletions.
4 changes: 2 additions & 2 deletions software/glasgow/applet/audio/dac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,15 @@ def add_build_arguments(cls, parser, access):
def build(self, target, args):
self.mux_interface = iface = target.multiplexer.claim_interface(self, args)
if args.frequency is None:
pulse_cyc = 0
pulse_cyc = 1
else:
pulse_cyc = self.derive_clock(clock_name="modulation",
input_hz=target.sys_clk_freq, output_hz=args.frequency * 1e6)
sample_cyc = self.derive_clock(clock_name="sampling",
input_hz=target.sys_clk_freq, output_hz=args.sample_rate,
# Drift of sampling clock is extremely bad, so ensure it only happens insofar as
# the oscillator on the board is imprecise, and with no additional error.
max_deviation_ppm=0)
max_deviation_ppm=0) - 1
subtarget = iface.add_subtarget(AudioDACSubtarget(
ports=iface.get_port_group(o = args.pin_set_o),
out_fifo=iface.get_out_fifo(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ def build_subtarget(self, target, args):
min_cyc=4),
delay_cyc=self.derive_clock(input_hz=target.sys_clk_freq,
output_hz=1e6,
clock_name="delay"),
clock_name="delay") - 1,
sck_idle=args.sck_idle,
sck_edge=args.sck_edge,
)
Expand Down
4 changes: 2 additions & 2 deletions software/glasgow/applet/interface/uart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def build(self, target, args):
# a build argument, even though the applet will never be rebuilt as long as you stay
# above 9600.
max_bit_cyc = self.derive_clock(
input_hz=target.sys_clk_freq, output_hz=min(9600, args.baud))
input_hz=target.sys_clk_freq, output_hz=min(9600, args.baud)) - 1

self.__sys_clk_freq = target.sys_clk_freq

Expand Down Expand Up @@ -215,7 +215,7 @@ async def run(self, device, args):
# Load the manually set baud rate.
manual_cyc = self.derive_clock(
input_hz=self.__sys_clk_freq, output_hz=args.baud,
min_cyc=2, max_deviation_ppm=args.tolerance)
min_cyc=2, max_deviation_ppm=args.tolerance) - 1
await device.write_register(self.__addr_manual_cyc, manual_cyc, width=4)
await device.write_register(self.__addr_use_auto, 0)

Expand Down
2 changes: 1 addition & 1 deletion software/glasgow/applet/program/m16c/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def add_build_arguments(cls, parser, access):

def build(self, target, args):
self.__bit_cyc_for_baud = {
baud: self.derive_clock(input_hz=target.sys_clk_freq, output_hz=baud)
baud: self.derive_clock(input_hz=target.sys_clk_freq, output_hz=baud) - 1
for baud in BAUD_RATES
}
max_bit_cyc = max(self.__bit_cyc_for_baud.values())
Expand Down
15 changes: 9 additions & 6 deletions software/glasgow/gateware/clockgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ def __init__(self, cyc):
def elaborate(self, platform):
m = Module()

if self.cyc == 0:
if self.cyc <= 0:
raise ValueError(f"Invalid output clock period: {self.cyc}")

if self.cyc == 1:
# Special case: output frequency equal to input frequency.
# Implementation: wire.
m.d.comb += [
Expand All @@ -59,7 +62,7 @@ def elaborate(self, platform):
self.stb_f.eq(1),
]

if self.cyc == 1:
if self.cyc == 2:
# Special case: output frequency half of input frequency.
# Implementation: flip-flop.
m.d.sync += [
Expand All @@ -70,7 +73,7 @@ def elaborate(self, platform):
self.stb_f.eq(self.clk),
]

if self.cyc >= 2:
if self.cyc >= 3:
# General case.
# Implementation: counter.
counter = Signal(range(self.cyc))
Expand Down Expand Up @@ -119,8 +122,8 @@ def calculate(input_hz, output_hz, max_deviation_ppm=None, min_cyc=None):
"cycles at input frequency {:.3f} kHz"
.format(output_hz / 1000, min_cyc, input_hz / 1000))

cyc = round(input_hz // output_hz) - 1
actual_output_hz = input_hz / (cyc + 1)
cyc = round(input_hz // output_hz)
actual_output_hz = input_hz / cyc
deviation_ppm = round(1000000 * (actual_output_hz - output_hz) // output_hz)

if max_deviation_ppm is not None and deviation_ppm > max_deviation_ppm:
Expand Down Expand Up @@ -148,7 +151,7 @@ def derive(cls, input_hz, output_hz, max_deviation_ppm=None, min_cyc=None,
clock = "clock"
else:
clock = f"clock {clock_name}"
if cyc in (0, 1):
if cyc in (1, 2):
duty = 50
else:
duty = (cyc // 2) / cyc * 100
Expand Down

0 comments on commit bd8ceb5

Please sign in to comment.