[> Status:
Miio & Mila working on board with standard term.
+RLE working on board.
RangeDetector and EdgeDector terms not tested.
[> Examples:
dat_w = 16
rec_size = 512
rec_offset = 32
+enable_rle = True
# Miscope Configuration
# MiLa
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()
print("-Receiving Data...", end=' ')
sys.stdout.flush()
- dat_vcd += mila.recorder.pull(size)
+ dat_vcd += mila.recorder.pull(rec_size)
print("[Done]")
print("Capturing ...")
("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
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):
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:
#
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)
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
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),
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
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)
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
from migen.sim.icarus import Runner
from migen.bus.transactions import *
-from miscope import recorder
+from miscope.recorder import *
arm_done = False
dat = 0
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
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
csr_master0 = csr.Initiator(csr_transactions())
# Recorder
- recorder0 = recorder.Recorder(32, 1024)
+ recorder0 = Recorder(32, 1024)
# Csr Interconnect
csrcon0 = csr.Interconnect(csr_master0.bus,
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):
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 *
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):
# 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
##############################
# 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
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))
# 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
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()