From fb6cd481f05cc098095314ebd89e61115d4fe35f Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 16 May 2013 22:38:55 +0200 Subject: [PATCH] dvisampler: report the word error rate --- milkymist/dvisampler/__init__.py | 5 +++ milkymist/dvisampler/wer.py | 60 +++++++++++++++++++++++++++++++ software/videomixer/dvisamplerX.c | 8 ++++- 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 milkymist/dvisampler/wer.py diff --git a/milkymist/dvisampler/__init__.py b/milkymist/dvisampler/__init__.py index 7db5e3c8..6819fb18 100644 --- a/milkymist/dvisampler/__init__.py +++ b/milkymist/dvisampler/__init__.py @@ -6,6 +6,7 @@ from milkymist.dvisampler.edid import EDID from milkymist.dvisampler.clocking import Clocking from milkymist.dvisampler.datacapture import DataCapture from milkymist.dvisampler.charsync import CharSync +from milkymist.dvisampler.wer import WER from milkymist.dvisampler.decoding import Decoding from milkymist.dvisampler.chansync import ChanSync from milkymist.dvisampler.analysis import SyncPolarity, ResolutionDetection, FrameExtraction @@ -36,6 +37,10 @@ class DVISampler(Module, AutoCSR): setattr(self.submodules, name + "_charsync", charsync) self.comb += charsync.raw_data.eq(cap.d) + wer = WER() + setattr(self.submodules, name + "_wer", wer) + self.comb += wer.data.eq(charsync.data) + decoding = Decoding() setattr(self.submodules, name + "_decod", decoding) self.comb += [ diff --git a/milkymist/dvisampler/wer.py b/milkymist/dvisampler/wer.py new file mode 100644 index 00000000..5e9a2380 --- /dev/null +++ b/milkymist/dvisampler/wer.py @@ -0,0 +1,60 @@ +from migen.fhdl.structure import * +from migen.fhdl.module import Module +from migen.bank.description import * +from migen.genlib.misc import optree +from migen.genlib.cdc import PulseSynchronizer + +from milkymist.dvisampler.common import control_tokens + +class WER(Module, AutoCSR): + def __init__(self, period_bits=24): + self.data = Signal(10) + self._r_update = CSR() + self._r_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) + self.sync.pix += transition_count.eq(optree("+", [transitions[i] for i in range(8)])) + + is_control = Signal() + self.sync.pix += is_control.eq(optree("|", [data_r == ct for ct in control_tokens])) + + # 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._r_update.re, self._r_value.status.eq(wer_counter_sys)) diff --git a/software/videomixer/dvisamplerX.c b/software/videomixer/dvisamplerX.c index d1cec368..35e9225a 100644 --- a/software/videomixer/dvisamplerX.c +++ b/software/videomixer/dvisamplerX.c @@ -65,7 +65,10 @@ static int dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2; void dvisamplerX_print_status(void) { - printf("dvisamplerX: ph:%4d %4d %4d // charsync:%d%d%d [%d %d %d] // chansync:%d // res:%dx%d\n", + dvisamplerX_data0_wer_update_write(1); + dvisamplerX_data1_wer_update_write(1); + dvisamplerX_data2_wer_update_write(1); + printf("dvisamplerX: ph:%4d %4d %4d // charsync:%d%d%d [%d %d %d] // WER:%3d %3d %3d // chansync:%d // res:%dx%d\n", dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2, dvisamplerX_data0_charsync_char_synced_read(), dvisamplerX_data1_charsync_char_synced_read(), @@ -73,6 +76,9 @@ void dvisamplerX_print_status(void) dvisamplerX_data0_charsync_ctl_pos_read(), dvisamplerX_data1_charsync_ctl_pos_read(), dvisamplerX_data2_charsync_ctl_pos_read(), + dvisamplerX_data0_wer_value_read(), + dvisamplerX_data1_wer_value_read(), + dvisamplerX_data2_wer_value_read(), dvisamplerX_chansync_channels_synced_read(), dvisamplerX_resdetection_hres_read(), dvisamplerX_resdetection_vres_read()); -- 2.30.2