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 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 While free vendor toolchains are generally used by beginners or for prototyping
(situations where having a logic analyser in the design is generally very (situations where having a logic analyser in the design is generally helpful)
helpful) free toolchains are always provided without the proprietary logic free toolchains are always provided without the proprietary logic analyzer
analyzer solution... :( 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! alternative to vendor's solutions!
[> Specification: [> Specification:
miscope provides Migen cores to be embedded in the design and Python drivers to Miscope provides Migen cores to embed in the design and Python drivers to control
control the logic analyzer from the Host. miscope automatically interconnects the logic analyzer from the Host. Miscope automatically interconnects all cores
all cores to the CSR bus. When using Python on the Host, no needs to worry about to a CSR bus. When using Python on the Host, no needs to worry aboutcores register
cores register mapping, importing miscope project gives you direct access to mapping, importing miscope project gives you direct access to all the cores!
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: [> Status:
Refactoring in progress... Miio & Mila working on board with standard term.
RangeDetector and EdgeDector terms not tested.
[> Examples: [> Examples:
test_MigIo : Led & Switch Test controlled by Python Host. test_Miio : Led & Switch Test controlled by Python Host.
test_MigLa : Logic Analyzer controlled by Python Host. test_Miia : Logic Analyzer controlled by Python Host.
[> Contact [> Contact
E-mail: florent@enjoy-digital.fr E-mail: florent@enjoy-digital.fr

View File

@ -8,7 +8,7 @@ from miscope.bridges.uart2csr.tools.uart2Csr import *
csr = Uart2Csr(3,115200) csr = Uart2Csr(3,115200)
# Csr Addr # Csr Addr
MIIO_ADDR = 0x0000 MIIO_ADDR = 0x00
# Miscope Configuration # Miscope Configuration
miio = miio.MiIo(MIIO_ADDR, 8, "IO", csr) 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 # 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.fhdl.module import *
from migen.bus import csr from migen.bus import csr
from miscope import miio from miscope import trigger, recorder, miio, mila
from miscope.bridges import uart2csr from miscope.bridges import uart2csr
from miscope.tools.misc import *
from timings import * from timings import *
@ -31,7 +32,13 @@ from timings import *
clk_freq = 50*MHz clk_freq = 50*MHz
# Csr Addr # 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 # M I S C O P E E X A M P L E
@ -39,7 +46,14 @@ MIIO0_ADDR = 0x0000
class SoC(Module): class SoC(Module):
def __init__(self): def __init__(self):
# MiIo # 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 # Uart2Csr
self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200) self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200)
@ -47,15 +61,43 @@ class SoC(Module):
# Csr Interconnect # Csr Interconnect
self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr, 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 # Led
self.led = Signal(8) 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 # Output
self.comb += self.led.eq(self.miio.o) self.comb += self.led.eq(self.miio.o)
# Input # 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": elif endianess == "LE":
self.write(addr+words-1-i, (data>>(8*i)) & 0xFF) self.write(addr+words-1-i, (data>>(8*i)) & 0xFF)
if self.debug: if self.debug:
print("WR %08X @ %04X" %(data, addr)) 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()

View File

@ -75,8 +75,8 @@ class Uart2Csr(Module):
self.sync += If(fsm.ongoing(fsm.IDLE) & uart.rx_ev, cmd.eq(uart.rx_dat)) 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, fsm.act(fsm.GET_BL,
If(get_bl_done, If(get_bl_done,
fsm.next_state(fsm.GET_ADDR) fsm.next_state(fsm.GET_ADDR)

View File

@ -3,6 +3,7 @@ import time
import serial import serial
from struct import * from struct import *
import time import time
from migen.fhdl.structure import *
WRITE_CMD = 0x01 WRITE_CMD = 0x01
READ_CMD = 0x02 READ_CMD = 0x02
@ -36,7 +37,19 @@ class Uart2Csr:
return values[0] return values[0]
else: else:
return values 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): def write(self, addr, data):
if isinstance(data, list): if isinstance(data, list):
burst_length = len(data) burst_length = len(data)
@ -45,9 +58,9 @@ class Uart2Csr:
write_b(self.uart, WRITE_CMD) write_b(self.uart, WRITE_CMD)
write_b(self.uart, burst_length) write_b(self.uart, burst_length)
self.uart.write([(addr & 0xff000000) >> 24, self.uart.write([(addr & 0xff000000) >> 24,
(addr & 0x00ff0000) >> 16, (addr & 0x00ff0000) >> 16,
(addr & 0x0000ff00) >> 8, (addr & 0x0000ff00) >> 8,
(addr & 0x000000ff)]) (addr & 0x000000ff)])
if isinstance(data, list): if isinstance(data, list):
for i in range(len(data)): for i in range(len(data)):
write_b(self.uart, data[i]) write_b(self.uart, data[i])
@ -56,4 +69,14 @@ class Uart2Csr:
else: else:
write_b(self.uart, data) write_b(self.uart, data)
if self.debug: 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 #Driver
# #
def write(self, data): def write(self, data):
self.interface.write(self.address, data) self.interface.write(self.bank.get_base(), data)
def read(self): 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_address(address)
self.set_interface(interface) 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): def set_interface(self, interface):
self.interface = interface self.interface = interface
self.trigger.set_interface(interface) self.trigger.set_interface(interface)
self.recorder.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): def get_fragment(self):
comb =[ comb =[

View File

@ -6,6 +6,8 @@ from migen.bank.description import *
from migen.genlib.misc import optree from migen.genlib.misc import optree
from migen.genlib.fsm import * from migen.genlib.fsm import *
from miscope.tools.misc import RisingEdge
class Storage: class Storage:
# #
# Definition # Definition
@ -49,14 +51,6 @@ class Storage:
self.pull_dat.eq(self._pull_port.dat_r) 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 = FSM("IDLE", "ACTIVE") fsm = FSM("IDLE", "ACTIVE")
@ -64,32 +58,28 @@ class Storage:
fsm.act(fsm.IDLE, fsm.act(fsm.IDLE,
If(self.start, If(self.start,
fsm.next_state(fsm.ACTIVE), fsm.next_state(fsm.ACTIVE),
active_rising.eq(1) )
),
idle_ongoing.eq(1)
) )
# Active # Active
fsm.act(fsm.ACTIVE, fsm.act(fsm.ACTIVE,
If(self.done | self.rst, If(self.done | self.rst,
fsm.next_state(fsm.IDLE), fsm.next_state(fsm.IDLE),
idle_rising.eq(1) )
),
active_ongoing.eq(1)
) )
sync =[ sync =[
If(active_rising, If(fsm.entering(fsm.ACTIVE),
self._push_ptr_stop.eq(self._push_ptr + self.size - self.offset), 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( ).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: class Sequencer:
# #
@ -120,11 +110,6 @@ class Sequencer:
self.enable = Signal() self.enable = Signal()
def get_fragment(self): def get_fragment(self):
idle_rising = Signal()
idle_ongoing = Signal()
active_rising = Signal()
active_ongoing = Signal()
# FSM # FSM
fsm = FSM("IDLE", "ACTIVE") fsm = FSM("IDLE", "ACTIVE")
@ -133,53 +118,46 @@ class Sequencer:
fsm.act(fsm.IDLE, fsm.act(fsm.IDLE,
If(self.ctl_arm, If(self.ctl_arm,
fsm.next_state(fsm.ACTIVE), fsm.next_state(fsm.ACTIVE),
active_rising.eq(1) )
),
idle_ongoing.eq(1)
) )
# Active # Active
fsm.act(fsm.ACTIVE, fsm.act(fsm.ACTIVE,
If(self.rec_done, If(self.rec_done | self.ctl_rst,
fsm.next_state(fsm.IDLE), 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 # trig_hit rising_edge
_hit_d = Signal() hit_rising = RisingEdge(self.hit)
_hit_rising = Signal()
sync =[_hit_d.eq(self.hit)]
comb +=[_hit_rising.eq(self.hit & ~_hit_d)]
# connexion # connexion
comb = [ comb = [
self.rec_offset.eq(self.ctl_offset), self.rec_offset.eq(self.ctl_offset),
self.rec_size.eq(self.ctl_size), self.rec_size.eq(self.ctl_size),
self.rec_start.eq(self.enable & _hit_rising), self.rec_start.eq(self.enable & hit_rising.o),
self.ctl_done.eq(~self.enable) 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_RST_BASE = 0x00
REC_ARM_BASE = 0x01 REC_ARM_BASE = 0x01
REC_DONE_BASE = 0x02 REC_DONE_BASE = 0x02
REC_SIZE_BASE = 0x03 REC_SIZE_BASE = 0x03
REC_OFFSET_BASE = 0x05 REC_OFFSET_BASE = 0x05
REC_READ_BASE = 0x07 REC_READ_BASE = 0x07
REC_READ_DATA_BASE = 0x09 REC_READ_DATA_BASE = 0x08
class Recorder: class Recorder:
# #
# Definition # Definition
# #
def __init__(self, width, depth, address = 0x0000, interface = None): def __init__(self, width, depth, address=0x0000, interface=None):
self.width = width self.width = width
self.depth = depth 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.storage = Storage(self.width, self.depth)
self.sequencer = Sequencer(self.depth) self.sequencer = Sequencer(self.depth)
@ -188,19 +166,17 @@ class Recorder:
self._rst = RegisterField("rst", reset=1) self._rst = RegisterField("rst", reset=1)
self._arm = RegisterField("arm", reset=0) self._arm = RegisterField("arm", reset=0)
self._done = RegisterField("done", reset=0, access_bus=READ_ONLY, 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._size = RegisterField("size", self.depth_width, reset=1)
self._offset = RegisterField("offset", self.depth_width, reset=1) self._offset = RegisterField("offset", self.depth_width, reset=1)
self._pull_stb = RegisterField("pull_stb", reset=0) self._pull_stb = RegisterField("pull_stb", reset=0)
self._pull_dat = RegisterField("pull_dat", self.width, reset=1, 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.regs = [self._rst, self._arm, self._done, self._size, self._offset,
self._pull_stb, self._pull_dat] self._pull_stb, self._pull_dat]
self.bank = csrgen.Bank(self.regs, address=address)
# set address / interface # set address / interface
self.set_address(address) self.set_address(address)
@ -212,19 +188,14 @@ class Recorder:
def set_address(self, address): def set_address(self, address):
self.address = 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): def set_interface(self, interface):
self.interface = interface self.interface = interface
def get_fragment(self): def get_fragment(self):
_pull_stb_d = Signal()
_pull_stb_rising = Signal() _pull_stb_rising = RisingEdge(self._pull_stb.field.r)
sync = [
_pull_stb_d.eq(self._pull_stb.field.r),
_pull_stb_rising.eq(self._pull_stb.field.r & ~_pull_stb_d)
]
# Bank <--> Storage / Sequencer # Bank <--> Storage / Sequencer
comb = [ comb = [
@ -237,7 +208,7 @@ class Recorder:
self._done.field.w.eq(self.sequencer.ctl_done), 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) self._pull_dat.field.w.eq(self.storage.pull_dat)
] ]
@ -254,33 +225,34 @@ class Recorder:
self.storage.push_dat.eq(self.dat) self.storage.push_dat.eq(self.dat)
] ]
return self.bank.get_fragment() + Fragment(comb, sync) +\ return self.bank.get_fragment() + Fragment(comb) +\
self.storage.get_fragment() + self.sequencer.get_fragment() self.storage.get_fragment() + self.sequencer.get_fragment() +\
_pull_stb_rising.get_fragment()
# #
#Driver #Driver
# #
def reset(self): def reset(self):
self.interface.write(self.address + REC_RST_BASE, 1) self.interface.write(self.bank.get_base() + REC_RST_BASE, 1)
self.interface.write(self.address + REC_RST_BASE, 0) self.interface.write(self.bank.get_base() + REC_RST_BASE, 0)
def arm(self): def arm(self):
self.interface.write(self.address + REC_ARM_BASE, 1) self.interface.write(self.bank.get_base() + REC_ARM_BASE, 1)
self.interface.write(self.address + REC_ARM_BASE, 0) self.interface.write(self.bank.get_base() + REC_ARM_BASE, 0)
def is_done(self): 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): 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): 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): def read(self, size):
r = [] r = []
for i in range(size): for i in range(size):
self.interface.write(self.address + REC_READ_BASE, 1) self.interface.write(self.bank.get_base() + REC_READ_BASE, 1)
self.interface.write(self.address + REC_READ_BASE, 0) self.interface.write(self.bank.get_base() + REC_READ_BASE, 0)
r.append(self.interface.read_n(self.address + REC_READ_DATA_BASE, self.width)) r.append(self.interface.read_n(self.bank.get_base() + REC_READ_DATA_BASE, self.width))
return r 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 * from miscope.tools.conv import *
def get_bits(values, width, low, high =None): def get_bits(values, width, low, high=None):
r = [] r = []
for val in values: for val in values:
t = dec2bin(val,width)[::-1] t = dec2bin(val, width)[::-1]
if high == None: if high == None:
t = t[low] t = t[low]
else: else:
@ -16,8 +16,32 @@ def get_bits(values, width, low, high =None):
r.append(t) r.append(t)
return r 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: 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.type = type
self.width = width self.width = width
self.name = name self.name = name
@ -36,7 +60,7 @@ class Var:
try : try :
if self.values[cnt+1] != self.val: if self.values[cnt+1] != self.val:
r += "b" r += "b"
r += dec2bin(self.values[cnt+1], self.width) r += dec2bin(self.values[cnt+1], self.width)[::-1]
r += " " r += " "
r += self.vcd_id r += self.vcd_id
r += "\n" r += "\n"
@ -44,10 +68,9 @@ class Var:
except : except :
return r return r
return r return r
class Vcd: class Vcd:
def __init__(self,timescale = "1ps", comment = ""): def __init__(self, timescale="1ps", comment=""):
self.timescale = timescale self.timescale = timescale
self.comment = comment self.comment = comment
self.vars = [] self.vars = []
@ -58,6 +81,12 @@ class Vcd:
var.set_vcd_id(self.vcd_id) var.set_vcd_id(self.vcd_id)
self.vcd_id = chr(ord(self.vcd_id)+1) self.vcd_id = chr(ord(self.vcd_id)+1)
self.vars.append(var) 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): def __len__(self):
l = 0 l = 0
@ -77,7 +106,6 @@ class Vcd:
r += c r += c
return r return r
def p_date(self): def p_date(self):
now = datetime.datetime.now() now = datetime.datetime.now()
r = "$date\n" r = "$date\n"
@ -110,6 +138,7 @@ class Vcd:
r += self.timescale r += self.timescale
r += " $end\n" r += " $end\n"
return r return r
def p_vars(self): def p_vars(self):
r = "" r = ""
for var in self.vars: for var in self.vars:
@ -151,7 +180,6 @@ class Vcd:
r += self.change() r += self.change()
self.cnt += 1 self.cnt += 1
return r return r
def __repr__(self): def __repr__(self):
r = "" r = ""
@ -174,12 +202,12 @@ class Vcd:
def main(): def main():
myvcd = Vcd() myvcd = Vcd()
myvcd.add(Var("wire", 1, "foo1", [0,1,0,1,0,1])) myvcd.add(Var(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(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(3, "foo3"))
myvcd.add(Var("wire", 4, "foo4")) myvcd.add(Var(4, "foo4"))
ramp = [i%128 for i in range(1024)] ramp = [i%128 for i in range(1024)]
myvcd.add(Var("wire", 16, "ramp", ramp)) myvcd.add(Var(16, "ramp", ramp))
print(myvcd) print(myvcd)
if __name__ == '__main__': if __name__ == '__main__':

View File

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

View File

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

View File

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

View File

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