2022-04-03 06:58:03 -04:00
|
|
|
#
|
|
|
|
# This file is part of LiteX.
|
|
|
|
#
|
|
|
|
# Copyright (c) 2022 Wolfgang Nagele <mail@wnagele.com>
|
|
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
from migen import *
|
|
|
|
|
|
|
|
from litex.soc.cores.led import WS2812
|
|
|
|
|
|
|
|
|
|
|
|
class TestWS2812(unittest.TestCase):
|
2022-04-04 09:24:54 -04:00
|
|
|
test_clk_freqs = [75e6, 50e6, 25e6]
|
|
|
|
|
2022-04-03 06:58:03 -04:00
|
|
|
def generator(self, dut, led_signal, led_data, sys_clk_freq, iterations):
|
2022-04-04 09:24:54 -04:00
|
|
|
# Error Margin from WS2812 datasheet.
|
|
|
|
error_margin = 150e-9
|
2022-04-03 06:58:03 -04:00
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
# Cap on how long a sequence will be evaluated.
|
2022-04-03 06:58:03 -04:00
|
|
|
max_cycles_per_seq = int(dut.trst * sys_clk_freq * 2)
|
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
# Verify initial reset.
|
2022-04-03 06:58:03 -04:00
|
|
|
rst_cycles = 0
|
|
|
|
for _ in range(max_cycles_per_seq):
|
|
|
|
if (yield led_signal) != 0:
|
|
|
|
break
|
|
|
|
rst_cycles += 1
|
|
|
|
yield
|
|
|
|
rst_time = rst_cycles / sys_clk_freq
|
|
|
|
assert rst_time >= dut.trst
|
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
# Verify generated data pulses.
|
2022-04-03 06:58:03 -04:00
|
|
|
length = len(led_data)
|
|
|
|
for _ in range(iterations):
|
2022-04-04 09:24:54 -04:00
|
|
|
for i_num, num in enumerate(led_data, start=1):
|
|
|
|
for idx_bit, bit in enumerate(TestWS2812.to_bits(num), start=1):
|
|
|
|
exp_high, exp_low = {
|
|
|
|
0 : (dut.t0h, dut.t0l),
|
|
|
|
1 : (dut.t1h, dut.t1l)
|
|
|
|
}[bit]
|
|
|
|
|
|
|
|
# On end of chain, add reset time to exp_low
|
2022-04-03 06:58:03 -04:00
|
|
|
if i_num == length and idx_bit == 24:
|
|
|
|
exp_low += dut.trst
|
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
# Verify high cycle.
|
2022-04-03 06:58:03 -04:00
|
|
|
high_cycles = 0
|
|
|
|
for _ in range(max_cycles_per_seq):
|
|
|
|
if (yield led_signal) != 1:
|
|
|
|
break
|
|
|
|
high_cycles += 1
|
|
|
|
yield
|
|
|
|
high_time = high_cycles / sys_clk_freq
|
|
|
|
assert high_time >= exp_high - error_margin
|
|
|
|
assert high_time <= exp_high + error_margin
|
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
# Verify low cycle.
|
2022-04-03 06:58:03 -04:00
|
|
|
low_cycles = 0
|
|
|
|
for _ in range(max_cycles_per_seq):
|
|
|
|
if (yield led_signal) != 0:
|
|
|
|
break
|
|
|
|
low_cycles += 1
|
|
|
|
yield
|
|
|
|
low_time = low_cycles / sys_clk_freq
|
|
|
|
assert low_time >= exp_low - error_margin
|
|
|
|
assert low_time <= exp_low + error_margin
|
|
|
|
|
|
|
|
def to_bits(num, length = 24):
|
|
|
|
return ( int(x) for x in bin(num)[2:].zfill(length) )
|
|
|
|
|
|
|
|
|
2022-04-04 09:24:54 -04:00
|
|
|
def run_test(self, revision, sys_clk_freq):
|
2022-04-03 06:58:03 -04:00
|
|
|
led_signal = Signal()
|
2022-04-04 09:24:54 -04:00
|
|
|
led_data = [0x100000, 0x200000, 0x300000, 0x400000, 0x500000, 0x600000, 0x700000, 0x800000, 0x900000]
|
|
|
|
iterations = 2
|
|
|
|
dut = WS2812(led_signal, len(led_data), sys_clk_freq, revision=revision, init=led_data)
|
|
|
|
run_simulation(dut, self.generator(dut, led_signal, led_data, sys_clk_freq, iterations), vcd_name="sim.vcd")
|
2022-04-03 06:58:03 -04:00
|
|
|
|
|
|
|
def test_WS2812_old(self):
|
2022-04-04 09:24:54 -04:00
|
|
|
for sys_clk_freq in self.test_clk_freqs:
|
2022-04-03 06:58:03 -04:00
|
|
|
self.run_test("old", sys_clk_freq)
|
|
|
|
|
|
|
|
def test_WS2812_new(self):
|
2022-04-04 09:24:54 -04:00
|
|
|
for sys_clk_freq in self.test_clk_freqs:
|
2022-04-03 06:58:03 -04:00
|
|
|
self.run_test("new", sys_clk_freq)
|