dvisampler: report the word error rate
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 16 May 2013 20:38:55 +0000 (22:38 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 16 May 2013 20:38:55 +0000 (22:38 +0200)
milkymist/dvisampler/__init__.py
milkymist/dvisampler/wer.py [new file with mode: 0644]
software/videomixer/dvisamplerX.c

index 7db5e3c80ebd1f61058f332511886580014467e2..6819fb183d66b9ba3e49b44ff72b714b336d8655 100644 (file)
@@ -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 (file)
index 0000000..5e9a238
--- /dev/null
@@ -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))
index d1cec3688d287ac5cc135ce46484532c2749da17..35e9225a3092d03f5cfdeefcf288398f93168fe3 100644 (file)
@@ -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());