From b1cbfe2326957d97bab9404e461f7bd7a31aa990 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 21 Mar 2013 12:23:44 +0100 Subject: [PATCH] clean up/fixes --- README | 35 +++--- examples/de0_nano/client/test_miio.py | 2 +- examples/de0_nano/client/test_mila.py | 68 ++++++++++++ examples/de0_nano/top.py | 58 ++++++++-- miscope/bridges/spi2csr/tools/uart2Spi.py | 11 +- miscope/bridges/uart2csr/__init__.py | 4 +- miscope/bridges/uart2csr/tools/uart2Csr.py | 33 +++++- miscope/miio.py | 4 +- miscope/mila.py | 12 ++- miscope/recorder.py | 120 ++++++++------------- miscope/tools/misc.py | 111 +++++++++++++++++++ miscope/tools/vcd.py | 56 +++++++--- miscope/trigger.py | 14 +-- sim/tb_RecorderCsr.py | 26 +++-- sim/tb_TriggerCsr.py | 29 +++-- sim/tb_miscope.py | 54 ++++++---- 16 files changed, 452 insertions(+), 185 deletions(-) create mode 100644 examples/de0_nano/client/test_mila.py create mode 100644 miscope/tools/misc.py diff --git a/README b/README index dbc997c7..cdffe5f6 100644 --- a/README +++ b/README @@ -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 diff --git a/examples/de0_nano/client/test_miio.py b/examples/de0_nano/client/test_miio.py index 0e011923..dea73da9 100644 --- a/examples/de0_nano/client/test_miio.py +++ b/examples/de0_nano/client/test_miio.py @@ -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) diff --git a/examples/de0_nano/client/test_mila.py b/examples/de0_nano/client/test_mila.py new file mode 100644 index 00000000..fcd6a755 --- /dev/null +++ b/examples/de0_nano/client/test_mila.py @@ -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") \ No newline at end of file diff --git a/examples/de0_nano/top.py b/examples/de0_nano/top.py index 40bef128..81592de5 100644 --- a/examples/de0_nano/top.py +++ b/examples/de0_nano/top.py @@ -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) \ No newline at end of file + 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) diff --git a/miscope/bridges/spi2csr/tools/uart2Spi.py b/miscope/bridges/spi2csr/tools/uart2Spi.py index 9f5568df..c7326c70 100644 --- a/miscope/bridges/spi2csr/tools/uart2Spi.py +++ b/miscope/bridges/spi2csr/tools/uart2Spi.py @@ -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() \ No newline at end of file + print("WR %08X @ %04X" %(data, addr)) \ No newline at end of file diff --git a/miscope/bridges/uart2csr/__init__.py b/miscope/bridges/uart2csr/__init__.py index b10d2dff..9cf0a8b4 100644 --- a/miscope/bridges/uart2csr/__init__.py +++ b/miscope/bridges/uart2csr/__init__.py @@ -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) diff --git a/miscope/bridges/uart2csr/tools/uart2Csr.py b/miscope/bridges/uart2csr/tools/uart2Csr.py index 0f265eb8..27fc288b 100644 --- a/miscope/bridges/uart2csr/tools/uart2Csr.py +++ b/miscope/bridges/uart2csr/tools/uart2Csr.py @@ -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)) \ No newline at end of file + 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)) \ No newline at end of file diff --git a/miscope/miio.py b/miscope/miio.py index bad8dbc4..07729103 100644 --- a/miscope/miio.py +++ b/miscope/miio.py @@ -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) \ No newline at end of file + return self.interface.read(self.bank.get_base() + self.words) \ No newline at end of file diff --git a/miscope/mila.py b/miscope/mila.py index e9104d44..177ee583 100644 --- a/miscope/mila.py +++ b/miscope/mila.py @@ -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 =[ diff --git a/miscope/recorder.py b/miscope/recorder.py index 04283f2d..caa23674 100644 --- a/miscope/recorder.py +++ b/miscope/recorder.py @@ -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 diff --git a/miscope/tools/misc.py b/miscope/tools/misc.py new file mode 100644 index 00000000..1067a5c4 --- /dev/null +++ b/miscope/tools/misc.py @@ -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}) \ No newline at end of file diff --git a/miscope/tools/vcd.py b/miscope/tools/vcd.py index 3a44116a..192ce383 100644 --- a/miscope/tools/vcd.py +++ b/miscope/tools/vcd.py @@ -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__': diff --git a/miscope/trigger.py b/miscope/trigger.py index 80599b6f..8beae529 100644 --- a/miscope/trigger.py +++ b/miscope/trigger.py @@ -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: diff --git a/sim/tb_RecorderCsr.py b/sim/tb_RecorderCsr.py index 45e2ea08..d9f086f8 100644 --- a/sim/tb_RecorderCsr.py +++ b/sim/tb_RecorderCsr.py @@ -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() \ No newline at end of file diff --git a/sim/tb_TriggerCsr.py b/sim/tb_TriggerCsr.py index f3db1bda..9262872e 100644 --- a/sim/tb_TriggerCsr.py +++ b/sim/tb_TriggerCsr.py @@ -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() diff --git a/sim/tb_miscope.py b/sim/tb_miscope.py index e44ddc53..8ad225e2 100644 --- a/sim/tb_miscope.py +++ b/sim/tb_miscope.py @@ -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() -- 2.30.2