2015-11-01 09:38:06 -05:00
|
|
|
from functools import reduce
|
|
|
|
from operator import add, or_
|
|
|
|
|
2015-09-22 12:36:47 -04:00
|
|
|
from migen import *
|
2015-03-01 04:01:23 -05:00
|
|
|
from migen.genlib.cdc import PulseSynchronizer
|
|
|
|
|
2015-11-01 09:38:06 -05:00
|
|
|
from misoc.interconnect.csr import *
|
|
|
|
from misoc.cores.dvi_sampler.common import control_tokens
|
2015-03-01 04:01:23 -05:00
|
|
|
|
2015-04-13 10:47:22 -04:00
|
|
|
|
2015-03-01 04:01:23 -05:00
|
|
|
class WER(Module, AutoCSR):
|
2015-04-13 10:19:55 -04:00
|
|
|
def __init__(self, period_bits=24):
|
|
|
|
self.data = Signal(10)
|
|
|
|
self._update = CSR()
|
|
|
|
self._value = CSRStatus(period_bits)
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
# pipeline stage 1
|
|
|
|
# we ignore the 10th (inversion) bit, as it is independent of the transition minimization
|
|
|
|
data_r = Signal(9)
|
|
|
|
self.sync.pix += data_r.eq(self.data[:9])
|
|
|
|
|
|
|
|
# pipeline stage 2
|
|
|
|
transitions = Signal(8)
|
|
|
|
self.comb += [transitions[i].eq(data_r[i] ^ data_r[i+1]) for i in range(8)]
|
|
|
|
transition_count = Signal(max=9)
|
2015-11-01 09:38:06 -05:00
|
|
|
self.sync.pix += transition_count.eq(reduce(add, [transitions[i] for i in range(8)]))
|
2015-04-13 10:19:55 -04:00
|
|
|
|
|
|
|
is_control = Signal()
|
2015-11-01 09:38:06 -05:00
|
|
|
self.sync.pix += is_control.eq(reduce(or_, [data_r == ct for ct in control_tokens]))
|
2015-04-13 10:19:55 -04:00
|
|
|
|
|
|
|
# pipeline stage 3
|
|
|
|
is_error = Signal()
|
|
|
|
self.sync.pix += is_error.eq((transition_count > 4) & ~is_control)
|
|
|
|
|
|
|
|
# counter
|
|
|
|
period_counter = Signal(period_bits)
|
|
|
|
period_done = Signal()
|
|
|
|
self.sync.pix += Cat(period_counter, period_done).eq(period_counter + 1)
|
|
|
|
|
|
|
|
wer_counter = Signal(period_bits)
|
|
|
|
wer_counter_r = Signal(period_bits)
|
|
|
|
wer_counter_r_updated = Signal()
|
|
|
|
self.sync.pix += [
|
|
|
|
wer_counter_r_updated.eq(period_done),
|
|
|
|
If(period_done,
|
|
|
|
wer_counter_r.eq(wer_counter),
|
|
|
|
wer_counter.eq(0)
|
|
|
|
).Elif(is_error,
|
|
|
|
wer_counter.eq(wer_counter + 1)
|
|
|
|
)
|
|
|
|
]
|
|
|
|
|
|
|
|
# sync to system clock domain
|
|
|
|
wer_counter_sys = Signal(period_bits)
|
|
|
|
self.submodules.ps_counter = PulseSynchronizer("pix", "sys")
|
|
|
|
self.comb += self.ps_counter.i.eq(wer_counter_r_updated)
|
|
|
|
self.sync += If(self.ps_counter.o, wer_counter_sys.eq(wer_counter_r))
|
|
|
|
|
|
|
|
# register interface
|
|
|
|
self.sync += If(self._update.re, self._value.status.eq(wer_counter_sys))
|