clean up/fixes

This commit is contained in:
Florent Kermarrec 2013-03-21 12:23:44 +01:00
parent db1ceccca1
commit b1cbfe2326
16 changed files with 452 additions and 185 deletions

35
README
View File

@ -6,38 +6,41 @@
Copyright 2012 / Florent Kermarrec / florent@enjoy-digital.fr
miscope
Miscope
--------------------------------------------------------------------------------
[> miscope
[> Miscope
------------
miscope is a small logic analyzer to be embedded in an FPGA.
Miscope is a small logic analyzer to embed in an FPGA.
While free vendor toolchains are generally used by beginners or for prototyping
(situations where having a logic analyser in the design is generally very
helpful) free toolchains are always provided without the proprietary logic
analyzer solution... :(
(situations where having a logic analyser in the design is generally helpful)
free toolchains are always provided without the proprietary logic analyzer
solution... :(
Based on Migen, miscope aims to provide a free, portable and flexible
Based on Migen, Miscope aims to provide a free, portable and flexible
alternative to vendor's solutions!
[> Specification:
miscope provides Migen cores to be embedded in the design and Python drivers to
control the logic analyzer from the Host. miscope automatically interconnects
all cores to the CSR bus. When using Python on the Host, no needs to worry about
cores register mapping, importing miscope project gives you direct access to
all the cores!
Miscope provides Migen cores to embed in the design and Python drivers to control
the logic analyzer from the Host. Miscope automatically interconnects all cores
to a CSR bus. When using Python on the Host, no needs to worry aboutcores register
mapping, importing miscope project gives you direct access to all the cores!
miscope produces .vcd output files to be analyzed in your favorite waveform viewer.
Miscope produces .vcd output files to be analyzed in your favorite waveform viewer.
Since Miscope also provides an Uart2Csr bridge, you only need 2 external Rx/Tx pins
to be ready to debug!
[> Status:
Refactoring in progress...
Miio & Mila working on board with standard term.
RangeDetector and EdgeDector terms not tested.
[> Examples:
test_MigIo : Led & Switch Test controlled by Python Host.
test_MigLa : Logic Analyzer controlled by Python Host.
test_Miio : Led & Switch Test controlled by Python Host.
test_Miia : Logic Analyzer controlled by Python Host.
[> Contact
E-mail: florent@enjoy-digital.fr

View File

@ -8,7 +8,7 @@ from miscope.bridges.uart2csr.tools.uart2Csr import *
csr = Uart2Csr(3,115200)
# Csr Addr
MIIO_ADDR = 0x0000
MIIO_ADDR = 0x00
# Miscope Configuration
miio = miio.MiIo(MIIO_ADDR, 8, "IO", csr)

View File

@ -0,0 +1,68 @@
from miscope import trigger, recorder, miio, mila
from miscope.tools.truthtable import *
from miscope.tools.vcd import *
from miscope.bridges.uart2csr.tools.uart2Csr import *
#==============================================================================
# P A R A M E T E R S
#==============================================================================
# Csr Addr
MILA_ADDR = 0x01
csr = Uart2Csr(3, 115200, debug=False)
# Mila Param
trig_w = 16
dat_w = 16
rec_size = 512
rec_offset = 32
# Miscope Configuration
# MiLa
term = trigger.Term(trig_w)
trigger = trigger.Trigger(trig_w, [term])
recorder = recorder.Recorder(dat_w, rec_size)
mila = mila.MiLa(MILA_ADDR, trigger, recorder, csr)
#==============================================================================
# T E S T M I G L A
#==============================================================================
dat_vcd = VcdDat(dat_w)
def capture(size):
global trigger
global recorder
global dat_vcd
sum_tt = gen_truth_table("term")
mila.trigger.sum.write(sum_tt)
mila.recorder.reset()
recorder.size(rec_size)
mila.recorder.offset(rec_offset)
mila.recorder.arm()
print("-Recorder [Armed]")
print("-Waiting Trigger...", end=' ')
while(not mila.recorder.is_done()):
time.sleep(0.1)
print("[Done]")
print("-Receiving Data...", end=' ')
sys.stdout.flush()
dat_vcd += mila.recorder.read(size)
print("[Done]")
print("Capturing ...")
print("----------------------")
term.write(0x0000, 0xFFFF)
capture(rec_size)
mila_layout = [
("freqgen", 1),
("event_rising", 1),
("event_falling", 1),
("cnt", 8),
]
myvcd = Vcd()
myvcd.add_from_layout(mila_layout, dat_vcd)
myvcd.write("test_mila.vcd")

View File

@ -7,7 +7,7 @@
#
# Copyright 2013 / Florent Kermarrec / florent@enjoy-digital.fr
#
# miscope miio example on De0 Nano
# miscope example on De0 Nano
# --------------------------------
################################################################################
@ -18,8 +18,9 @@ from migen.fhdl.structure import *
from migen.fhdl.module import *
from migen.bus import csr
from miscope import miio
from miscope import trigger, recorder, miio, mila
from miscope.bridges import uart2csr
from miscope.tools.misc import *
from timings import *
@ -31,7 +32,13 @@ from timings import *
clk_freq = 50*MHz
# Csr Addr
MIIO0_ADDR = 0x0000
MIIO_ADDR = 0x00
MILA_ADDR = 0x01
# Mila Param
trig_w = 16
dat_w = 16
rec_size = 4096
#==============================================================================
# M I S C O P E E X A M P L E
@ -39,7 +46,14 @@ MIIO0_ADDR = 0x0000
class SoC(Module):
def __init__(self):
# MiIo
self.submodules.miio = miio.MiIo(MIIO0_ADDR, 8, "IO")
self.submodules.miio = miio.MiIo(MIIO_ADDR, 8, "IO")
# MiLa
self.submodules.term = trigger.Term(trig_w)
self.submodules.trigger = trigger.Trigger(trig_w, [self.term])
self.submodules.recorder = recorder.Recorder(dat_w, rec_size)
self.submodules.mila = mila.MiLa(MILA_ADDR, self.trigger, self.recorder)
# Uart2Csr
self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200)
@ -47,15 +61,43 @@ class SoC(Module):
# Csr Interconnect
self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr,
[
self.miio.bank.bus
self.miio.bank.bus,
self.trigger.bank.bus,
self.recorder.bank.bus
])
# Led
self.led = Signal(8)
# Misc
self.cnt = Signal(9)
self.submodules.freqgen = FreqGen(clk_freq, 500*KHz)
self.submodules.eventgen_rising = EventGen(self.freqgen.o, RISING_EDGE, clk_freq, 100*ns)
self.submodules.eventgen_falling = EventGen(self.freqgen.o, FALLING_EDGE, clk_freq, 100*ns)
###
#
# Miio
#
# Output
self.comb += self.led.eq(self.miio.o)
# Input
self.comb += self.miio.i.eq(0x5A)
self.comb += self.miio.i.eq(self.miio.o)
#
# Mila
#
self.comb +=[
self.mila.trig[0].eq(self.freqgen.o),
self.mila.trig[1].eq(self.eventgen_rising.o),
self.mila.trig[2].eq(self.eventgen_falling.o),
self.mila.trig[3:11].eq(self.cnt),
self.mila.dat[0].eq(self.freqgen.o),
self.mila.dat[1].eq(self.eventgen_rising.o),
self.mila.dat[2].eq(self.eventgen_falling.o),
self.mila.dat[3:11].eq(self.cnt),
]
self.sync += self.cnt.eq(self.cnt+1)

View File

@ -53,13 +53,4 @@ class Uart2Spi:
elif endianess == "LE":
self.write(addr+words-1-i, (data>>(8*i)) & 0xFF)
if self.debug:
print("WR %08X @ %04X" %(data, addr))
def main():
csr = Uart2Spi(1,115200)
for i in range(100):
csr.write(0x0000,i)
print(csr.read(0x0000))
if __name__ == '__main__':
main()
print("WR %08X @ %04X" %(data, addr))

View File

@ -75,8 +75,8 @@ class Uart2Csr(Module):
self.sync += If(fsm.ongoing(fsm.IDLE) & uart.rx_ev, cmd.eq(uart.rx_dat))
#
# Get burst length
#
# Get burst length
#
fsm.act(fsm.GET_BL,
If(get_bl_done,
fsm.next_state(fsm.GET_ADDR)

View File

@ -3,6 +3,7 @@ import time
import serial
from struct import *
import time
from migen.fhdl.structure import *
WRITE_CMD = 0x01
READ_CMD = 0x02
@ -36,7 +37,19 @@ class Uart2Csr:
return values[0]
else:
return values
def read_n(self, addr, n, endianess = "LE"):
r = 0
words = int(2**bits_for(n-1)/8)
for i in range(words):
if endianess == "BE":
r += self.read(addr+i)<<(8*i)
elif endianess == "LE":
r += self.read(addr+words-1-i)<<(8*i)
if self.debug:
print("RD @ %04X" %addr)
return r
def write(self, addr, data):
if isinstance(data, list):
burst_length = len(data)
@ -45,9 +58,9 @@ class Uart2Csr:
write_b(self.uart, WRITE_CMD)
write_b(self.uart, burst_length)
self.uart.write([(addr & 0xff000000) >> 24,
(addr & 0x00ff0000) >> 16,
(addr & 0x0000ff00) >> 8,
(addr & 0x000000ff)])
(addr & 0x00ff0000) >> 16,
(addr & 0x0000ff00) >> 8,
(addr & 0x000000ff)])
if isinstance(data, list):
for i in range(len(data)):
write_b(self.uart, data[i])
@ -56,4 +69,14 @@ class Uart2Csr:
else:
write_b(self.uart, data)
if self.debug:
print("WR %02X @ %08X" %(data, addr))
print("WR %02X @ %08X" %(data, addr))
def write_n(self, addr, data, n, endianess = "LE"):
words = int(2**bits_for(n-1)/8)
for i in range(words):
if endianess == "BE":
self.write(addr+i, (data>>(8*i)) & 0xFF)
elif endianess == "LE":
self.write(addr+words-1-i, (data>>(8*i)) & 0xFF)
if self.debug:
print("WR %08X @ %04X" %(data, addr))

View File

@ -38,7 +38,7 @@ class MiIo:
#Driver
#
def write(self, data):
self.interface.write(self.address, data)
self.interface.write(self.bank.get_base(), data)
def read(self):
return self.interface.read(self.address + self.words)
return self.interface.read(self.bank.get_base() + self.words)

View File

@ -17,16 +17,18 @@ class MiLa:
self.set_address(address)
self.set_interface(interface)
def set_address(self, address):
self.address = address
self.trigger.set_address(self.address)
self.recorder.set_address(self.address + 0x01)
def set_interface(self, interface):
self.interface = interface
self.trigger.set_interface(interface)
self.recorder.set_interface(interface)
def set_address(self, address):
self.address = address
self.trigger.set_address(self.address)
self.recorder.set_address(self.address + 0x0200)
def get_fragment(self):
comb =[

View File

@ -6,6 +6,8 @@ from migen.bank.description import *
from migen.genlib.misc import optree
from migen.genlib.fsm import *
from miscope.tools.misc import RisingEdge
class Storage:
#
# Definition
@ -49,14 +51,6 @@ class Storage:
self.pull_dat.eq(self._pull_port.dat_r)
]
size_minus_offset = Signal(self.depth_width)
comb += [size_minus_offset.eq(self.size-self.offset)]
idle_rising = Signal()
idle_ongoing = Signal()
active_rising = Signal()
active_ongoing = Signal()
# FSM
fsm = FSM("IDLE", "ACTIVE")
@ -64,32 +58,28 @@ class Storage:
fsm.act(fsm.IDLE,
If(self.start,
fsm.next_state(fsm.ACTIVE),
active_rising.eq(1)
),
idle_ongoing.eq(1)
)
)
# Active
fsm.act(fsm.ACTIVE,
If(self.done | self.rst,
fsm.next_state(fsm.IDLE),
idle_rising.eq(1)
),
active_ongoing.eq(1)
)
)
sync =[
If(active_rising,
If(fsm.entering(fsm.ACTIVE),
self._push_ptr_stop.eq(self._push_ptr + self.size - self.offset),
self._pull_ptr.eq(self._push_ptr-self.offset-1)
self._pull_ptr.eq(self._push_ptr-self.offset - 1)
).Else(
If(self.pull_stb, self._pull_ptr.eq(self._pull_ptr+1))
If(self.pull_stb, self._pull_ptr.eq(self._pull_ptr + 1))
),
If(self.push_stb, self._push_ptr.eq(self._push_ptr+1)),
If(self.push_stb, self._push_ptr.eq(self._push_ptr + 1)),
]
comb +=[self.done.eq((self._push_ptr == self._push_ptr_stop) & active_ongoing)]
comb +=[self.done.eq((self._push_ptr == self._push_ptr_stop) & fsm.ongoing(fsm.ACTIVE))]
return Fragment(comb, sync, specials={self._mem})
return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment()
class Sequencer:
#
@ -120,11 +110,6 @@ class Sequencer:
self.enable = Signal()
def get_fragment(self):
idle_rising = Signal()
idle_ongoing = Signal()
active_rising = Signal()
active_ongoing = Signal()
# FSM
fsm = FSM("IDLE", "ACTIVE")
@ -133,53 +118,46 @@ class Sequencer:
fsm.act(fsm.IDLE,
If(self.ctl_arm,
fsm.next_state(fsm.ACTIVE),
active_rising.eq(1)
),
idle_ongoing.eq(1)
)
)
# Active
fsm.act(fsm.ACTIVE,
If(self.rec_done,
If(self.rec_done | self.ctl_rst,
fsm.next_state(fsm.IDLE),
idle_rising.eq(1)
),
active_ongoing.eq(1)
self.enable.eq(1)
)
comb =[self.enable.eq(active_ongoing)]
# trig_hit rising_edge
_hit_d = Signal()
_hit_rising = Signal()
sync =[_hit_d.eq(self.hit)]
comb +=[_hit_rising.eq(self.hit & ~_hit_d)]
hit_rising = RisingEdge(self.hit)
# connexion
comb = [
self.rec_offset.eq(self.ctl_offset),
self.rec_size.eq(self.ctl_size),
self.rec_start.eq(self.enable & _hit_rising),
self.ctl_done.eq(~self.enable)
self.rec_start.eq(self.enable & hit_rising.o),
self.ctl_done.eq(~self.enable),
]
return Fragment(comb, sync)
return Fragment(comb) + fsm.get_fragment() + hit_rising.get_fragment()
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 = 0x09
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
class Recorder:
#
# Definition
#
def __init__(self, width, depth, address = 0x0000, interface = None):
def __init__(self, width, depth, address=0x0000, interface=None):
self.width = width
self.depth = depth
self.depth_width = bits_for(self.depth)
self.depth_width = bits_for(self.depth-1)
self.storage = Storage(self.width, self.depth)
self.sequencer = Sequencer(self.depth)
@ -188,19 +166,17 @@ class Recorder:
self._rst = RegisterField("rst", reset=1)
self._arm = RegisterField("arm", reset=0)
self._done = RegisterField("done", reset=0, access_bus=READ_ONLY,
access_dev=WRITE_ONLY)
access_dev=WRITE_ONLY)
self._size = RegisterField("size", self.depth_width, reset=1)
self._offset = RegisterField("offset", self.depth_width, reset=1)
self._pull_stb = RegisterField("pull_stb", reset=0)
self._pull_dat = RegisterField("pull_dat", self.width, reset=1,
access_bus=READ_ONLY, access_dev=WRITE_ONLY)
access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self.regs = [self._rst, self._arm, self._done, self._size, self._offset,
self._pull_stb, self._pull_dat]
self.bank = csrgen.Bank(self.regs, address=address)
self._pull_stb, self._pull_dat]
# set address / interface
self.set_address(address)
@ -212,19 +188,14 @@ class Recorder:
def set_address(self, address):
self.address = address
self.bank = csrgen.Bank(self.regs,address=self.address)
self.bank = csrgen.Bank(self.regs, address=self.address)
def set_interface(self, interface):
self.interface = interface
def get_fragment(self):
_pull_stb_d = Signal()
_pull_stb_rising = Signal()
sync = [
_pull_stb_d.eq(self._pull_stb.field.r),
_pull_stb_rising.eq(self._pull_stb.field.r & ~_pull_stb_d)
]
_pull_stb_rising = RisingEdge(self._pull_stb.field.r)
# Bank <--> Storage / Sequencer
comb = [
@ -237,7 +208,7 @@ class Recorder:
self._done.field.w.eq(self.sequencer.ctl_done),
self.storage.pull_stb.eq(_pull_stb_rising),
self.storage.pull_stb.eq(_pull_stb_rising.o),
self._pull_dat.field.w.eq(self.storage.pull_dat)
]
@ -254,33 +225,34 @@ class Recorder:
self.storage.push_dat.eq(self.dat)
]
return self.bank.get_fragment() + Fragment(comb, sync) +\
self.storage.get_fragment() + self.sequencer.get_fragment()
return self.bank.get_fragment() + Fragment(comb) +\
self.storage.get_fragment() + self.sequencer.get_fragment() +\
_pull_stb_rising.get_fragment()
#
#Driver
#
def reset(self):
self.interface.write(self.address + REC_RST_BASE, 1)
self.interface.write(self.address + REC_RST_BASE, 0)
self.interface.write(self.bank.get_base() + REC_RST_BASE, 1)
self.interface.write(self.bank.get_base() + REC_RST_BASE, 0)
def arm(self):
self.interface.write(self.address + REC_ARM_BASE, 1)
self.interface.write(self.address + REC_ARM_BASE, 0)
self.interface.write(self.bank.get_base() + REC_ARM_BASE, 1)
self.interface.write(self.bank.get_base() + REC_ARM_BASE, 0)
def is_done(self):
return self.interface.read(self.address + REC_DONE_BASE) == 1
return self.interface.read(self.bank.get_base() + REC_DONE_BASE) == 1
def size(self, dat):
self.interface.write_n(self.address + REC_SIZE_BASE, dat, 16)
self.interface.write_n(self.bank.get_base() + REC_SIZE_BASE, dat, 16)
def offset(self, dat):
self.interface.write_n(self.address + REC_OFFSET_BASE, dat, 16)
self.interface.write_n(self.bank.get_base() + REC_OFFSET_BASE, dat, 16)
def read(self, size):
r = []
for i in range(size):
self.interface.write(self.address + REC_READ_BASE, 1)
self.interface.write(self.address + REC_READ_BASE, 0)
r.append(self.interface.read_n(self.address + REC_READ_DATA_BASE, self.width))
self.interface.write(self.bank.get_base() + REC_READ_BASE, 1)
self.interface.write(self.bank.get_base() + REC_READ_BASE, 0)
r.append(self.interface.read_n(self.bank.get_base() + REC_READ_DATA_BASE, self.width))
return r

111
miscope/tools/misc.py Normal file
View File

@ -0,0 +1,111 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
class RisingEdge(Module):
def __init__(self, i=None, o=None, domain="sys"):
self.i = ifthenelse(i, i, Signal())
self.o = ifthenelse(o, o, Signal())
####
i_d = Signal()
sync =[i_d.eq(self.i)]
self.comb +=[self.o.eq(self.i & ~i_d)]
self._fragment += Fragment(sync={domain : sync})
class FallingEdge(Module):
def __init__(self, i=None, o=None, domain="sys"):
self.i = ifthenelse(i, i, Signal())
self.o = ifthenelse(o, o, Signal())
####
i_d = Signal()
sync =[i_d.eq(self.i)]
self.comb +=[self.o.eq(~self.i & i_d)]
self._fragment += Fragment(sync={domain : sync})
class FreqGen(Module):
def __init__(self, clk_freq, freq, o=None):
cnt_max = int(clk_freq/freq/2)
width = bits_for(cnt_max)
self.o = ifthenelse(o, o, Signal())
####
cnt = Signal(width)
self.sync += [
If(cnt >= cnt_max,
cnt.eq(0),
self.o.eq(~self.o)
).Else(
cnt.eq(cnt+1)
)
]
RISING_EDGE = 1
FALLING_EDGE = 0
class EventGen(Module):
def __init__(self, i=None, level=1, clk_freq=0, length=1, o=None):
cnt_max = int(length*clk_freq)
width = bits_for(cnt_max)
self.i = ifthenelse(i, i, Signal())
self.o = ifthenelse(o, o, Signal())
###
cnt = Signal(width)
i_edge = Signal()
if level == RISING_EDGE:
self.submodules += RisingEdge(self.i, i_edge)
elif level == FALLING_EDGE:
self.submodules += FallingEdge(self.i, i_edge)
self.sync += [
If(i_edge == 1,
cnt.eq(0),
self.o.eq(1)
).Elif(cnt >= cnt_max,
self.o.eq(0)
).Else(
cnt.eq(cnt+1)
),
]
class PwmGen(Module):
def __init__(self, width, o=None):
self.ratio = Signal(width)
self.o = ifthenelse(o, o, Signal())
###
cnt = Signal(width)
self.sync += [
If(cnt == 0,
self.o.eq(1)
).Elif(cnt >= self.ratio,
self.o.eq(0)
),
cnt.eq(cnt+1)
]
class Cascade(Module):
def __init__(self, i=None, elements=None, o=None):
self.i = ifthenelse(i, i, Signal())
self.o = ifthenelse(o, o, Signal())
self.comb +=[elements[0].i.eq(self.i)]
self.comb +=[elements[i+1].i.eq(elements[i].o) for i in range(len(elements)-1)]
self.comb +=[self.o.eq(elements[len(elements)-1].o)]
class PwrOnRst(Module):
def __init__(self, width, rst=None, simulation=False):
self.rst = ifthenelse(rst, rst, Signal())
###
cnt = Signal(width)
sync_no_reset = [If(self.rst, cnt.eq(cnt+1))]
if not simulation:
self.comb +=[
If(cnt >= (2**width-1),
self.rst.eq(0)
).Else(
self.rst.eq(1)
)
]
else:
self.comb += self.rst.eq(0)
self._fragment += Fragment(sync={"sys_no_reset" : sync_no_reset})

View File

@ -3,10 +3,10 @@ import datetime
from miscope.tools.conv import *
def get_bits(values, width, low, high =None):
def get_bits(values, width, low, high=None):
r = []
for val in values:
t = dec2bin(val,width)[::-1]
t = dec2bin(val, width)[::-1]
if high == None:
t = t[low]
else:
@ -16,8 +16,32 @@ def get_bits(values, width, low, high =None):
r.append(t)
return r
class VcdDat(list):
def __init__(self, width):
self.width = width
def __getitem__(self, key):
if isinstance(key, int):
return get_bits(self, self.width, key)
elif isinstance(key, slice):
if key.start != None:
start = key.start
else:
start = 0
if key.stop != None:
stop = key.stop
else:
stop = self.width
if stop > self.width:
stop = self.width
if key.step != None:
raise KeyError
return get_bits(self, self.width, start, stop)
else:
raise KeyError
class Var:
def __init__(self,type , width , name, values=[], default="x"):
def __init__(self, name, width, values=[], type="wire", default="x"):
self.type = type
self.width = width
self.name = name
@ -36,7 +60,7 @@ class Var:
try :
if self.values[cnt+1] != self.val:
r += "b"
r += dec2bin(self.values[cnt+1], self.width)
r += dec2bin(self.values[cnt+1], self.width)[::-1]
r += " "
r += self.vcd_id
r += "\n"
@ -44,10 +68,9 @@ class Var:
except :
return r
return r
class Vcd:
def __init__(self,timescale = "1ps", comment = ""):
def __init__(self, timescale="1ps", comment=""):
self.timescale = timescale
self.comment = comment
self.vars = []
@ -58,6 +81,12 @@ class Vcd:
var.set_vcd_id(self.vcd_id)
self.vcd_id = chr(ord(self.vcd_id)+1)
self.vars.append(var)
def add_from_layout(self, layout, var):
i=0
for s, n in layout:
self.add(Var(s, n, var[i:i+n]))
i += n
def __len__(self):
l = 0
@ -77,7 +106,6 @@ class Vcd:
r += c
return r
def p_date(self):
now = datetime.datetime.now()
r = "$date\n"
@ -110,6 +138,7 @@ class Vcd:
r += self.timescale
r += " $end\n"
return r
def p_vars(self):
r = ""
for var in self.vars:
@ -151,7 +180,6 @@ class Vcd:
r += self.change()
self.cnt += 1
return r
def __repr__(self):
r = ""
@ -174,12 +202,12 @@ class Vcd:
def main():
myvcd = Vcd()
myvcd.add(Var("wire", 1, "foo1", [0,1,0,1,0,1]))
myvcd.add(Var("wire", 2, "foo2", [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
myvcd.add(Var("wire", 3, "foo3"))
myvcd.add(Var("wire", 4, "foo4"))
myvcd.add(Var(1, "foo1", [0,1,0,1,0,1]))
myvcd.add(Var(2, "foo2", [1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]))
myvcd.add(Var(3, "foo3"))
myvcd.add(Var(4, "foo4"))
ramp = [i%128 for i in range(1024)]
myvcd.add(Var("wire", 16, "ramp", ramp))
myvcd.add(Var(16, "ramp", ramp))
print(myvcd)
if __name__ == '__main__':

View File

@ -55,8 +55,8 @@ class Term:
def write(self, dat, mask=None):
if mask is None:
mask = (2**self.width)-1
self.interface.write_n(self.reg_p.base, mask, self.width)
self.interface.write_n(self.reg_p.base + self.reg_p.words, dat, self.width)
self.interface.write_n(self.reg_p.base, mask, self.width)
class RangeDetector:
#
@ -144,13 +144,13 @@ class EdgeDetector:
# Falling Edge
if "F" in self.mode:
comb += [self.fo.eq(self.f_mask & (~ self.i) & self.i_d)]
comb += [self.fo.eq(self.f_mask & (~self.i) & self.i_d)]
else:
comb += [self.fo.eq(0)]
# Both
if "B" in self.mode:
comb += [self.bo.eq(self.b_mask & self.i != self.i_d)]
comb += [self.bo.eq((self.b_mask & self.i) != self.i_d)]
else:
comb += [self.bo.eq(0)]
@ -243,8 +243,8 @@ class Sum:
we = 1<<17
dat = val<<16
addr = i
self.interface.write_n(self.reg_p.base, we + dat + addr, self.reg_size)
self.interface.write_n(self.reg_p.base, dat + addr, self.reg_size)
self.interface.write_n(self.reg_p.base, we + dat + addr, self.reg_p.size)
self.interface.write_n(self.reg_p.base, dat + addr, self.reg_p.size)
class Trigger:
#
@ -283,11 +283,11 @@ class Trigger:
def set_address(self, address):
self.address = address
self.bank = csrgen.Bank(self.regs,address=self.address)
self.bank = csrgen.Bank(self.regs, address=self.address)
for port in self.ports:
port.reg_p.base = self.bank.get_base(port.reg_p.name)
self.sum.reg_p.base = self.bank.get_base(self.sum.reg_p.name)
def set_interface(self, interface):
self.interface = interface
for port in self.ports:

View File

@ -1,5 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl import verilog, autofragment
from migen.fhdl import verilog
from migen.bus import csr
from migen.sim.generic import Simulator, PureSimulable, TopLevel
from migen.sim.icarus import Runner
@ -8,7 +8,7 @@ from migen.bus.transactions import *
from miscope import recorder
arm_done = False
trig_dat = 0
dat = 0
rec_done = False
@ -30,6 +30,7 @@ def csr_transactions():
#Arm
yield TWrite(1, 1)
yield TWrite(1, 0)
for t in range(10):
yield None
@ -62,42 +63,45 @@ def main():
csr_master0 = csr.Initiator(csr_transactions())
# Recorder
recorder0 = recorder.Recorder(0, 32, 1024)
recorder0 = recorder.Recorder(32, 1024)
# Csr Interconnect
csrcon0 = csr.Interconnect(csr_master0.bus,
[
recorder0.bank.interface
recorder0.bank.bus
])
# Recorder Data
def recorder_data(s):
global arm_done
if arm_done:
s.wr(recorder0.trig_hit, 1)
s.wr(recorder0.hit, 1)
arm_done = False
global trig_dat
s.wr(recorder0.trig_dat,trig_dat)
trig_dat += 1
global dat
s.wr(recorder0.dat,dat)
dat += 1
global rec_done
if s.rd(recorder0.sequencer.rec_done) == 1:
rec_done = True
if dat_rdy:
print("%08X" %s.rd(recorder0._get_dat.field.w))
print("%08X" %s.rd(recorder0._pull_dat.field.w))
# Simulation
def end_simulation(s):
s.interrupt = csr_master0.done
fragment = autofragment.from_local()
fragment = csr_master0.get_fragment()
fragment += recorder0.get_fragment()
fragment += csrcon0.get_fragment()
fragment += Fragment(sim=[end_simulation])
fragment += Fragment(sim=[recorder_data])
sim = Simulator(fragment, Runner(), TopLevel("tb_RecorderCsr.vcd"))
sim = Simulator(fragment, TopLevel("tb_RecorderCsr.vcd"))
sim.run(10000)
main()
print("Sim Done")
input()

View File

@ -1,5 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl import verilog, autofragment
from migen.fhdl import verilog
from migen.bus import csr
from migen.sim.generic import Simulator, PureSimulable, TopLevel
from migen.sim.icarus import Runner
@ -27,10 +27,14 @@ csr_done = False
def csr_transactions():
term_trans = []
term_trans += [term_prog(0x04 ,0xDEADBEEF)]
term_trans += [term_prog(0x08 ,0xCAFEFADE)]
term_trans += [term_prog(0x0C ,0xDEADBEEF)]
term_trans += [term_prog(0x10 ,0xCAFEFADE)]
term_trans += [term_prog(0x04+0 ,0xFFFFFFFF)]
term_trans += [term_prog(0x04+4 ,0xDEADBEEF)]
term_trans += [term_prog(0x04+8 ,0xFFFFFFFF)]
term_trans += [term_prog(0x04+12 ,0xCAFEFADE)]
term_trans += [term_prog(0x04+16 ,0xFFFFFFFF)]
term_trans += [term_prog(0x04+20 ,0xDEADBEEF)]
term_trans += [term_prog(0x04+24 ,0xFFFFFFFF)]
term_trans += [term_prog(0x04+28 ,0xCAFEFADE)]
for t in term_trans:
for r in t:
yield r
@ -67,12 +71,12 @@ def main():
term1 = trigger.Term(32)
term2 = trigger.Term(32)
term3 = trigger.Term(32)
trigger0 = trigger.Trigger(0, 32, 64, [term0, term1, term2, term3])
trigger0 = trigger.Trigger(32, [term0, term1, term2, term3])
# Csr Interconnect
csrcon0 = csr.Interconnect(csr_master0.bus,
[
trigger0.bank.interface
trigger0.bank.bus
])
# Term Test
@ -88,13 +92,20 @@ def main():
def end_simulation(s):
s.interrupt = csr_master0.done
fragment = autofragment.from_local()
fragment = csr_master0.get_fragment()
fragment += term0.get_fragment()
fragment += term1.get_fragment()
fragment += term2.get_fragment()
fragment += term3.get_fragment()
fragment += trigger0.get_fragment()
fragment += csrcon0.get_fragment()
fragment += Fragment(sim=[end_simulation])
fragment += Fragment(sim=[term_stimuli])
sim = Simulator(fragment, Runner(), TopLevel("tb_TriggerCsr.vcd"))
sim = Simulator(fragment, TopLevel("tb_TriggerCsr.vcd"))
sim.run(2000)
main()
print("Sim Done")
input()

View File

@ -1,5 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl import verilog, autofragment
from migen.fhdl import verilog
from migen.bus import csr
from migen.sim.generic import Simulator, PureSimulable, TopLevel
from migen.sim.icarus import Runner
@ -38,10 +38,14 @@ def csr_transactions(trigger0, recorder0):
# Term Prog
term_trans = []
term_trans += [term_prog(trigger0.ports[0].reg_base, 0x00000000)]
term_trans += [term_prog(trigger0.ports[1].reg_base, 0x00000004)]
term_trans += [term_prog(trigger0.ports[2].reg_base, 0x00000008)]
term_trans += [term_prog(trigger0.ports[3].reg_base, 0x0000000C)]
term_trans += [term_prog(trigger0.ports[0].reg_p.base+0, 0xFFFFFFFF)]
term_trans += [term_prog(trigger0.ports[0].reg_p.base+4, 0x00000000)]
term_trans += [term_prog(trigger0.ports[1].reg_p.base+0, 0xFFFFFFFF)]
term_trans += [term_prog(trigger0.ports[1].reg_p.base+4, 0x00000004)]
term_trans += [term_prog(trigger0.ports[2].reg_p.base+0, 0xFFFFFFFF)]
term_trans += [term_prog(trigger0.ports[2].reg_p.base+4, 0x00000008)]
term_trans += [term_prog(trigger0.ports[3].reg_p.base+0, 0xFFFFFFFF)]
term_trans += [term_prog(trigger0.ports[3].reg_p.base+4, 0x0000000C)]
for t in term_trans:
for r in t:
yield r
@ -50,7 +54,7 @@ def csr_transactions(trigger0, recorder0):
sum_tt = gen_truth_table("term0 | term1 | term2 | term3")
sum_trans = []
for i in range(len(sum_tt)):
sum_trans.append(sum_prog(trigger0.sum.reg_base, i, sum_tt[i]))
sum_trans.append(sum_prog(trigger0.sum.reg_p.base, i, sum_tt[i]))
for t in sum_trans:
for r in t:
yield r
@ -71,6 +75,7 @@ def csr_transactions(trigger0, recorder0):
#Arm
yield TWrite(recorder0.address + 1, 1)
yield TWrite(recorder0.address + 1, 0)
# Wait Record to be done
##############################
@ -107,10 +112,10 @@ def main():
term1 = trigger.Term(32)
term2 = trigger.Term(32)
term3 = trigger.Term(32)
trigger0 = trigger.Trigger(TRIGGER_ADDR, 32, 64, [term0, term1, term2, term3])
trigger0 = trigger.Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR)
# Recorder
recorder0 = recorder.Recorder(RECORDER_ADDR, 32, 1024)
recorder0 = recorder.Recorder(32, 1024, address=RECORDER_ADDR)
# Csr Master
csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0))
@ -118,19 +123,18 @@ def main():
# Csr Interconnect
csrcon0 = csr.Interconnect(csr_master0.bus,
[
trigger0.bank.interface,
recorder0.bank.interface
trigger0.bank.bus,
recorder0.bank.bus
])
trig_sig = Signal(32)
comb = []
comb +=[
trigger0.in_trig.eq(trig_sig)
comb =[
trigger0.trig.eq(trig_sig)
]
comb += [
recorder0.trig_dat.eq(trig_sig),
recorder0.trig_hit.eq(trigger0.hit)
recorder0.dat.eq(trig_sig),
recorder0.hit.eq(trigger0.hit)
]
# Term Test
def term_stimuli(s):
@ -147,9 +151,9 @@ def main():
global dat_rdy
if dat_rdy:
print("%08X" %s.rd(recorder0._get_dat.field.w))
print("%08X" %s.rd(recorder0._pull_dat.field.w))
global dat_vcd
dat_vcd.append(s.rd(recorder0._get_dat.field.w))
dat_vcd.append(s.rd(recorder0._pull_dat.field.w))
# Simulation
@ -157,19 +161,27 @@ def main():
s.interrupt = csr_master0.done
myvcd = Vcd()
myvcd.add(Var("wire", 32, "trig_dat", dat_vcd))
f = open("tb_Miscope_Out.vcd", "w")
f = open("tb_miscope_out.vcd", "w")
f.write(str(myvcd))
f.close()
fragment = autofragment.from_local()
fragment = term0.get_fragment()
fragment += term1.get_fragment()
fragment += term2.get_fragment()
fragment += term3.get_fragment()
fragment += trigger0.get_fragment()
fragment += recorder0.get_fragment()
fragment += csr_master0.get_fragment()
fragment += csrcon0.get_fragment()
fragment += Fragment(comb=comb)
fragment += Fragment(sim=[term_stimuli])
fragment += Fragment(sim=[recorder_data])
fragment += Fragment(sim=[end_simulation])
sim = Simulator(fragment, Runner(),TopLevel("tb_MigScope.vcd"))
sim = Simulator(fragment, TopLevel("tb_miscope.vcd"))
sim.run(2000)
main()
print("Sim Done")
input()