add Run Length Encoding
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 23 Mar 2013 12:57:59 +0000 (13:57 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Sat, 23 Mar 2013 21:06:08 +0000 (22:06 +0100)
README
examples/de0_nano/client/test_mila.py
miscope/recorder.py
miscope/tools/vcd.py
sim/tb_RecorderCsr.py
sim/tb_miscope.py

diff --git a/README b/README
index cdffe5f61324ebd1bb0de8b3c7cd0bdefbac8b36..846e7b606887dc73fa11ee49247addcad93858d1 100644 (file)
--- a/README
+++ b/README
@@ -36,6 +36,7 @@ to be ready to debug!
 
 [> Status:
 Miio & Mila working on board with standard term.
+RLE working on board.
 RangeDetector and EdgeDector terms not tested.
 
 [> Examples:
index 4887851bb251d89c89e16e8ff440dde7ada66155..8976870971d783194e17e5d63f5a91dc11cc9219 100644 (file)
@@ -16,6 +16,7 @@ trig_w                = 16
 dat_w          = 16
 rec_size       = 512
 rec_offset     = 32
+enable_rle  = True
 
 # Miscope Configuration
 # MiLa
@@ -35,6 +36,8 @@ def capture(size):
        sum_tt = gen_truth_table("term")
        mila.trigger.sum.set(sum_tt)
        mila.recorder.reset()
+       if enable_rle:
+               mila.recorder.enable_rle()
        recorder.set_size(rec_size)     
        mila.recorder.set_offset(rec_offset)
        mila.recorder.arm()
@@ -46,7 +49,7 @@ def capture(size):
        
        print("-Receiving Data...", end=' ')
        sys.stdout.flush()
-       dat_vcd += mila.recorder.pull(size)
+       dat_vcd += mila.recorder.pull(rec_size)
        print("[Done]")
 
 print("Capturing ...")
@@ -61,6 +64,9 @@ mila_layout = [
        ("cnt", 8),
        ]
 
+if enable_rle:
+       dat_vcd = dat_vcd.decode_rle()
+
 myvcd = Vcd()
 myvcd.add_from_layout(mila_layout, dat_vcd)
 myvcd.write("test_mila.vcd")
\ No newline at end of file
index caebb7a5eb923979b75e6af55c5551896bdb1b68..2d634678185d4c140a10fbc45ec0ebc1dc247ccc 100644 (file)
@@ -81,24 +81,88 @@ class Storage:
                
                return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment()
 
+class RLE:
+
+       # 
+       # Definition
+       #
+       def __init__(self, width, length):
+               self.width = width
+               self.length = length
+
+               # Control
+               self.enable = Signal()
+
+               # Input
+               self.dat_i = Signal(width)
+
+               # Output
+               self.stb_o = Signal()
+               self.dat_o = Signal(width)
+               
+       def get_fragment(self):
+
+               # Register Input                
+               dat_i_d = Signal(self.width)
+
+               sync =[dat_i_d.eq(self.dat_i)]
+
+               # Detect diff
+               diff = Signal()
+               comb = [diff.eq(~self.enable | (dat_i_d != self.dat_i))]
+
+               diff_rising = RisingEdge(diff)
+               diff_d = Signal()
+               sync +=[diff_d.eq(diff)]
+
+               # Generate RLE word
+               rle_cnt  = Signal(max=self.length)
+               rle_max  = Signal()
+
+               comb +=[If(rle_cnt == self.length, rle_max.eq(self.enable))]
+
+               sync +=[
+                       If(diff | rle_max,
+                               rle_cnt.eq(0)
+                       ).Else(
+                               rle_cnt.eq(rle_cnt + 1)
+                       )
+               ]
+
+               # Mux RLE word and data
+               comb +=[
+                       If(diff_rising.o & (~rle_max),
+                               self.stb_o.eq(1),
+                               self.dat_o[self.width-1].eq(1),
+                               self.dat_o[:len(rle_cnt)].eq(rle_cnt)
+                       ).Elif(diff_d | rle_max,
+                               self.stb_o.eq(1),
+                               self.dat_o.eq(dat_i_d)
+                       ).Else(
+                               self.stb_o.eq(0),
+                       )
+               ]
+
+               return Fragment(comb, sync) + diff_rising.get_fragment()
+
 class Sequencer:
        # 
        # Definition
        #
        def __init__(self):
                
-               # Controller interface
+               # Control
                self.rst = Signal()
                self.arm = Signal()
                
-               # Trigger interface
+               # Trigger
                self.hit  = Signal()
                
-               # Recorder interface
+               # Recorder
                self.start = Signal()
                self.done = Signal()
                
-               # Others
+               # Internal
                self.enable = Signal()
                
        def get_fragment(self):
@@ -129,12 +193,13 @@ class Sequencer:
 
 
 REC_RST_BASE           = 0x00
-REC_ARM_BASE           = 0x01
-REC_DONE_BASE          = 0x02
-REC_SIZE_BASE          = 0x03
-REC_OFFSET_BASE                = 0x05
-REC_READ_BASE          = 0x07
-REC_READ_DATA_BASE     = 0x08
+REC_RLE_BASE        = 0x01
+REC_ARM_BASE           = 0x02
+REC_DONE_BASE          = 0x03
+REC_SIZE_BASE          = 0x04
+REC_OFFSET_BASE                = 0x06
+REC_READ_BASE          = 0x08
+REC_READ_DATA_BASE     = 0x09
 
 class Recorder:
        # 
@@ -147,9 +212,11 @@ class Recorder:
                
                self.storage = Storage(self.width, self.depth)
                self.sequencer = Sequencer()
+               self.rle = RLE(self.width, (2**(width-2)))
                
                # csr interface
                self._rst = RegisterField("rst", reset=1)
+               self._rle = RegisterField("rle", reset=0)
                self._arm = RegisterField("arm", reset=0)
                self._done = RegisterField("done", reset=0, access_bus=READ_ONLY, 
                                                                        access_dev=WRITE_ONLY)
@@ -161,7 +228,7 @@ class Recorder:
                self._pull_dat = RegisterField("pull_dat", self.width, reset=1, 
                                                                                access_bus=READ_ONLY, access_dev=WRITE_ONLY)
                
-               self.regs = [self._rst, self._arm, self._done, self._size, self._offset,
+               self.regs = [self._rst, self._rle, self._arm, self._done, self._size, self._offset,
                                        self._pull_stb, self._pull_dat]
                
                # set address / interface
@@ -188,6 +255,7 @@ class Recorder:
                        self.sequencer.rst.eq(self._rst.field.r),
                        self.storage.rst.eq(self._rst.field.r),
                        
+                       self.rle.enable.eq(self._rle.field.r),
                        self.sequencer.arm.eq(self._arm.field.r),
                        self.storage.offset.eq(self._offset.field.r),
                        self.storage.size.eq(self._size.field.r),
@@ -204,13 +272,17 @@ class Recorder:
                        self.sequencer.done.eq(self.storage.done),
                        self.sequencer.hit.eq(self.hit),
                        
-                       self.storage.push_stb.eq(self.sequencer.enable),
-                       self.storage.push_dat.eq(self.dat)
+                       self.rle.dat_i.eq(self.dat),
+
+                       self.storage.push_stb.eq(self.sequencer.enable & self.rle.stb_o),
+                       self.storage.push_dat.eq(self.rle.dat_o)
                        ]
                
                return self.bank.get_fragment() + Fragment(comb) +\
                        self.storage.get_fragment() + self.sequencer.get_fragment() +\
-                       _pull_stb_rising.get_fragment()
+                       _pull_stb_rising.get_fragment() + self.rle.get_fragment()
+
+                       
                        
        #
        # Driver
@@ -218,7 +290,13 @@ class Recorder:
        def reset(self):
                self.interface.write(self.bank.get_base() + REC_RST_BASE, 1)
                self.interface.write(self.bank.get_base() + REC_RST_BASE, 0)
-       
+
+       def enable_rle(self):
+               self.interface.write(self.bank.get_base() + REC_RLE_BASE, 1)
+
+       def disable_rle(self):
+               self.interface.write(self.bank.get_base() + REC_RLE_BASE, 0)
+
        def arm(self):
                self.interface.write(self.bank.get_base() + REC_ARM_BASE, 1)
                self.interface.write(self.bank.get_base() + REC_ARM_BASE, 0)
index 192ce383c1e37438185cf3ee4d20a9c13b057803..481a1238877222faba1ac32a5d4fb8f5996d9adb 100644 (file)
@@ -40,6 +40,25 @@ class VcdDat(list):
                else:
                        raise KeyError
 
+       def decode_rle(self):
+               rle_bit = self[-1]
+               rle_dat = self[:self.width-1]
+
+               dat = VcdDat(self.width)
+               i=0
+               last = 0
+               for d in self:
+                       if rle_bit[i]:
+                               if len(dat) >= 1:
+                                       # FIX ME... why is rle_dat in reverse orderd...
+                                       for j in range(int(dec2bin(rle_dat[i])[::-1],2)):
+                                               dat.append(last)
+                       else:
+                               dat.append(d)
+                               last = d
+                       i +=1
+               return dat 
+
 class Var:
        def __init__(self, name, width, values=[], type="wire", default="x"):
                self.type = type
index d9f086f8c79b57b9c4ef01f26e543d7c3d62e6da..9aaf3d01f0557fdaa3c9768c917fbd3228a45d5d 100644 (file)
@@ -5,7 +5,7 @@ from migen.sim.generic import Simulator, PureSimulable, TopLevel
 from migen.sim.icarus import Runner
 from migen.bus.transactions import *
 
-from miscope import recorder
+from miscope.recorder import *
 
 arm_done = False
 dat = 0
@@ -14,23 +14,28 @@ rec_done = False
 
 dat_rdy = False
 
+rec_size = 128
+
 def csr_transactions():
 
-       #Reset
-       yield TWrite(0, 1)
-       yield TWrite(0, 0)
+       # Reset
+       yield TWrite(REC_RST_BASE, 1)
+       yield TWrite(REC_RST_BASE, 0)
+
+       # RLE
+       yield TWrite(REC_RLE_BASE, 1)
        
-       #Size
-       yield TWrite(3, 0)
-       yield TWrite(4, 32)
+       # Size
+       yield TWrite(REC_SIZE_BASE + 0, 0)
+       yield TWrite(REC_SIZE_BASE + 1, rec_size)
        
-       #Offset
-       yield TWrite(5, 0)
-       yield TWrite(6, 0)
+       # Offset
+       yield TWrite(REC_OFFSET_BASE + 0, 0)
+       yield TWrite(REC_OFFSET_BASE + 1, 0)
        
-       #Arm
-       yield TWrite(1, 1)
-       yield TWrite(1, 0)
+       # Arm
+       yield TWrite(REC_ARM_BASE, 1)
+       yield TWrite(REC_ARM_BASE, 0)
        
        for t in range(10):
                yield None
@@ -43,14 +48,14 @@ def csr_transactions():
                yield None
 
        global dat_rdy
-       for t in range(32):
-               yield TWrite(7, 1)
+       for t in range(rec_size):
+               yield TWrite(REC_READ_BASE, 1)
                dat_rdy = False
-               yield TWrite(7, 0)
-               yield TRead(8)
-               yield TRead(9)
-               yield TRead(10)
-               yield TRead(11)
+               yield TWrite(REC_READ_BASE, 0)
+               yield TRead(REC_READ_DATA_BASE + 0)
+               yield TRead(REC_READ_DATA_BASE + 1)
+               yield TRead(REC_READ_DATA_BASE + 2)
+               yield TRead(REC_READ_DATA_BASE + 3)
                dat_rdy = True
 
        dat_rdy = False
@@ -63,7 +68,7 @@ def main():
        csr_master0 = csr.Initiator(csr_transactions())
 
        # Recorder
-       recorder0 = recorder.Recorder(32, 1024)
+       recorder0 = Recorder(32, 1024)
        
        # Csr Interconnect
        csrcon0 = csr.Interconnect(csr_master0.bus,
@@ -79,16 +84,15 @@ def main():
                        arm_done = False
 
                global dat
-               s.wr(recorder0.dat,dat)
+               s.wr(recorder0.dat, dat//5)
                dat += 1
                        
                global rec_done
-               if s.rd(recorder0.sequencer.rec_done) == 1:
+               if s.rd(recorder0.sequencer.enable) == 0:
                        rec_done = True
                
                if dat_rdy:
                        print("%08X" %s.rd(recorder0._pull_dat.field.w))
-               
 
        # Simulation
        def end_simulation(s):
index 8ad225e2e40814bdee61ff9a3f53f8854d91fc55..5b2107d8a88f274370ff84031e3b35f756fa063f 100644 (file)
@@ -5,7 +5,8 @@ from migen.sim.generic import Simulator, PureSimulable, TopLevel
 from migen.sim.icarus import Runner
 from migen.bus.transactions import *
 
-from miscope import trigger, recorder
+from miscope.trigger import *
+from miscope.recorder import *
 from miscope.tools.truthtable import *
 from miscope.tools.vcd import *
 
@@ -15,7 +16,8 @@ RECORDER_ADDR = 0x0200
 rec_done = False
 dat_rdy  = False
 
-dat_vcd = []
+dat_vcd = VcdDat(32)
+rec_size = 64
 
 def term_prog(off, dat):
        for i in range(4):
@@ -62,20 +64,23 @@ def csr_transactions(trigger0, recorder0):
        # Recorder Prog
        ##############################
        #Reset
-       yield TWrite(recorder0.address + 0,  1)
-       yield TWrite(recorder0.address + 0,  0)
+       yield TWrite(recorder0.address + REC_RST_BASE,  1)
+       yield TWrite(recorder0.address + REC_RST_BASE,  0)
+
+       # RLE
+       yield TWrite(REC_RLE_BASE, 0)
        
        #Size
-       yield TWrite(recorder0.address + 3,  0)
-       yield TWrite(recorder0.address + 4, 64)
+       yield TWrite(recorder0.address + REC_SIZE_BASE + 0,  0)
+       yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, rec_size)
        
        #Offset
-       yield TWrite(recorder0.address + 5,   0)
-       yield TWrite(recorder0.address + 6,  16)
+       yield TWrite(recorder0.address + REC_OFFSET_BASE + 0,   0)
+       yield TWrite(recorder0.address + REC_OFFSET_BASE + 1,  16)
 
        #Arm
-       yield TWrite(recorder0.address + 1,  1)
-       yield TWrite(recorder0.address + 1,  0)
+       yield TWrite(recorder0.address + REC_ARM_BASE,  1)
+       yield TWrite(recorder0.address + REC_ARM_BASE,  0)
 
        # Wait Record to be done
        ##############################
@@ -86,14 +91,14 @@ def csr_transactions(trigger0, recorder0):
        # Read recorded data
        ##############################
        global dat_rdy  
-       for t in range(64):
-               yield TWrite(recorder0.address + 7, 1)
+       for t in range(rec_size):
+               yield TWrite(recorder0.address + REC_READ_BASE, 1)
                dat_rdy = False
-               yield TWrite(recorder0.address + 7, 0)
-               yield TRead(recorder0.address + 8)
-               yield TRead(recorder0.address + 9)
-               yield TRead(recorder0.address + 10)
-               yield TRead(recorder0.address + 11)
+               yield TWrite(recorder0.address + REC_READ_BASE, 0)
+               yield TRead(recorder0.address + REC_READ_DATA_BASE + 0)
+               yield TRead(recorder0.address + REC_READ_DATA_BASE + 1)
+               yield TRead(recorder0.address + REC_READ_DATA_BASE + 2)
+               yield TRead(recorder0.address + REC_READ_DATA_BASE + 3)
                dat_rdy = True
 
        dat_rdy = False
@@ -108,14 +113,14 @@ trig_sig_val = 0
 def main():
 
        # Trigger
-       term0 = trigger.Term(32)
-       term1 = trigger.Term(32)
-       term2 = trigger.Term(32)
-       term3 = trigger.Term(32)
-       trigger0 = trigger.Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR)
+       term0 = Term(32)
+       term1 = Term(32)
+       term2 = Term(32)
+       term3 = Term(32)
+       trigger0 = Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR)
        
        # Recorder
-       recorder0 = recorder.Recorder(32, 1024, address=RECORDER_ADDR)
+       recorder0 = Recorder(32, 1024, address=RECORDER_ADDR)
        
        # Csr Master
        csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0))
@@ -146,7 +151,7 @@ def main():
        # Recorder Data
        def recorder_data(s):
                global rec_done
-               if s.rd(recorder0.sequencer.rec_done) == 1:
+               if s.rd(recorder0.sequencer.done) == 1:
                        rec_done = True
                
                global dat_rdy
@@ -160,7 +165,7 @@ def main():
        def end_simulation(s):
                s.interrupt = csr_master0.done
                myvcd = Vcd()
-               myvcd.add(Var("wire", 32, "trig_dat", dat_vcd))
+               myvcd.add(Var("trig_dat", 32, dat_vcd))
                f = open("tb_miscope_out.vcd", "w")
                f.write(str(myvcd))
                f.close()