mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
refactoring
This commit is contained in:
parent
89a8d8daf3
commit
ce9bff21e9
36 changed files with 753 additions and 1896 deletions
|
@ -1,11 +1,10 @@
|
||||||
all: build/top.sta
|
all: build/soc-de0nano.sta
|
||||||
|
|
||||||
build/top.sta:
|
build/soc-de0nano.sta:
|
||||||
./build.py
|
./make.py
|
||||||
|
|
||||||
load:
|
load:
|
||||||
cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;top.sof"
|
cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;soc-de0nano.sof"
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build/*
|
rm -rf build/*
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
from mibuild.platforms import de0nano
|
|
||||||
import top
|
|
||||||
|
|
||||||
def main():
|
|
||||||
platform = de0nano.Platform()
|
|
||||||
soc = top.SoC(platform)
|
|
||||||
|
|
||||||
|
|
||||||
# set extra constraints
|
|
||||||
platform.add_platform_command("""
|
|
||||||
set_global_assignment -name FAMILY "Cyclone IV E"
|
|
||||||
set_global_assignment -name TOP_LEVEL_ENTITY "top"
|
|
||||||
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
|
|
||||||
""")
|
|
||||||
|
|
||||||
platform.build_cmdline(soc)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,23 +1,31 @@
|
||||||
from miscope import miio
|
from miscope import miio
|
||||||
from miscope.bridges.uart2csr.tools.uart2Csr import *
|
from miscope.com.uart2csr.host.uart2csr import *
|
||||||
|
|
||||||
|
from csr import *
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# P A R A M E T E R S
|
# P A R A M E T E R S
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
|
||||||
csr = Uart2Csr(3,115200)
|
uart = Uart2Csr(3, 115200)
|
||||||
|
|
||||||
# Csr Addr
|
class MiIoCtrl():
|
||||||
MIIO_ADDR = 0x00
|
def __init__(self, bus):
|
||||||
|
self.bus = bus
|
||||||
|
|
||||||
# Miscope Configuration
|
def write(self, value):
|
||||||
miio = miio.MiIo(MIIO_ADDR, 8, "IO", csr)
|
miio_o_write(self.bus, value)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
return miio_i_read(self.bus)
|
||||||
|
|
||||||
|
miio = MiIoCtrl(uart)
|
||||||
|
|
||||||
def led_anim0():
|
def led_anim0():
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
miio.set(0xA5)
|
miio.write(0xA5)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
miio.set(0x5A)
|
miio.write(0x5A)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
def led_anim1():
|
def led_anim1():
|
||||||
|
@ -25,18 +33,18 @@ def led_anim1():
|
||||||
#Led <<
|
#Led <<
|
||||||
ledData = 1
|
ledData = 1
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
miio.set(ledData)
|
miio.write(ledData)
|
||||||
time.sleep(i*i*0.0020)
|
time.sleep(i*i*0.0020)
|
||||||
ledData = (ledData<<1)
|
ledData = (ledData<<1)
|
||||||
#Led >>
|
#Led >>
|
||||||
ledData = 128
|
ledData = 128
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
miio.set(ledData)
|
miio.write(ledData)
|
||||||
time.sleep(i*i*0.0020)
|
time.sleep(i*i*0.0020)
|
||||||
ledData = (ledData>>1)
|
ledData = (ledData>>1)
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# T E S T M I G I O
|
# T E S T M I I O
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
|
||||||
print("- Led Animation...")
|
print("- Led Animation...")
|
||||||
|
@ -46,4 +54,4 @@ led_anim1()
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
print("- Read Switch: ",end=' ')
|
print("- Read Switch: ",end=' ')
|
||||||
print("%02X" %miio.get())
|
print("%02X" %miio.read())
|
||||||
|
|
|
@ -1,61 +1,79 @@
|
||||||
from miscope import trigger, recorder, miio, mila
|
from miscope import mila
|
||||||
from miscope.tools.truthtable import *
|
from miscope.std.truthtable import *
|
||||||
from miscope.tools.vcd import *
|
from miscope.std.vcd import *
|
||||||
from miscope.bridges.uart2csr.tools.uart2Csr import *
|
from miscope.com.uart2csr.host.uart2csr import *
|
||||||
|
from csr import *
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# P A R A M E T E R S
|
# P A R A M E T E R S
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# Csr Addr
|
|
||||||
MILA_ADDR = 0x01
|
|
||||||
|
|
||||||
csr = Uart2Csr(3, 115200, debug=False)
|
uart = Uart2Csr(3, 115200)
|
||||||
|
|
||||||
|
class MiLaCtrl():
|
||||||
|
def __init__(self, bus):
|
||||||
|
self.bus = bus
|
||||||
|
|
||||||
|
def prog_term(self, trigger, mask):
|
||||||
|
mila_trigger_port0_trig_write(self.bus, trigger)
|
||||||
|
mila_trigger_port0_mask_write(self.bus, mask)
|
||||||
|
|
||||||
|
def prog_sum(self, datas):
|
||||||
|
for adr, dat in enumerate(datas):
|
||||||
|
mila_trigger_sum_prog_adr_write(self.bus, adr)
|
||||||
|
mila_trigger_sum_prog_dat_write(self.bus, dat)
|
||||||
|
mila_trigger_sum_prog_we_write(self.bus, 1)
|
||||||
|
|
||||||
|
def is_done(self):
|
||||||
|
return mila_recorder_done_read(self.bus)
|
||||||
|
|
||||||
|
def trigger(self, offset, length):
|
||||||
|
mila_recorder_offset_write(self.bus, offset)
|
||||||
|
mila_recorder_length_write(self.bus, length)
|
||||||
|
mila_recorder_trigger_write(self.bus, 1)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
r = []
|
||||||
|
empty = mila_recorder_read_empty_read(self.bus)
|
||||||
|
while(not empty):
|
||||||
|
r.append(mila_recorder_read_dat_read(self.bus))
|
||||||
|
empty = mila_recorder_read_empty_read(self.bus)
|
||||||
|
mila_recorder_read_en_write(self.bus, 1)
|
||||||
|
return r
|
||||||
|
|
||||||
# Mila Param
|
# Mila Param
|
||||||
trig_w = 16
|
trig_w = 16
|
||||||
dat_w = 16
|
dat_w = 16
|
||||||
rec_size = 512
|
rec_length = 512
|
||||||
rec_offset = 32
|
rec_offset = 0
|
||||||
enable_rle = True
|
|
||||||
|
|
||||||
# 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
|
# T E S T M I L A
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
dat_vcd = VcdDat(dat_w)
|
dat_vcd = VcdDat(dat_w)
|
||||||
|
|
||||||
def capture(size):
|
mila = MiLaCtrl(uart)
|
||||||
|
|
||||||
|
def capture():
|
||||||
global dat_vcd
|
global dat_vcd
|
||||||
sum_tt = gen_truth_table("term")
|
sum_tt = gen_truth_table("term")
|
||||||
mila.trigger.sum.set(sum_tt)
|
mila.prog_sum(sum_tt)
|
||||||
mila.recorder.reset()
|
mila.trigger(rec_offset, rec_length)
|
||||||
if enable_rle:
|
print("-Recorder [Triggered]")
|
||||||
mila.recorder.enable_rle()
|
|
||||||
recorder.set_size(rec_size)
|
|
||||||
mila.recorder.set_offset(rec_offset)
|
|
||||||
mila.recorder.arm()
|
|
||||||
print("-Recorder [Armed]")
|
|
||||||
print("-Waiting Trigger...", end=' ')
|
print("-Waiting Trigger...", end=' ')
|
||||||
while(not mila.recorder.is_done()):
|
while(not mila.is_done()):
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
print("[Done]")
|
print("[Done]")
|
||||||
|
|
||||||
print("-Receiving Data...", end=' ')
|
print("-Receiving Data...", end=' ')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
dat_vcd += mila.recorder.pull(rec_size)
|
dat_vcd += mila.read()
|
||||||
print("[Done]")
|
print("[Done]")
|
||||||
|
|
||||||
print("Capturing ...")
|
print("Capturing ...")
|
||||||
print("----------------------")
|
print("----------------------")
|
||||||
term.set(0x0000, 0xFFFF)
|
mila.prog_term(0x0000, 0xFFFF)
|
||||||
capture(rec_size)
|
capture()
|
||||||
|
|
||||||
mila_layout = [
|
mila_layout = [
|
||||||
("freqgen", 1),
|
("freqgen", 1),
|
||||||
|
@ -64,9 +82,6 @@ mila_layout = [
|
||||||
("cnt", 8),
|
("cnt", 8),
|
||||||
]
|
]
|
||||||
|
|
||||||
if enable_rle:
|
|
||||||
dat_vcd = dat_vcd.decode_rle()
|
|
||||||
|
|
||||||
myvcd = Vcd()
|
myvcd = Vcd()
|
||||||
myvcd.add_from_layout(mila_layout, dat_vcd)
|
myvcd.add_from_layout(mila_layout, dat_vcd)
|
||||||
myvcd.write("test_mila.vcd")
|
myvcd.write("test_mila.vcd")
|
42
examples/de0_nano/make.py
Normal file
42
examples/de0_nano/make.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse, os, subprocess, struct, shutil
|
||||||
|
|
||||||
|
from mibuild.tools import write_to_file
|
||||||
|
import mibuild.platforms.de0nano as de0nano
|
||||||
|
|
||||||
|
from miscope.std import cif
|
||||||
|
|
||||||
|
import top
|
||||||
|
|
||||||
|
def build(build_bitstream, build_header):
|
||||||
|
platform = de0nano.Platform()
|
||||||
|
soc = top.SoC(platform)
|
||||||
|
|
||||||
|
platform.add_platform_command("""
|
||||||
|
set_global_assignment -name FAMILY "Cyclone IV E"
|
||||||
|
set_global_assignment -name TOP_LEVEL_ENTITY "top"
|
||||||
|
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
|
||||||
|
""")
|
||||||
|
|
||||||
|
if build_bitstream:
|
||||||
|
build_name = "soc-de0nano"
|
||||||
|
platform.build(soc, build_name=build_name)
|
||||||
|
else:
|
||||||
|
soc.finalize()
|
||||||
|
if build_header:
|
||||||
|
|
||||||
|
csr_py_header = cif.get_py_csr_header(soc.csr_base, soc.csrbankarray)
|
||||||
|
write_to_file(os.path.join("client", "csr.py"), csr_py_header)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="miscope")
|
||||||
|
parser.add_argument("-B", "--no-bitstream", default=False, action="store_true", help="do not build bitstream file")
|
||||||
|
parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header file with CSR defs")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
build(not args.no_bitstream, not args.no_header)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -14,13 +14,16 @@
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
# I M P O R T
|
# I M P O R T
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl.module import *
|
|
||||||
from migen.bus import csr
|
from migen.bus import csr
|
||||||
|
from migen.bank import csrgen
|
||||||
|
from miscope.std.misc import *
|
||||||
|
|
||||||
from miscope import trigger, recorder, miio, mila
|
from miscope.triggering import *
|
||||||
from miscope.bridges import uart2csr
|
from miscope.recording import *
|
||||||
from miscope.tools.misc import *
|
from miscope import miio, mila
|
||||||
|
|
||||||
|
from miscope.com import uart2csr
|
||||||
|
|
||||||
from timings import *
|
from timings import *
|
||||||
|
|
||||||
|
@ -31,10 +34,6 @@ from timings import *
|
||||||
# Timings Param
|
# Timings Param
|
||||||
clk_freq = 50*MHz
|
clk_freq = 50*MHz
|
||||||
|
|
||||||
# Csr Addr
|
|
||||||
MIIO_ADDR = 0x00
|
|
||||||
MILA_ADDR = 0x01
|
|
||||||
|
|
||||||
# Mila Param
|
# Mila Param
|
||||||
trig_w = 16
|
trig_w = 16
|
||||||
dat_w = 16
|
dat_w = 16
|
||||||
|
@ -44,16 +43,23 @@ 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
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
class SoC(Module):
|
class SoC(Module):
|
||||||
|
csr_base = 0xe0000000
|
||||||
|
csr_map = {
|
||||||
|
"miio": 1,
|
||||||
|
"mila": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, platform):
|
def __init__(self, platform):
|
||||||
# MiIo
|
# MiIo
|
||||||
self.submodules.miio = miio.MiIo(MIIO_ADDR, 8, "IO")
|
self.submodules.miio = miio.MiIo(8)
|
||||||
|
|
||||||
# MiLa
|
# MiLa
|
||||||
self.submodules.term = trigger.Term(trig_w)
|
term = Term(trig_w)
|
||||||
self.submodules.trigger = trigger.Trigger(trig_w, [self.term])
|
trigger = Trigger(trig_w, [term])
|
||||||
self.submodules.recorder = recorder.Recorder(dat_w, rec_size)
|
recorder = Recorder(dat_w, rec_size)
|
||||||
|
|
||||||
self.submodules.mila = mila.MiLa(MILA_ADDR, self.trigger, self.recorder, trig_is_dat=True)
|
self.submodules.mila = mila.MiLa(trigger, recorder)
|
||||||
|
|
||||||
# Uart2Csr
|
# Uart2Csr
|
||||||
self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200)
|
self.submodules.uart2csr = uart2csr.Uart2Csr(clk_freq, 115200)
|
||||||
|
@ -62,15 +68,12 @@ class SoC(Module):
|
||||||
self.comb += self.uart2csr.rx.eq(uart_pads.rx)
|
self.comb += self.uart2csr.rx.eq(uart_pads.rx)
|
||||||
|
|
||||||
# Csr Interconnect
|
# Csr Interconnect
|
||||||
self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr,
|
self.submodules.csrbankarray = csrgen.BankArray(self,
|
||||||
[
|
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
||||||
self.miio.bank.bus,
|
self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr, self.csrbankarray.get_buses())
|
||||||
self.trigger.bank.bus,
|
|
||||||
self.recorder.bank.bus
|
|
||||||
])
|
|
||||||
|
|
||||||
# Led
|
# Led
|
||||||
self.led = platform.request("user_led", 0, 8)
|
self.led = Cat(*[platform.request("user_led", i) for i in range(8)])
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
self.cnt = Signal(9)
|
self.cnt = Signal(9)
|
||||||
|
@ -94,7 +97,8 @@ class SoC(Module):
|
||||||
# Mila
|
# Mila
|
||||||
#
|
#
|
||||||
self.comb +=[
|
self.comb +=[
|
||||||
self.mila.trig.eq(Cat(
|
self.mila.sink.stb.eq(1),
|
||||||
|
self.mila.sink.payload.d.eq(Cat(
|
||||||
self.freqgen.o,
|
self.freqgen.o,
|
||||||
self.eventgen_rising.o,
|
self.eventgen_rising.o,
|
||||||
self.eventgen_falling.o,
|
self.eventgen_falling.o,
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.genlib.misc import *
|
|
||||||
from migen.genlib.cdc import *
|
|
||||||
from migen.bus import csr
|
|
||||||
|
|
||||||
class Spi2Csr(Module):
|
|
||||||
def __init__(self, burst_length=8):
|
|
||||||
self.a_w = 14
|
|
||||||
self.d_w = 8
|
|
||||||
self.burst_length = 8
|
|
||||||
|
|
||||||
# Csr interface
|
|
||||||
self.csr = csr.Interface()
|
|
||||||
|
|
||||||
# Spi interface
|
|
||||||
self.spi_clk = Signal()
|
|
||||||
self.spi_cs_n = Signal(reset=1)
|
|
||||||
self.spi_mosi = Signal()
|
|
||||||
self.spi_miso = Signal()
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
# Resychronisation
|
|
||||||
clk_synchro = Synchronizer(i=self.spi_clk)
|
|
||||||
cs_n_synchro = Synchronizer(i=self.spi_cs_n)
|
|
||||||
mosi_synchro = Synchronizer(i=self.spi_mosi)
|
|
||||||
|
|
||||||
self.specials += {clk_synchro, cs_n_synchro, mosi_synchro}
|
|
||||||
|
|
||||||
# Decode
|
|
||||||
spi_clk_rising = Signal()
|
|
||||||
spi_clk_falling = Signal()
|
|
||||||
spi_cs_n_active = Signal()
|
|
||||||
spi_mosi_dat = Signal()
|
|
||||||
|
|
||||||
self.specials += RisingEdge(i=clk_synchro.o, o=spi_clk_rising)
|
|
||||||
self.specials += FallingEdge(i=clk_synchro.o, o=spi_clk_falling)
|
|
||||||
|
|
||||||
self.sync +=[
|
|
||||||
spi_cs_n_active.eq(~cs_n_synchro.o),
|
|
||||||
spi_mosi_dat.eq(~mosi_synchro.o),
|
|
||||||
]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Spi --> Csr
|
|
||||||
#
|
|
||||||
spi_cnt = Signal(bits_for(self.a_w + self.burst_length*self.d_w))
|
|
||||||
spi_addr = Signal(self.a_w)
|
|
||||||
spi_w_dat = Signal(self.d_w)
|
|
||||||
spi_r_dat = Signal(self.d_w)
|
|
||||||
spi_we = Signal()
|
|
||||||
spi_re = Signal()
|
|
||||||
spi_we_re_done = Signal(reset=1)
|
|
||||||
spi_miso_dat = Signal()
|
|
||||||
|
|
||||||
# Re/We Signals Decoding
|
|
||||||
first_b = Signal()
|
|
||||||
last_b = Signal()
|
|
||||||
|
|
||||||
self.comb +=[
|
|
||||||
first_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 0),
|
|
||||||
last_b.eq(spi_cnt[0:bits_for(self.d_w)-1] == 2**(bits_for(self.d_w-1))-1)
|
|
||||||
]
|
|
||||||
self.sync +=[
|
|
||||||
If((spi_cnt >= (self.a_w + self.d_w)) & first_b,
|
|
||||||
spi_we.eq(spi_addr[self.a_w-1] & ~spi_we_re_done),
|
|
||||||
spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done),
|
|
||||||
spi_we_re_done.eq(1)
|
|
||||||
).Elif((spi_cnt >= self.a_w) & first_b,
|
|
||||||
spi_re.eq(~spi_addr[self.a_w-1] & ~spi_we_re_done),
|
|
||||||
spi_we_re_done.eq(1)
|
|
||||||
).Else(
|
|
||||||
spi_we.eq(0),
|
|
||||||
spi_re.eq(0),
|
|
||||||
spi_we_re_done.eq(0)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Spi Addr / Data Decoding
|
|
||||||
self.sync +=[
|
|
||||||
If(~spi_cs_n_active,
|
|
||||||
spi_cnt.eq(0),
|
|
||||||
).Elif(spi_clk_rising,
|
|
||||||
# addr
|
|
||||||
If(spi_cnt < self.a_w,
|
|
||||||
spi_addr.eq(Cat(spi_mosi_dat,spi_addr[:self.a_w-1]))
|
|
||||||
).Elif((spi_cnt >= (self.a_w+self.d_w)) & last_b,
|
|
||||||
spi_addr.eq(spi_addr+1)
|
|
||||||
).Elif((spi_cnt >= self.a_w) & last_b & (spi_addr[self.a_w-1] == 0),
|
|
||||||
spi_addr.eq(spi_addr+1)
|
|
||||||
),
|
|
||||||
# dat
|
|
||||||
If(spi_cnt >= self.a_w,
|
|
||||||
spi_w_dat.eq(Cat(spi_mosi_dat,spi_w_dat[:self.d_w-1]))
|
|
||||||
),
|
|
||||||
|
|
||||||
# spi_cnt
|
|
||||||
spi_cnt.eq(spi_cnt+1)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Csr --> Spi
|
|
||||||
#
|
|
||||||
spi_r_dat_shift = Signal(self.d_w)
|
|
||||||
self.sync +=[
|
|
||||||
If(spi_re,
|
|
||||||
spi_r_dat_shift.eq(spi_r_dat)
|
|
||||||
),
|
|
||||||
|
|
||||||
If(~spi_cs_n_active,
|
|
||||||
spi_miso_dat.eq(0)
|
|
||||||
).Elif(spi_clk_falling,
|
|
||||||
spi_miso_dat.eq(spi_r_dat_shift[self.d_w-1]),
|
|
||||||
spi_r_dat_shift.eq(Cat(0,spi_r_dat_shift[:self.d_w-1]))
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Csr Interface
|
|
||||||
#
|
|
||||||
self.comb += [
|
|
||||||
self.csr.adr.eq(spi_addr),
|
|
||||||
self.csr.dat_w.eq(spi_w_dat),
|
|
||||||
self.csr.we.eq(spi_we)
|
|
||||||
]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Spi Interface
|
|
||||||
#
|
|
||||||
self.comb += [
|
|
||||||
spi_r_dat.eq(self.csr.dat_r),
|
|
||||||
self.spi_miso.eq(spi_miso_dat)
|
|
||||||
]
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* spiFpga
|
|
||||||
* Copyright (C) 2012 by Florent Kermarrec <florent@enjoy-digital.fr>
|
|
||||||
* Copyright (C) 2011 by James Bowman <jamesb@excamera.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "WProgram.h"
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <spiFpga.h>
|
|
||||||
|
|
||||||
SFClass SF;
|
|
||||||
|
|
||||||
void SFClass::begin()
|
|
||||||
{
|
|
||||||
pinMode(SS_PIN, OUTPUT);
|
|
||||||
SPI.begin();
|
|
||||||
SPI.setClockDivider(SPI_CLOCK_DIV2);
|
|
||||||
SPI.setBitOrder(MSBFIRST);
|
|
||||||
SPI.setDataMode(SPI_MODE0);
|
|
||||||
SPSR = (1 << SPI2X);
|
|
||||||
digitalWrite(SS_PIN, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SFClass::end() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void SFClass::__start(unsigned int addr)
|
|
||||||
{
|
|
||||||
digitalWrite(SS_PIN, LOW);
|
|
||||||
SPI.transfer(highByte(addr));
|
|
||||||
SPI.transfer(lowByte(addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SFClass::__wstart(unsigned int addr)
|
|
||||||
{
|
|
||||||
__start(0x8000|addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SFClass::__end()
|
|
||||||
{
|
|
||||||
digitalWrite(SS_PIN, HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
char SFClass::rd(unsigned int addr)
|
|
||||||
{
|
|
||||||
__start(addr);
|
|
||||||
char r = SPI.transfer(0);
|
|
||||||
__end();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SFClass::wr(unsigned int addr, char v)
|
|
||||||
{
|
|
||||||
__wstart(addr);
|
|
||||||
SPI.transfer(v);
|
|
||||||
__end();
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* spiFpga
|
|
||||||
* Copyright (C) 2012 by Florent Kermarrec <florent@enjoy-digital.fr>
|
|
||||||
* Copyright (C) 2011 by James Bowman <jamesb@excamera.com>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _SF_H_INCLUDED
|
|
||||||
#define _SF_H_INCLUDED
|
|
||||||
|
|
||||||
#ifndef SS_PIN
|
|
||||||
#define SS_PIN 10
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class SFClass {
|
|
||||||
public:
|
|
||||||
static void begin();
|
|
||||||
static void end();
|
|
||||||
static void __start(unsigned int addr);
|
|
||||||
static void __wstart(unsigned int addr);
|
|
||||||
static void __end(void);
|
|
||||||
static char rd(unsigned int addr);
|
|
||||||
static void wr(unsigned int addr, char v);
|
|
||||||
};
|
|
||||||
|
|
||||||
extern SFClass SF;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
Uart2Spi
|
|
||||||
Copyright 2012 - Florent Kermarrec - florent@enjoy-digital.fr
|
|
||||||
|
|
||||||
Protocol:
|
|
||||||
-Write : 0x01 + 16b Addr + 8b Data
|
|
||||||
-Read : 0x02 + 16b Addr + 8b Don't Care
|
|
||||||
|
|
||||||
Todo:
|
|
||||||
Support Spi Burst Mode
|
|
||||||
|
|
||||||
*/
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <spiFpga.h>
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
SF.begin();
|
|
||||||
SPI.setClockDivider(8);
|
|
||||||
Serial.begin(115200);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd = 0;
|
|
||||||
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (Serial.available() == 4)
|
|
||||||
{
|
|
||||||
cmd = Serial.read();
|
|
||||||
//Write Cmd
|
|
||||||
if (cmd == 0x01)
|
|
||||||
{
|
|
||||||
char addrMsb = Serial.read();
|
|
||||||
char addrLsb = Serial.read();
|
|
||||||
char data = Serial.read();
|
|
||||||
SF.wr(addrMsb<<8|addrLsb, data);
|
|
||||||
}
|
|
||||||
//Read Cmd
|
|
||||||
if (cmd == 0x02)
|
|
||||||
{
|
|
||||||
char addrMsb = Serial.read();
|
|
||||||
char addrLsb = Serial.read();
|
|
||||||
Serial.read();
|
|
||||||
char data;
|
|
||||||
data = SF.rd(addrMsb<<8|addrLsb);
|
|
||||||
Serial.print(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Serial.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import string
|
|
||||||
import time
|
|
||||||
import serial
|
|
||||||
from struct import *
|
|
||||||
from migen.fhdl.structure import *
|
|
||||||
|
|
||||||
def write_b(uart, data):
|
|
||||||
uart.write(pack('B',data))
|
|
||||||
|
|
||||||
class Uart2Spi:
|
|
||||||
def __init__(self, port, baudrate, debug = False):
|
|
||||||
self.port = port
|
|
||||||
self.baudrate = baudrate
|
|
||||||
self.debug = debug
|
|
||||||
self.uart = serial.Serial(port, baudrate, timeout=0.25)
|
|
||||||
|
|
||||||
def read(self, addr):
|
|
||||||
write_b(self.uart, 0x02)
|
|
||||||
write_b(self.uart, (addr>>8)&0xFF)
|
|
||||||
write_b(self.uart, (addr&0xFF))
|
|
||||||
write_b(self.uart, 0x00)
|
|
||||||
read = self.uart.read()
|
|
||||||
if self.debug:
|
|
||||||
print("RD @ %04X" %addr)
|
|
||||||
return int(read[0])
|
|
||||||
|
|
||||||
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):
|
|
||||||
write_b(self.uart, 0x01)
|
|
||||||
write_b(self.uart, (addr>>8)&0xFF)
|
|
||||||
write_b(self.uart, (addr&0xFF))
|
|
||||||
write_b(self.uart, data)
|
|
||||||
if self.debug:
|
|
||||||
print("WR %02X @ %04X" %(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))
|
|
|
@ -1,9 +1,9 @@
|
||||||
from migen.fhdl.structure import *
|
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 migen.genlib.fsm import *
|
from migen.genlib.fsm import FSM, NextState
|
||||||
|
|
||||||
from miscope.bridges.uart2csr.uart import *
|
from miscope.com.uart2csr.uart import *
|
||||||
|
|
||||||
WRITE_CMD = 0x01
|
WRITE_CMD = 0x01
|
||||||
READ_CMD = 0x02
|
READ_CMD = 0x02
|
||||||
|
@ -39,10 +39,7 @@ class Uart2Csr(Module):
|
||||||
data = Signal(8)
|
data = Signal(8)
|
||||||
|
|
||||||
# FSM
|
# FSM
|
||||||
self.submodules.fsm = FSM("IDLE",
|
self.submodules.fsm = FSM(reset_state="IDLE")
|
||||||
"GET_BL", "GET_ADDR",
|
|
||||||
"GET_DATA", "WRITE_CSR",
|
|
||||||
"READ_CSR0", "READ_CSR1", "SEND_DATA")
|
|
||||||
|
|
||||||
fsm = self.fsm
|
fsm = self.fsm
|
||||||
|
|
||||||
|
@ -50,7 +47,7 @@ class Uart2Csr(Module):
|
||||||
# Global
|
# Global
|
||||||
#
|
#
|
||||||
self.sync +=[
|
self.sync +=[
|
||||||
If(fsm.ongoing(fsm.IDLE), cnt.eq(0)
|
If(fsm.ongoing("IDLE"), cnt.eq(0)
|
||||||
).Elif(uart.rx_ev, cnt.eq(cnt + 1)),
|
).Elif(uart.rx_ev, cnt.eq(cnt + 1)),
|
||||||
|
|
||||||
If(uart.rx_ev, sr.eq(Cat(uart.rx_dat, sr[0:24])))
|
If(uart.rx_ev, sr.eq(Cat(uart.rx_dat, sr[0:24])))
|
||||||
|
@ -66,45 +63,45 @@ class Uart2Csr(Module):
|
||||||
#
|
#
|
||||||
# Idle
|
# Idle
|
||||||
#
|
#
|
||||||
fsm.act(fsm.IDLE,
|
fsm.act("IDLE",
|
||||||
If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)),
|
If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)),
|
||||||
fsm.next_state(fsm.GET_BL)
|
NextState("GET_BL")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.sync += If(fsm.ongoing(fsm.IDLE) & uart.rx_ev, cmd.eq(uart.rx_dat))
|
self.sync += If(fsm.ongoing("IDLE") & uart.rx_ev, cmd.eq(uart.rx_dat))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Get burst length
|
# Get burst length
|
||||||
#
|
#
|
||||||
fsm.act(fsm.GET_BL,
|
fsm.act("GET_BL",
|
||||||
If(get_bl_done,
|
If(get_bl_done,
|
||||||
fsm.next_state(fsm.GET_ADDR)
|
NextState("GET_ADDR")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.comb += get_bl_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_BL))
|
self.comb += get_bl_done.eq(uart.rx_ev & fsm.ongoing("GET_BL"))
|
||||||
|
|
||||||
self.sync += If(get_bl_done, burst_cnt.eq(uart.rx_dat))
|
self.sync += If(get_bl_done, burst_cnt.eq(uart.rx_dat))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Get address
|
# Get address
|
||||||
#
|
#
|
||||||
fsm.act(fsm.GET_ADDR,
|
fsm.act("GET_ADDR",
|
||||||
If(get_addr_done & (cmd == WRITE_CMD),
|
If(get_addr_done & (cmd == WRITE_CMD),
|
||||||
fsm.next_state(fsm.GET_DATA)
|
NextState("GET_DATA")
|
||||||
).Elif(get_addr_done & (cmd == READ_CMD),
|
).Elif(get_addr_done & (cmd == READ_CMD),
|
||||||
fsm.next_state(fsm.READ_CSR0)
|
NextState("READ_CSR0")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.comb += get_addr_done.eq(uart.rx_ev & (cnt == 4) & fsm.ongoing(fsm.GET_ADDR))
|
self.comb += get_addr_done.eq(uart.rx_ev & (cnt == 4) & fsm.ongoing("GET_ADDR"))
|
||||||
self.sync += get_addr_done_d.eq(get_addr_done)
|
self.sync += get_addr_done_d.eq(get_addr_done)
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(get_addr_done_d,
|
If(get_addr_done_d,
|
||||||
addr.eq(sr)
|
addr.eq(sr)
|
||||||
).Elif(fsm.leaving(fsm.WRITE_CSR) | send_data_done,
|
).Elif(fsm.leaving("WRITE_CSR") | send_data_done,
|
||||||
addr.eq(addr + 1)
|
addr.eq(addr + 1)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
@ -112,13 +109,13 @@ class Uart2Csr(Module):
|
||||||
#
|
#
|
||||||
# Get data
|
# Get data
|
||||||
#
|
#
|
||||||
fsm.act(fsm.GET_DATA,
|
fsm.act("GET_DATA",
|
||||||
If(get_data_done,
|
If(get_data_done,
|
||||||
fsm.next_state(fsm.WRITE_CSR)
|
NextState("WRITE_CSR")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing(fsm.GET_DATA))
|
self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing("GET_DATA"))
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(get_data_done,
|
If(get_data_done,
|
||||||
burst_cnt.eq(burst_cnt-1),
|
burst_cnt.eq(burst_cnt-1),
|
||||||
|
@ -129,46 +126,46 @@ class Uart2Csr(Module):
|
||||||
#
|
#
|
||||||
# Write Csr
|
# Write Csr
|
||||||
#
|
#
|
||||||
fsm.act(fsm.WRITE_CSR,
|
fsm.act("WRITE_CSR",
|
||||||
If((burst_cnt==0),
|
If((burst_cnt==0),
|
||||||
fsm.next_state(fsm.IDLE)
|
NextState("IDLE")
|
||||||
).Else(fsm.next_state(fsm.GET_DATA))
|
).Else(NextState("GET_DATA"))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Read Csr0
|
# Read Csr0
|
||||||
#
|
#
|
||||||
fsm.act(fsm.READ_CSR0,
|
fsm.act("READ_CSR0",
|
||||||
fsm.next_state(fsm.READ_CSR1)
|
NextState("READ_CSR1")
|
||||||
)
|
)
|
||||||
|
|
||||||
self.sync += If(fsm.entering(fsm.READ_CSR0), burst_cnt.eq(burst_cnt-1))
|
self.sync += If(fsm.entering("READ_CSR0"), burst_cnt.eq(burst_cnt-1))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Read Csr1
|
# Read Csr1
|
||||||
#
|
#
|
||||||
fsm.act(fsm.READ_CSR1,
|
fsm.act("READ_CSR1",
|
||||||
fsm.next_state(fsm.SEND_DATA)
|
NextState("SEND_DATA")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Send Data
|
# Send Data
|
||||||
#
|
#
|
||||||
fsm.act(fsm.SEND_DATA,
|
fsm.act("SEND_DATA",
|
||||||
If(send_data_done & (burst_cnt==0),
|
If(send_data_done & (burst_cnt==0),
|
||||||
fsm.next_state(fsm.IDLE)
|
NextState("IDLE")
|
||||||
).Elif(send_data_done,
|
).Elif(send_data_done,
|
||||||
fsm.next_state(fsm.READ_CSR0)
|
NextState("READ_CSR0")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.comb += send_data_done.eq(fsm.ongoing(fsm.SEND_DATA) & uart.tx_ev)
|
self.comb += send_data_done.eq(fsm.ongoing("SEND_DATA") & uart.tx_ev)
|
||||||
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
uart.tx_dat.eq(self.csr.dat_r),
|
uart.tx_dat.eq(self.csr.dat_r),
|
||||||
uart.tx_we.eq(fsm.entering(fsm.SEND_DATA)),
|
uart.tx_we.eq(fsm.entering("SEND_DATA")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,7 +175,7 @@ class Uart2Csr(Module):
|
||||||
self.comb += self.csr.adr.eq(addr)
|
self.comb += self.csr.adr.eq(addr)
|
||||||
self.sync +=[
|
self.sync +=[
|
||||||
self.csr.dat_w.eq(data),
|
self.csr.dat_w.eq(data),
|
||||||
If(fsm.ongoing(fsm.WRITE_CSR),
|
If(fsm.ongoing("WRITE_CSR"),
|
||||||
self.csr.we.eq(1)
|
self.csr.we.eq(1)
|
||||||
).Else(
|
).Else(
|
||||||
self.csr.we.eq(0)
|
self.csr.we.eq(0)
|
|
@ -19,9 +19,17 @@ class Uart2Csr:
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.uart = serial.Serial(port, baudrate, timeout=0.25)
|
self.uart = serial.Serial(port, baudrate, timeout=0.25)
|
||||||
|
|
||||||
def read(self, addr, burst_length=1):
|
def open(self):
|
||||||
|
self.uart.close()
|
||||||
|
self.uart.open()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.uart.close()
|
||||||
|
|
||||||
|
def read_csr(self, addr, burst_length=1):
|
||||||
write_b(self.uart, READ_CMD)
|
write_b(self.uart, READ_CMD)
|
||||||
write_b(self.uart, burst_length)
|
write_b(self.uart, burst_length)
|
||||||
|
addr = addr//4
|
||||||
write_b(self.uart, (addr & 0xff000000) >> 24)
|
write_b(self.uart, (addr & 0xff000000) >> 24)
|
||||||
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
||||||
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
||||||
|
@ -50,13 +58,14 @@ class Uart2Csr:
|
||||||
print("RD @ %04X" %addr)
|
print("RD @ %04X" %addr)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def write(self, addr, data):
|
def write_csr(self, addr, data):
|
||||||
if isinstance(data, list):
|
if isinstance(data, list):
|
||||||
burst_length = len(data)
|
burst_length = len(data)
|
||||||
else:
|
else:
|
||||||
burst_length = 1
|
burst_length = 1
|
||||||
write_b(self.uart, WRITE_CMD)
|
write_b(self.uart, WRITE_CMD)
|
||||||
write_b(self.uart, burst_length)
|
write_b(self.uart, burst_length)
|
||||||
|
addr = addr//4
|
||||||
self.uart.write([(addr & 0xff000000) >> 24,
|
self.uart.write([(addr & 0xff000000) >> 24,
|
||||||
(addr & 0x00ff0000) >> 16,
|
(addr & 0x00ff0000) >> 16,
|
||||||
(addr & 0x0000ff00) >> 8,
|
(addr & 0x0000ff00) >> 8,
|
|
@ -3,44 +3,17 @@ from migen.bus import csr
|
||||||
from migen.bank import csrgen
|
from migen.bank import csrgen
|
||||||
from migen.bank.description import *
|
from migen.bank.description import *
|
||||||
|
|
||||||
from miscope.tools.misc import *
|
class MiIo(Module, AutoCSR):
|
||||||
|
def __init__(self, width):
|
||||||
class MiIo:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, address, width, mode="IO", interface=None):
|
|
||||||
self.address = address
|
|
||||||
self.width = width
|
self.width = width
|
||||||
self.mode = mode.upper()
|
|
||||||
self.interface = interface
|
|
||||||
self.words = int((2**bits_for(width-1))/8)
|
|
||||||
|
|
||||||
if "I" in self.mode:
|
self.i = Signal(self.width)
|
||||||
self.i = Signal(self.width)
|
self.o = Signal(self.width)
|
||||||
self._r_i = CSRStatus(self.width)
|
|
||||||
|
|
||||||
if "O" in self.mode:
|
self._r_i = CSRStatus(self.width)
|
||||||
self.o = Signal(self.width)
|
self._r_o = CSRStorage(self.width)
|
||||||
self._r_o = CSRStorage(self.width)
|
|
||||||
|
|
||||||
self.bank = csrgen.Bank([self._r_o, self._r_i], address=self.address)
|
self.sync +=[
|
||||||
|
self._r_i.status.eq(self.i),
|
||||||
def get_fragment(self):
|
self.o.eq(self._r_o.storage)
|
||||||
comb = []
|
]
|
||||||
|
|
||||||
if "I" in self.mode:
|
|
||||||
comb += [self._r_i.status.eq(self.i)]
|
|
||||||
|
|
||||||
if "O" in self.mode:
|
|
||||||
comb += [self.o.eq(self._r_o.storage)]
|
|
||||||
|
|
||||||
return Fragment(comb) + self.bank.get_fragment()
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def set(self, data):
|
|
||||||
self.interface.write(get_csr_base(self.bank), data)
|
|
||||||
|
|
||||||
def get(self):
|
|
||||||
return self.interface.read(get_csr_base(self.bank) + self.words)
|
|
|
@ -1,48 +1,27 @@
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
|
from migen.flow.actor import *
|
||||||
|
from migen.flow.network import *
|
||||||
from migen.bus import csr
|
from migen.bus import csr
|
||||||
from migen.bank import description, csrgen
|
from migen.bank import description, csrgen
|
||||||
from migen.bank.description import *
|
from migen.bank.description import *
|
||||||
|
|
||||||
from miscope import trigger, recorder
|
class MiLa(Module, AutoCSR):
|
||||||
from miscope.tools.misc import *
|
def __init__(self, trigger, recorder):
|
||||||
|
|
||||||
class MiLa:
|
|
||||||
def __init__(self, address, trigger, recorder, interface=None, trig_is_dat=False):
|
|
||||||
|
|
||||||
self.trigger = trigger
|
self.trigger = trigger
|
||||||
self.recorder = recorder
|
self.recorder = recorder
|
||||||
self.interface = interface
|
|
||||||
self.trig_is_dat = trig_is_dat
|
|
||||||
|
|
||||||
self.stb = Signal(reset=1)
|
self.sink = trigger.sink
|
||||||
self.trig = Signal(self.trigger.width)
|
self.submodules += trigger, recorder
|
||||||
self.dat = Signal(self.recorder.width)
|
|
||||||
|
|
||||||
self.set_address(address)
|
self.comb +=[
|
||||||
self.set_interface(interface)
|
recorder.sink.stb.eq(trigger.source.stb),
|
||||||
|
|
||||||
def set_address(self, address):
|
recorder.sink.payload.hit.eq(trigger.source.payload.hit),
|
||||||
self.address = address
|
trigger.source.ack.eq(recorder.sink.ack)
|
||||||
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 get_fragment(self):
|
|
||||||
comb =[
|
|
||||||
self.recorder.stb.eq(self.stb),
|
|
||||||
self.trigger.trig.eq(self.trig),
|
|
||||||
|
|
||||||
self.recorder.hit.eq(self.trigger.hit)
|
|
||||||
]
|
]
|
||||||
if self.trig_is_dat:
|
|
||||||
comb +=[
|
|
||||||
self.recorder.dat.eq(self.trig),
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
self.recorder.dat.eq(self.dat),
|
|
||||||
|
|
||||||
return Fragment(comb)
|
# Todo; Insert configurable delay to support pipelined
|
||||||
|
# triggers elements
|
||||||
|
self.comb +=[
|
||||||
|
recorder.sink.payload.d.eq(self.sink.payload.d),
|
||||||
|
]
|
|
@ -1,324 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.specials import Memory
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.bank import description, csrgen
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.genlib.misc import optree
|
|
||||||
from migen.genlib.fsm import *
|
|
||||||
|
|
||||||
from miscope.tools.misc import *
|
|
||||||
|
|
||||||
class Storage:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width, depth):
|
|
||||||
self.width = width
|
|
||||||
self.depth = depth
|
|
||||||
self.depth_width = bits_for(self.depth)
|
|
||||||
|
|
||||||
# Control
|
|
||||||
self.rst = Signal()
|
|
||||||
self.start = Signal()
|
|
||||||
self.offset = Signal(self.depth_width)
|
|
||||||
self.size = Signal(self.depth_width)
|
|
||||||
self.done = Signal()
|
|
||||||
|
|
||||||
# Push Path
|
|
||||||
self.push_stb = Signal()
|
|
||||||
self.push_dat = Signal(self.width)
|
|
||||||
self._push_ptr = Signal(self.depth_width)
|
|
||||||
self._push_ptr_stop = Signal(self.depth_width)
|
|
||||||
|
|
||||||
# Pull Path
|
|
||||||
self.pull_stb = Signal()
|
|
||||||
self.pull_dat = Signal(self.width)
|
|
||||||
self._pull_ptr = Signal(self.depth_width)
|
|
||||||
|
|
||||||
# Memory
|
|
||||||
self._mem = Memory(self.width, self.depth)
|
|
||||||
self._push_port = self._mem.get_port(write_capable=True)
|
|
||||||
self._pull_port = self._mem.get_port(has_re=True)
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
comb = [
|
|
||||||
self._push_port.adr.eq(self._push_ptr),
|
|
||||||
self._push_port.we.eq(self.push_stb),
|
|
||||||
self._push_port.dat_w.eq(self.push_dat),
|
|
||||||
|
|
||||||
self._pull_port.adr.eq(self._pull_ptr),
|
|
||||||
self._pull_port.re.eq(self.pull_stb),
|
|
||||||
self.pull_dat.eq(self._pull_port.dat_r)
|
|
||||||
]
|
|
||||||
|
|
||||||
# FSM
|
|
||||||
fsm = FSM("IDLE", "ACTIVE")
|
|
||||||
|
|
||||||
# Idle
|
|
||||||
fsm.act(fsm.IDLE,
|
|
||||||
If(self.start,
|
|
||||||
fsm.next_state(fsm.ACTIVE),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Active
|
|
||||||
fsm.act(fsm.ACTIVE,
|
|
||||||
If(self.done | self.rst,
|
|
||||||
fsm.next_state(fsm.IDLE),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
sync =[
|
|
||||||
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)
|
|
||||||
).Else(
|
|
||||||
If(self.pull_stb, self._pull_ptr.eq(self._pull_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) & fsm.ongoing(fsm.ACTIVE))]
|
|
||||||
|
|
||||||
return Fragment(comb, sync, specials={self._mem}) + fsm.get_fragment()
|
|
||||||
|
|
||||||
class RLE:
|
|
||||||
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width, length):
|
|
||||||
self.width = width
|
|
||||||
self.length = length
|
|
||||||
|
|
||||||
# Control
|
|
||||||
self.enable = Signal()
|
|
||||||
|
|
||||||
# Input
|
|
||||||
self.stb_i = Signal()
|
|
||||||
self.dat_i = Signal(width)
|
|
||||||
|
|
||||||
# Output
|
|
||||||
self.stb_o = Signal()
|
|
||||||
self.dat_o = Signal(width)
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
|
|
||||||
# Register Input
|
|
||||||
stb_i_d = Signal()
|
|
||||||
dat_i_d = Signal(self.width)
|
|
||||||
|
|
||||||
sync =[dat_i_d.eq(self.dat_i)]
|
|
||||||
sync +=[stb_i_d.eq(self.stb_i)]
|
|
||||||
|
|
||||||
# Detect diff
|
|
||||||
diff = Signal()
|
|
||||||
comb = [diff.eq(self.stb_i & (~self.enable | (dat_i_d != self.dat_i)))]
|
|
||||||
|
|
||||||
diff_rising = RisingEdge(diff)
|
|
||||||
diff_d = Signal()
|
|
||||||
sync +=[diff_d.eq(diff)]
|
|
||||||
|
|
||||||
# Generate RLE word
|
|
||||||
rle_cnt = Signal(max=self.length)
|
|
||||||
rle_max = Signal()
|
|
||||||
|
|
||||||
comb +=[If(rle_cnt == self.length, rle_max.eq(self.enable))]
|
|
||||||
|
|
||||||
sync +=[
|
|
||||||
If(diff | rle_max,
|
|
||||||
rle_cnt.eq(0)
|
|
||||||
).Else(
|
|
||||||
rle_cnt.eq(rle_cnt + 1)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Mux RLE word and data
|
|
||||||
comb +=[
|
|
||||||
If(diff_rising.o & (~rle_max),
|
|
||||||
self.stb_o.eq(1),
|
|
||||||
self.dat_o[self.width-1].eq(1),
|
|
||||||
self.dat_o[:flen(rle_cnt)].eq(rle_cnt)
|
|
||||||
).Elif(diff_d | rle_max,
|
|
||||||
self.stb_o.eq(stb_i_d),
|
|
||||||
self.dat_o.eq(dat_i_d)
|
|
||||||
).Else(
|
|
||||||
self.stb_o.eq(0),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
return Fragment(comb, sync) + diff_rising.get_fragment()
|
|
||||||
|
|
||||||
class Sequencer:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self):
|
|
||||||
|
|
||||||
# Control
|
|
||||||
self.rst = Signal()
|
|
||||||
self.arm = Signal()
|
|
||||||
|
|
||||||
# Trigger
|
|
||||||
self.hit = Signal()
|
|
||||||
|
|
||||||
# Recorder
|
|
||||||
self.start = Signal()
|
|
||||||
self.done = Signal()
|
|
||||||
|
|
||||||
# Internal
|
|
||||||
self.enable = Signal()
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
|
|
||||||
# FSM
|
|
||||||
fsm = FSM("IDLE", "ACTIVE")
|
|
||||||
|
|
||||||
# Idle
|
|
||||||
fsm.act(fsm.IDLE,
|
|
||||||
If(self.arm,
|
|
||||||
fsm.next_state(fsm.ACTIVE),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Active
|
|
||||||
fsm.act(fsm.ACTIVE,
|
|
||||||
If(self.done | self.rst,
|
|
||||||
fsm.next_state(fsm.IDLE),
|
|
||||||
),
|
|
||||||
self.enable.eq(1)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Start
|
|
||||||
hit_rising = RisingEdge(self.hit)
|
|
||||||
comb =[self.start.eq(self.enable & hit_rising.o)]
|
|
||||||
|
|
||||||
return Fragment(comb) + fsm.get_fragment() + hit_rising.get_fragment()
|
|
||||||
|
|
||||||
|
|
||||||
REC_RST_BASE = 0x00
|
|
||||||
REC_RLE_BASE = 0x01
|
|
||||||
REC_ARM_BASE = 0x02
|
|
||||||
REC_DONE_BASE = 0x03
|
|
||||||
REC_SIZE_BASE = 0x04
|
|
||||||
REC_OFFSET_BASE = 0x06
|
|
||||||
REC_READ_BASE = 0x08
|
|
||||||
REC_READ_DATA_BASE = 0x09
|
|
||||||
|
|
||||||
class Recorder:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width, depth, address=0x0000, interface=None):
|
|
||||||
self.width = width
|
|
||||||
self.depth = depth
|
|
||||||
self.depth_width = bits_for(self.depth-1)
|
|
||||||
|
|
||||||
self.storage = Storage(self.width, self.depth)
|
|
||||||
self.sequencer = Sequencer()
|
|
||||||
self.rle = RLE(self.width, (2**(width-2)))
|
|
||||||
|
|
||||||
# csr interface
|
|
||||||
self._r_rst = CSRStorage(reset=1)
|
|
||||||
self._r_rle = CSRStorage(reset=0)
|
|
||||||
self._r_arm = CSRStorage(reset=0)
|
|
||||||
self._r_done = CSRStatus()
|
|
||||||
|
|
||||||
self._r_size = CSRStorage(self.depth_width, reset=1)
|
|
||||||
self._r_offset = CSRStorage(self.depth_width, reset=1)
|
|
||||||
|
|
||||||
self._r_pull_stb = CSRStorage(reset=0)
|
|
||||||
self._r_pull_dat = CSRStatus(self.width)
|
|
||||||
|
|
||||||
self.regs = [self._r_rst, self._r_rle, self._r_arm, self._r_done, self._r_size, self._r_offset,
|
|
||||||
self._r_pull_stb, self._r_pull_dat]
|
|
||||||
|
|
||||||
# set address / interface
|
|
||||||
self.set_address(address)
|
|
||||||
self.set_interface(interface)
|
|
||||||
|
|
||||||
# trigger Interface
|
|
||||||
self.hit = Signal()
|
|
||||||
self.stb = Signal()
|
|
||||||
self.dat = Signal(self.width)
|
|
||||||
|
|
||||||
def set_address(self, address):
|
|
||||||
self.address = address
|
|
||||||
self.bank = csrgen.Bank(self.regs, address=self.address)
|
|
||||||
|
|
||||||
def set_interface(self, interface):
|
|
||||||
self.interface = interface
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
|
|
||||||
_pull_stb_rising = RisingEdge(self._r_pull_stb.storage)
|
|
||||||
|
|
||||||
# Bank <--> Storage / Sequencer
|
|
||||||
comb = [
|
|
||||||
self.sequencer.rst.eq(self._r_rst.storage),
|
|
||||||
self.storage.rst.eq(self._r_rst.storage),
|
|
||||||
|
|
||||||
self.rle.enable.eq(self._r_rle.storage),
|
|
||||||
self.sequencer.arm.eq(self._r_arm.storage),
|
|
||||||
self.storage.offset.eq(self._r_offset.storage),
|
|
||||||
self.storage.size.eq(self._r_size.storage),
|
|
||||||
|
|
||||||
self._r_done.status.eq(~self.sequencer.enable),
|
|
||||||
|
|
||||||
self.storage.pull_stb.eq(_pull_stb_rising.o),
|
|
||||||
self._r_pull_dat.status.eq(self.storage.pull_dat)
|
|
||||||
]
|
|
||||||
|
|
||||||
# Storage <--> Sequencer <--> Trigger
|
|
||||||
comb += [
|
|
||||||
self.storage.start.eq(self.sequencer.start),
|
|
||||||
self.sequencer.done.eq(self.storage.done),
|
|
||||||
self.sequencer.hit.eq(self.hit),
|
|
||||||
|
|
||||||
self.rle.stb_i.eq(self.stb),
|
|
||||||
self.rle.dat_i.eq(self.dat),
|
|
||||||
|
|
||||||
self.storage.push_stb.eq(self.sequencer.enable & self.rle.stb_o),
|
|
||||||
self.storage.push_dat.eq(self.rle.dat_o)
|
|
||||||
]
|
|
||||||
|
|
||||||
return self.bank.get_fragment() + Fragment(comb) +\
|
|
||||||
self.storage.get_fragment() + self.sequencer.get_fragment() +\
|
|
||||||
_pull_stb_rising.get_fragment() + self.rle.get_fragment()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def reset(self):
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_RST_BASE, 1)
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_RST_BASE, 0)
|
|
||||||
|
|
||||||
def enable_rle(self):
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_RLE_BASE, 1)
|
|
||||||
|
|
||||||
def disable_rle(self):
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_RLE_BASE, 0)
|
|
||||||
|
|
||||||
def arm(self):
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_ARM_BASE, 1)
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_ARM_BASE, 0)
|
|
||||||
|
|
||||||
def is_done(self):
|
|
||||||
return self.interface.read(get_csr_base(self.bank) + REC_DONE_BASE) == 1
|
|
||||||
|
|
||||||
def set_size(self, dat):
|
|
||||||
self.interface.write_n(get_csr_base(self.bank) + REC_SIZE_BASE, dat, 16)
|
|
||||||
|
|
||||||
def set_offset(self, dat):
|
|
||||||
self.interface.write_n(get_csr_base(self.bank) + REC_OFFSET_BASE, dat, 16)
|
|
||||||
|
|
||||||
def pull(self, size):
|
|
||||||
r = []
|
|
||||||
for i in range(size):
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_READ_BASE, 1)
|
|
||||||
self.interface.write(get_csr_base(self.bank) + REC_READ_BASE, 0)
|
|
||||||
r.append(self.interface.read_n(get_csr_base(self.bank) + REC_READ_DATA_BASE, self.width))
|
|
||||||
if i%128 == 0:
|
|
||||||
print(i)
|
|
||||||
return r
|
|
86
miscope/recording/__init__.py
Normal file
86
miscope/recording/__init__.py
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.flow.actor import *
|
||||||
|
from migen.flow.network import *
|
||||||
|
from migen.fhdl.specials import Memory
|
||||||
|
from migen.bus import csr
|
||||||
|
from migen.bank import description, csrgen
|
||||||
|
from migen.bank.description import *
|
||||||
|
from migen.actorlib.fifo import SyncFIFO
|
||||||
|
|
||||||
|
class Recorder(Module, AutoCSR):
|
||||||
|
def __init__(self, width, depth):
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
self.sink = Sink([("hit", 1), ("d", width)])
|
||||||
|
|
||||||
|
self._r_trigger = CSR()
|
||||||
|
self._r_length = CSRStorage(bits_for(depth))
|
||||||
|
self._r_offset = CSRStorage(bits_for(depth))
|
||||||
|
self._r_done = CSRStatus()
|
||||||
|
|
||||||
|
self._r_read_en = CSR()
|
||||||
|
self._r_read_empty = CSRStatus()
|
||||||
|
self._r_read_dat = CSRStatus(width)
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
length = self._r_length.storage
|
||||||
|
offset = self._r_offset.storage
|
||||||
|
done = Signal(reset=1)
|
||||||
|
ongoing = Signal()
|
||||||
|
|
||||||
|
cnt = Signal(max=depth)
|
||||||
|
|
||||||
|
fifo = SyncFIFO([("d", width)], depth)
|
||||||
|
self.submodules += fifo
|
||||||
|
|
||||||
|
# Write fifo is done only when done = 0
|
||||||
|
# Fifo must always be pulled by software between
|
||||||
|
# acquisition (Todo: add a flush funtionnality)
|
||||||
|
self.comb +=[
|
||||||
|
fifo.sink.stb.eq(self.sink.stb & ~done),
|
||||||
|
fifo.sink.payload.d.eq(self.sink.payload.d),
|
||||||
|
self.sink.ack.eq(1)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Done, Ongoing:
|
||||||
|
# 0, 0 : Storage triggered but hit was not yet seen
|
||||||
|
# Data are recorded to fifo, if "offset" datas
|
||||||
|
# in the fifo, ack is set on fifo.source to
|
||||||
|
# store only "offset" datas.
|
||||||
|
#
|
||||||
|
# 0, 1 : Hit was seen, ack is no longer set on fifo.source
|
||||||
|
# we are storing "length"-"offset" data in this
|
||||||
|
# phase
|
||||||
|
#
|
||||||
|
# 1, 0 : We have stored "length" datas in fifo. Write to
|
||||||
|
# fifo is disabled.
|
||||||
|
# Software must now read data from the fifo until
|
||||||
|
# it is empty
|
||||||
|
|
||||||
|
# done & ongoing
|
||||||
|
self.sync += [
|
||||||
|
If(self._r_trigger.re & self._r_trigger.r, done.eq(0)
|
||||||
|
).Elif(cnt==length, done.eq(1)),
|
||||||
|
|
||||||
|
If(self.sink.stb & self.sink.payload.hit & ~done, ongoing.eq(1)
|
||||||
|
).Elif(done, ongoing.eq(0)),
|
||||||
|
]
|
||||||
|
|
||||||
|
# fifo ack & csr connection
|
||||||
|
self.comb += [
|
||||||
|
If(~done & ~ongoing & (cnt >= offset), fifo.source.ack.eq(1)
|
||||||
|
).Else(fifo.source.ack.eq(self._r_read_en.re & self._r_read_en.r)),
|
||||||
|
self._r_read_empty.status.eq(~fifo.source.stb),
|
||||||
|
self._r_read_dat.status.eq(fifo.source.payload.d),
|
||||||
|
self._r_done.status.eq(done)
|
||||||
|
]
|
||||||
|
|
||||||
|
# cnt
|
||||||
|
self.sync += [
|
||||||
|
If(done == 1,
|
||||||
|
cnt.eq(0)
|
||||||
|
).Elif(fifo.sink.stb & fifo.sink.ack & ~(fifo.source.stb & fifo.source.ack),
|
||||||
|
cnt.eq(cnt+1),
|
||||||
|
)
|
||||||
|
]
|
94
miscope/std/cif.py
Normal file
94
miscope/std/cif.py
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
from operator import itemgetter
|
||||||
|
import re
|
||||||
|
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.bank.description import CSRStatus
|
||||||
|
|
||||||
|
def get_macros(filename):
|
||||||
|
f = open(filename, "r")
|
||||||
|
r = {}
|
||||||
|
for line in f:
|
||||||
|
match = re.match("\w*#define\s+(\w+)\s+(.*)", line, re.IGNORECASE)
|
||||||
|
if match:
|
||||||
|
r[match.group(1)] = match.group(2)
|
||||||
|
return r
|
||||||
|
|
||||||
|
def _get_rw_functions(reg_name, reg_base, size, read_only):
|
||||||
|
r = ""
|
||||||
|
if size > 8:
|
||||||
|
raise NotImplementedError("Register too large")
|
||||||
|
elif size > 4:
|
||||||
|
ctype = "unsigned long long int"
|
||||||
|
elif size > 2:
|
||||||
|
ctype = "unsigned int"
|
||||||
|
elif size > 1:
|
||||||
|
ctype = "unsigned short int"
|
||||||
|
else:
|
||||||
|
ctype = "unsigned char"
|
||||||
|
|
||||||
|
r += "static inline "+ctype+" "+reg_name+"_read(void) {\n"
|
||||||
|
if size > 1:
|
||||||
|
r += "\t"+ctype+" r = MMPTR("+hex(reg_base)+");\n"
|
||||||
|
for byte in range(1, size):
|
||||||
|
r += "\tr <<= 8;\n\tr |= MMPTR("+hex(reg_base+4*byte)+");\n"
|
||||||
|
r += "\treturn r;\n}\n"
|
||||||
|
else:
|
||||||
|
r += "\treturn MMPTR("+hex(reg_base)+");\n}\n"
|
||||||
|
|
||||||
|
if not read_only:
|
||||||
|
r += "static inline void "+reg_name+"_write("+ctype+" value) {\n"
|
||||||
|
for byte in range(size):
|
||||||
|
shift = (size-byte-1)*8
|
||||||
|
if shift:
|
||||||
|
value_shifted = "value >> "+str(shift)
|
||||||
|
else:
|
||||||
|
value_shifted = "value"
|
||||||
|
r += "\tMMPTR("+hex(reg_base+4*byte)+") = "+value_shifted+";\n"
|
||||||
|
r += "}\n"
|
||||||
|
return r
|
||||||
|
|
||||||
|
def get_csr_header(csr_base, bank_array):
|
||||||
|
r = "#ifndef __HW_CSR_H\n#define __HW_CSR_H\n#include <hw/common.h>\n"
|
||||||
|
for name, csrs, mapaddr, rmap in bank_array.banks:
|
||||||
|
r += "\n/* "+name+" */\n"
|
||||||
|
reg_base = csr_base + 0x800*mapaddr
|
||||||
|
r += "#define "+name.upper()+"_BASE "+hex(reg_base)+"\n"
|
||||||
|
for csr in csrs:
|
||||||
|
nr = (csr.size + 7)//8
|
||||||
|
r += _get_rw_functions(name + "_" + csr.name, reg_base, nr, isinstance(csr, CSRStatus))
|
||||||
|
reg_base += 4*nr
|
||||||
|
r += "\n#endif\n"
|
||||||
|
return r
|
||||||
|
|
||||||
|
def _get_py_rw_functions(reg_name, reg_base, size):
|
||||||
|
r = ""
|
||||||
|
|
||||||
|
r += "def "+reg_name+"_read(bus):\n"
|
||||||
|
r += "\tr = bus.read_csr("+hex(reg_base)+")\n"
|
||||||
|
for byte in range(1, size):
|
||||||
|
r += "\tr <<= 8\n\tr |= bus.read_csr("+hex(reg_base+4*byte)+")\n"
|
||||||
|
r += "\treturn r\n\n"
|
||||||
|
|
||||||
|
|
||||||
|
r += "def "+reg_name+"_write(bus, value):\n"
|
||||||
|
for byte in range(size):
|
||||||
|
shift = (size-byte-1)*8
|
||||||
|
if shift:
|
||||||
|
value_shifted = "value >> "+str(shift)
|
||||||
|
else:
|
||||||
|
value_shifted = "value"
|
||||||
|
r += "\tbus.write_csr("+hex(reg_base+4*byte)+", ("+value_shifted+")&0xff)\n"
|
||||||
|
r += "\n"
|
||||||
|
return r
|
||||||
|
|
||||||
|
def get_py_csr_header(csr_base, bank_array):
|
||||||
|
r = ""
|
||||||
|
for name, csrs, mapaddr, rmap in bank_array.banks:
|
||||||
|
r += "\n# "+name+"\n"
|
||||||
|
reg_base = csr_base + 0x800*mapaddr
|
||||||
|
r += name.upper()+"_BASE ="+hex(reg_base)+"\n"
|
||||||
|
for csr in csrs:
|
||||||
|
nr = (csr.size + 7)//8
|
||||||
|
r += _get_py_rw_functions(name + "_" + csr.name, reg_base, nr)
|
||||||
|
reg_base += 4*nr
|
||||||
|
return r
|
|
@ -1,15 +1,19 @@
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl.module import Module
|
|
||||||
|
def ifthenelse(cond, r1, r2):
|
||||||
|
if cond != False and cond is not None:
|
||||||
|
return r1
|
||||||
|
else:
|
||||||
|
return r2
|
||||||
|
|
||||||
class RisingEdge(Module):
|
class RisingEdge(Module):
|
||||||
def __init__(self, i=None, o=None, domain="sys"):
|
def __init__(self, i=None, o=None):
|
||||||
self.i = ifthenelse(i, i, Signal())
|
self.i = ifthenelse(i, i, Signal())
|
||||||
self.o = ifthenelse(o, o, Signal())
|
self.o = ifthenelse(o, o, Signal())
|
||||||
####
|
####
|
||||||
i_d = Signal()
|
i_d = Signal()
|
||||||
sync =[i_d.eq(self.i)]
|
self.sync += i_d.eq(self.i)
|
||||||
self.comb +=[self.o.eq(self.i & ~i_d)]
|
self.comb += self.o.eq(self.i & ~i_d)
|
||||||
self._fragment += Fragment(sync={domain : sync})
|
|
||||||
|
|
||||||
class FallingEdge(Module):
|
class FallingEdge(Module):
|
||||||
def __init__(self, i=None, o=None, domain="sys"):
|
def __init__(self, i=None, o=None, domain="sys"):
|
||||||
|
@ -17,9 +21,8 @@ class FallingEdge(Module):
|
||||||
self.o = ifthenelse(o, o, Signal())
|
self.o = ifthenelse(o, o, Signal())
|
||||||
####
|
####
|
||||||
i_d = Signal()
|
i_d = Signal()
|
||||||
sync =[i_d.eq(self.i)]
|
self.sync += i_d.eq(self.i)
|
||||||
self.comb +=[self.o.eq(~self.i & i_d)]
|
self.comb += self.o.eq(~self.i & i_d)
|
||||||
self._fragment += Fragment(sync={domain : sync})
|
|
||||||
|
|
||||||
class FreqGen(Module):
|
class FreqGen(Module):
|
||||||
def __init__(self, clk_freq, freq, o=None):
|
def __init__(self, clk_freq, freq, o=None):
|
|
@ -1,123 +0,0 @@
|
||||||
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})
|
|
||||||
|
|
||||||
def get_csr_base(bank, name=None):
|
|
||||||
base = 0
|
|
||||||
if name != None:
|
|
||||||
base = None
|
|
||||||
for i, c in enumerate(bank.simple_csrs):
|
|
||||||
if name in c.name:
|
|
||||||
if base == None:
|
|
||||||
base = i
|
|
||||||
elif base >= i:
|
|
||||||
base = i
|
|
||||||
return (bank.address<<9) + base
|
|
|
@ -1,315 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.specials import Memory
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.bank import description, csrgen
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.genlib.misc import optree
|
|
||||||
|
|
||||||
from miscope.tools.misc import *
|
|
||||||
|
|
||||||
class RegParams:
|
|
||||||
def __init__(self, name, base, width, nb):
|
|
||||||
self.name = name
|
|
||||||
self.base = base
|
|
||||||
self.width = width
|
|
||||||
self.nb = nb
|
|
||||||
|
|
||||||
self.size = nb*width
|
|
||||||
self.words = int(2**bits_for(self.width-1)/8)
|
|
||||||
|
|
||||||
def list_regs(objects):
|
|
||||||
r = []
|
|
||||||
for object in objects:
|
|
||||||
if "_reg" in object:
|
|
||||||
r.append(objects[object])
|
|
||||||
return r
|
|
||||||
|
|
||||||
class Term:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width):
|
|
||||||
self.width = width
|
|
||||||
self.interface = None
|
|
||||||
|
|
||||||
self.i = Signal(width)
|
|
||||||
self.t = Signal(width)
|
|
||||||
self.m = Signal(width)
|
|
||||||
self.o = Signal()
|
|
||||||
|
|
||||||
self.reg_p = RegParams("term_reg", 0, width, 2)
|
|
||||||
self.reg = None
|
|
||||||
|
|
||||||
def get_registers_comb(self):
|
|
||||||
comb = [self.t.eq(self.reg.storage[0*self.width:1*self.width])]
|
|
||||||
comb += [self.m.eq(self.reg.storage[1*self.width:2*self.width])]
|
|
||||||
return comb
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
comb = [self.o.eq((self.m & self.i) == self.t)]
|
|
||||||
comb += self.get_registers_comb()
|
|
||||||
return Fragment(comb)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def set(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)
|
|
||||||
|
|
||||||
class RangeDetector:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width):
|
|
||||||
self.width = width
|
|
||||||
self.pipe = pipe
|
|
||||||
self.interface = None
|
|
||||||
|
|
||||||
self.reg_p = RegParams("range_reg", 0, width, 2)
|
|
||||||
self.reg = None
|
|
||||||
|
|
||||||
self.i = Signal(width)
|
|
||||||
self.low = Signal(width)
|
|
||||||
self.high = Signal(width)
|
|
||||||
self.o = Signal()
|
|
||||||
|
|
||||||
def get_registers_comb(self):
|
|
||||||
comb = [self.low.eq(self.reg.storage[0*self.width:1*self.width])]
|
|
||||||
comb += [self.low.eq(self.reg.storage[1*self.width:2*self.width])]
|
|
||||||
return comb
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
comb = [self.o.eq((self.i >= self.low) & (self.i <= self.high))]
|
|
||||||
comb += self.get_registers_comb()
|
|
||||||
return Fragment(comb)
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def set_low(self, dat):
|
|
||||||
self.interface.write_n(self.reg_p.base, dat ,self.width)
|
|
||||||
|
|
||||||
def set_high(self, dat):
|
|
||||||
self.interface.write_n(self.reg_p.base + self.reg_p.words, dat ,self.width)
|
|
||||||
|
|
||||||
class EdgeDetector:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width, mode="RFB"):
|
|
||||||
self.width = width
|
|
||||||
self.mode = mode
|
|
||||||
self.interface = None
|
|
||||||
|
|
||||||
self.reg_p = RegParams("edge_reg", 0, width, len(self.mode))
|
|
||||||
self.reg = None
|
|
||||||
|
|
||||||
self.i = Signal(self.width)
|
|
||||||
self.i_d = Signal(self.width)
|
|
||||||
if "R" in self.mode:
|
|
||||||
self.r_mask = Signal(self.width)
|
|
||||||
self.ro = Signal()
|
|
||||||
if "F" in self.mode:
|
|
||||||
self.f_mask = Signal(self.width)
|
|
||||||
self.fo = Signal()
|
|
||||||
if "B" in self.mode:
|
|
||||||
self.b_mask = Signal(self.width)
|
|
||||||
self.bo = Signal()
|
|
||||||
self.o = Signal()
|
|
||||||
|
|
||||||
def get_registers_comb(self):
|
|
||||||
comb = []
|
|
||||||
i = 0
|
|
||||||
if "R" in self.mode:
|
|
||||||
comb += [self.r_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])]
|
|
||||||
i += 1
|
|
||||||
if "F" in self.mode:
|
|
||||||
comb += [self.f_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])]
|
|
||||||
i += 1
|
|
||||||
if "B" in self.mode:
|
|
||||||
comb += [self.b_mask.eq(self.reg.storage[i*self.width:(i+1)*self.width])]
|
|
||||||
i += 1
|
|
||||||
return comb
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
comb = []
|
|
||||||
sync = [self.i_d.eq(self.i)]
|
|
||||||
|
|
||||||
# Rising Edge
|
|
||||||
if "R" in self.mode:
|
|
||||||
comb += [self.ro.eq(self.r_mask & self.i & (~self.i_d))]
|
|
||||||
else:
|
|
||||||
comb += [self.ro.eq(0)]
|
|
||||||
|
|
||||||
# Falling Edge
|
|
||||||
if "F" in self.mode:
|
|
||||||
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)]
|
|
||||||
else:
|
|
||||||
comb += [self.bo.eq(0)]
|
|
||||||
|
|
||||||
# Output
|
|
||||||
comb += [self.o.eq(self.ro | self.fo | self.bo)]
|
|
||||||
|
|
||||||
# Registers
|
|
||||||
comb += self.get_registers_comb()
|
|
||||||
|
|
||||||
return Fragment(comb, sync)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def get_offset(self, type):
|
|
||||||
if type == "R":
|
|
||||||
r = 0
|
|
||||||
r = r + self.words if "F" in self.mode else r
|
|
||||||
r = r + self.words if "B" in self.mode else r
|
|
||||||
return r
|
|
||||||
elif type == "F":
|
|
||||||
r = 0
|
|
||||||
r = r + self.words if "B" in self.mode else r
|
|
||||||
return r
|
|
||||||
elif type == "B":
|
|
||||||
r = 0
|
|
||||||
return r
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def set_r(self, dat):
|
|
||||||
self.interface.write_n(self.reg_p.base + self.get_offset("R"), dat ,self.width)
|
|
||||||
|
|
||||||
def set_f(self, dat):
|
|
||||||
self.interface.write_n(self.reg_p.base + self.get_offset("F"), dat ,self.width)
|
|
||||||
|
|
||||||
def set_b(self, dat):
|
|
||||||
self.interface.write_n(self.reg_p.base + self.get_offset("B"), dat ,self.width)
|
|
||||||
|
|
||||||
class Sum:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width=4):
|
|
||||||
self.width = width
|
|
||||||
self.interface = None
|
|
||||||
|
|
||||||
self.i = Signal(self.width)
|
|
||||||
self.o = Signal()
|
|
||||||
|
|
||||||
self.reg_p = RegParams("sum_reg", 0, 8, 4)
|
|
||||||
self.reg = None
|
|
||||||
|
|
||||||
self.prog_stb = Signal()
|
|
||||||
self.prog_adr = Signal(width)
|
|
||||||
self.prog_dat = Signal()
|
|
||||||
|
|
||||||
self._mem = Memory(1, 2**self.width)
|
|
||||||
self._lut_port = self._mem.get_port()
|
|
||||||
self._prog_port = self._mem.get_port(write_capable=True)
|
|
||||||
|
|
||||||
def get_registers_comb(self):
|
|
||||||
comb = [
|
|
||||||
self.prog_adr.eq(self.reg.storage[0:16]),
|
|
||||||
self.prog_dat.eq(self.reg.storage[16]),
|
|
||||||
self.prog_stb.eq(self.reg.storage[17])
|
|
||||||
]
|
|
||||||
return comb
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
comb = [
|
|
||||||
self._lut_port.adr.eq(self.i),
|
|
||||||
|
|
||||||
self._prog_port.adr.eq(self.prog_adr),
|
|
||||||
self._prog_port.we.eq(self.prog_stb),
|
|
||||||
self._prog_port.dat_w.eq(self.prog_dat),
|
|
||||||
|
|
||||||
self.o.eq(self._lut_port.dat_r),
|
|
||||||
]
|
|
||||||
comb += self.get_registers_comb()
|
|
||||||
return Fragment(comb, specials={self._mem})
|
|
||||||
|
|
||||||
#
|
|
||||||
# Driver
|
|
||||||
#
|
|
||||||
def set(self, truth_table):
|
|
||||||
for i in range(len(truth_table)):
|
|
||||||
val = truth_table[i]
|
|
||||||
we = 1<<17
|
|
||||||
dat = val<<16
|
|
||||||
addr = i
|
|
||||||
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:
|
|
||||||
#
|
|
||||||
# Definition
|
|
||||||
#
|
|
||||||
def __init__(self, width, ports, address=0x0000, interface=None):
|
|
||||||
self.width = width
|
|
||||||
self.ports = ports
|
|
||||||
|
|
||||||
self.sum = Sum(len(ports))
|
|
||||||
self.trig = Signal(self.width)
|
|
||||||
self.hit = Signal()
|
|
||||||
|
|
||||||
# insert port number in port reg name
|
|
||||||
for i in range(len(self.ports)):
|
|
||||||
self.ports[i].reg_p.name += "_%d"%i
|
|
||||||
|
|
||||||
# generate ports csr registers fields
|
|
||||||
for port in self.ports:
|
|
||||||
rf = CSRStorage(port.reg_p.size, reset=0, name=port.reg_p.name)
|
|
||||||
setattr(self, port.reg_p.name, rf)
|
|
||||||
|
|
||||||
# generate sum csr registers fields
|
|
||||||
self.sum_reg = CSRStorage(self.sum.reg_p.size, reset=0, name=self.sum.reg_p.name)
|
|
||||||
|
|
||||||
# generate registers
|
|
||||||
self.regs = list_regs(self.__dict__)
|
|
||||||
self.bank = csrgen.Bank(self.regs, address=address)
|
|
||||||
|
|
||||||
# update base addr & interface
|
|
||||||
self.set_address(address)
|
|
||||||
self.set_interface(interface)
|
|
||||||
self.set_registers()
|
|
||||||
|
|
||||||
def set_address(self, address):
|
|
||||||
self.address = address
|
|
||||||
self.bank = csrgen.Bank(self.regs, address=self.address)
|
|
||||||
for port in self.ports:
|
|
||||||
port.reg_p.base = get_csr_base(self.bank, port.reg_p.name)
|
|
||||||
self.sum.reg_p.base = get_csr_base(self.bank, self.sum.reg_p.name)
|
|
||||||
|
|
||||||
def set_interface(self, interface):
|
|
||||||
self.interface = interface
|
|
||||||
for port in self.ports:
|
|
||||||
port.interface = self.interface
|
|
||||||
self.sum.interface = self.interface
|
|
||||||
|
|
||||||
def set_registers(self):
|
|
||||||
self.sum.reg=self.sum_reg
|
|
||||||
for port in self.ports:
|
|
||||||
port.reg=getattr(self, port.reg_p.name)
|
|
||||||
|
|
||||||
def get_fragment(self):
|
|
||||||
# connect trig to input of each trig element
|
|
||||||
comb = [port.i.eq(self.trig) for port in self.ports]
|
|
||||||
|
|
||||||
# connect output of trig elements to sum
|
|
||||||
comb += [self.sum.i[j].eq(self.ports[j].o) for j in range(len(self.ports))]
|
|
||||||
|
|
||||||
# connect sum ouput to hit
|
|
||||||
comb += [self.hit.eq(self.sum.o)]
|
|
||||||
|
|
||||||
# add ports & sum to frag
|
|
||||||
frag = self.bank.get_fragment()
|
|
||||||
frag += self.sum.get_fragment()
|
|
||||||
for port in self.ports:
|
|
||||||
frag += port.get_fragment()
|
|
||||||
|
|
||||||
return frag + Fragment(comb)
|
|
95
miscope/triggering/__init__.py
Normal file
95
miscope/triggering/__init__.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.flow.actor import *
|
||||||
|
from migen.flow.network import *
|
||||||
|
from migen.fhdl.specials import Memory
|
||||||
|
from migen.bus import csr
|
||||||
|
from migen.bank import description, csrgen
|
||||||
|
from migen.bank.description import *
|
||||||
|
|
||||||
|
class Term(Module, AutoCSR):
|
||||||
|
def __init__(self, width):
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
self.sink = Sink([("d", width)])
|
||||||
|
self.source = Source([("hit", 1)])
|
||||||
|
|
||||||
|
self.busy = Signal()
|
||||||
|
|
||||||
|
self._r_trig = CSRStorage(width)
|
||||||
|
self._r_mask = CSRStorage(width)
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
trig = self._r_trig.storage
|
||||||
|
mask = self._r_mask.storage
|
||||||
|
|
||||||
|
hit = Signal()
|
||||||
|
|
||||||
|
self.comb +=[
|
||||||
|
hit.eq((self.sink.payload.d & mask) == trig),
|
||||||
|
self.source.stb.eq(self.sink.stb),
|
||||||
|
self.sink.ack.eq(self.sink.ack),
|
||||||
|
self.source.payload.hit.eq(hit)
|
||||||
|
]
|
||||||
|
|
||||||
|
class Sum(Module, AutoCSR):
|
||||||
|
def __init__(self, ports=4):
|
||||||
|
|
||||||
|
self.sinks = [Sink([("hit", 1)]) for p in range(ports)]
|
||||||
|
self.source = Source([("hit", 1)])
|
||||||
|
|
||||||
|
self._r_prog_we = CSRStorage()
|
||||||
|
self._r_prog_adr = CSRStorage(ports) #FIXME
|
||||||
|
self._r_prog_dat = CSRStorage()
|
||||||
|
|
||||||
|
mem = Memory(1, 2**ports)
|
||||||
|
lut_port = mem.get_port()
|
||||||
|
prog_port = mem.get_port(write_capable=True)
|
||||||
|
|
||||||
|
self.specials += mem, lut_port, prog_port
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
# Lut prog
|
||||||
|
self.comb +=[
|
||||||
|
prog_port.we.eq(self._r_prog_we.storage),
|
||||||
|
prog_port.adr.eq(self._r_prog_adr.storage),
|
||||||
|
prog_port.dat_w.eq(self._r_prog_dat.storage)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Lut read
|
||||||
|
for i, sink in enumerate(self.sinks):
|
||||||
|
self.comb += lut_port.adr[i].eq(sink.payload.hit)
|
||||||
|
|
||||||
|
# Drive source
|
||||||
|
self.comb +=[
|
||||||
|
self.source.stb.eq(optree("&", [sink.stb for sink in self.sinks])),
|
||||||
|
self.source.payload.hit.eq(lut_port.dat_r),
|
||||||
|
[sink.ack.eq(self.source.ack) for sink in self.sinks]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class Trigger(Module, AutoCSR):
|
||||||
|
def __init__(self, width, ports):
|
||||||
|
self.width = width
|
||||||
|
self.ports = ports
|
||||||
|
|
||||||
|
self.submodules.sum = Sum(len(ports))
|
||||||
|
|
||||||
|
# FIXME : when self.submodules += is used,
|
||||||
|
# get_csrs() is not called
|
||||||
|
for i, port in enumerate(ports):
|
||||||
|
tmp = "self.submodules.port"+str(i)+" = port"
|
||||||
|
exec(tmp)
|
||||||
|
|
||||||
|
self.sink = Sink([("d", width)])
|
||||||
|
self.source = self.sum.source
|
||||||
|
self.busy = Signal()
|
||||||
|
|
||||||
|
###
|
||||||
|
for i, port in enumerate(ports):
|
||||||
|
self.comb +=[
|
||||||
|
port.sink.stb.eq(self.sink.stb),
|
||||||
|
port.sink.payload.d.eq(self.sink.payload.d),
|
||||||
|
port.source.connect(self.sum.sinks[i])
|
||||||
|
]
|
|
@ -1,111 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.sim.generic import Simulator, PureSimulable, TopLevel
|
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
|
|
||||||
from miscope.recorder import *
|
|
||||||
|
|
||||||
arm_done = False
|
|
||||||
dat = 0
|
|
||||||
|
|
||||||
rec_done = False
|
|
||||||
|
|
||||||
dat_rdy = False
|
|
||||||
|
|
||||||
rec_size = 128
|
|
||||||
|
|
||||||
def csr_transactions():
|
|
||||||
|
|
||||||
# Reset
|
|
||||||
yield TWrite(REC_RST_BASE, 1)
|
|
||||||
yield TWrite(REC_RST_BASE, 0)
|
|
||||||
|
|
||||||
# RLE
|
|
||||||
yield TWrite(REC_RLE_BASE, 1)
|
|
||||||
|
|
||||||
# Size
|
|
||||||
yield TWrite(REC_SIZE_BASE + 0, 0)
|
|
||||||
yield TWrite(REC_SIZE_BASE + 1, rec_size)
|
|
||||||
|
|
||||||
# Offset
|
|
||||||
yield TWrite(REC_OFFSET_BASE + 0, 0)
|
|
||||||
yield TWrite(REC_OFFSET_BASE + 1, 0)
|
|
||||||
|
|
||||||
# Arm
|
|
||||||
yield TWrite(REC_ARM_BASE, 1)
|
|
||||||
yield TWrite(REC_ARM_BASE, 0)
|
|
||||||
|
|
||||||
for t in range(10):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
global arm_done
|
|
||||||
arm_done = True
|
|
||||||
|
|
||||||
global rec_done
|
|
||||||
while not rec_done:
|
|
||||||
yield None
|
|
||||||
|
|
||||||
global dat_rdy
|
|
||||||
for t in range(rec_size):
|
|
||||||
yield TWrite(REC_READ_BASE, 1)
|
|
||||||
dat_rdy = False
|
|
||||||
yield TWrite(REC_READ_BASE, 0)
|
|
||||||
yield TRead(REC_READ_DATA_BASE + 0)
|
|
||||||
yield TRead(REC_READ_DATA_BASE + 1)
|
|
||||||
yield TRead(REC_READ_DATA_BASE + 2)
|
|
||||||
yield TRead(REC_READ_DATA_BASE + 3)
|
|
||||||
dat_rdy = True
|
|
||||||
|
|
||||||
dat_rdy = False
|
|
||||||
|
|
||||||
for t in range(100):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Csr Master
|
|
||||||
csr_master0 = csr.Initiator(csr_transactions())
|
|
||||||
|
|
||||||
# Recorder
|
|
||||||
recorder0 = Recorder(32, 1024)
|
|
||||||
|
|
||||||
# Csr Interconnect
|
|
||||||
csrcon0 = csr.Interconnect(csr_master0.bus,
|
|
||||||
[
|
|
||||||
recorder0.bank.bus
|
|
||||||
])
|
|
||||||
|
|
||||||
# Recorder Data
|
|
||||||
def recorder_data(s):
|
|
||||||
global arm_done
|
|
||||||
if arm_done:
|
|
||||||
s.wr(recorder0.hit, 1)
|
|
||||||
arm_done = False
|
|
||||||
|
|
||||||
global dat
|
|
||||||
s.wr(recorder0.dat, dat//5)
|
|
||||||
dat += 1
|
|
||||||
|
|
||||||
global rec_done
|
|
||||||
if s.rd(recorder0.sequencer.enable) == 0:
|
|
||||||
rec_done = True
|
|
||||||
|
|
||||||
if dat_rdy:
|
|
||||||
print("%08X" %s.rd(recorder0._pull_dat.field.w))
|
|
||||||
|
|
||||||
# Simulation
|
|
||||||
def end_simulation(s):
|
|
||||||
s.interrupt = csr_master0.done
|
|
||||||
|
|
||||||
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, TopLevel("tb_RecorderCsr.vcd"))
|
|
||||||
sim.run(10000)
|
|
||||||
|
|
||||||
main()
|
|
||||||
print("Sim Done")
|
|
||||||
input()
|
|
|
@ -1,114 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.sim.generic import Simulator, PureSimulable, TopLevel
|
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
|
|
||||||
from miscope import trigger
|
|
||||||
from miscope.tools.truthtable import *
|
|
||||||
|
|
||||||
def term_prog(off, dat):
|
|
||||||
for i in range(4):
|
|
||||||
yield TWrite(off+3-i, (dat>>(8*i))&0xFF)
|
|
||||||
|
|
||||||
def sum_prog(off, addr, dat):
|
|
||||||
we = 2
|
|
||||||
yield TWrite(off+3, addr%0xFF)
|
|
||||||
yield TWrite(off+2, (addr>>8)%0xFF)
|
|
||||||
yield TWrite(off+1, we+dat)
|
|
||||||
yield TWrite(off+0, 0)
|
|
||||||
for i in range(4):
|
|
||||||
yield TWrite(off+i,0)
|
|
||||||
|
|
||||||
|
|
||||||
csr_done = False
|
|
||||||
|
|
||||||
def csr_transactions():
|
|
||||||
|
|
||||||
term_trans = []
|
|
||||||
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
|
|
||||||
|
|
||||||
sum_trans = []
|
|
||||||
sum_trans += [sum_prog(0x00, i, 1) for i in range(8)]
|
|
||||||
sum_trans += [sum_prog(0x00, i, 0) for i in range(8)]
|
|
||||||
for t in sum_trans:
|
|
||||||
for r in t:
|
|
||||||
yield r
|
|
||||||
|
|
||||||
sum_tt = gen_truth_table("i1 & i2 & i3 & i4")
|
|
||||||
sum_trans = []
|
|
||||||
for i in range(len(sum_tt)):
|
|
||||||
sum_trans.append(sum_prog(0x00, i, sum_tt[i]))
|
|
||||||
print(sum_tt)
|
|
||||||
for t in sum_trans:
|
|
||||||
for r in t:
|
|
||||||
yield r
|
|
||||||
|
|
||||||
global csr_done
|
|
||||||
csr_done = True
|
|
||||||
|
|
||||||
for t in range(100):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Csr Master
|
|
||||||
csr_master0 = csr.Initiator(csr_transactions())
|
|
||||||
|
|
||||||
# Trigger
|
|
||||||
term0 = trigger.Term(32)
|
|
||||||
term1 = trigger.Term(32)
|
|
||||||
term2 = trigger.Term(32)
|
|
||||||
term3 = trigger.Term(32)
|
|
||||||
trigger0 = trigger.Trigger(32, [term0, term1, term2, term3])
|
|
||||||
|
|
||||||
# Csr Interconnect
|
|
||||||
csrcon0 = csr.Interconnect(csr_master0.bus,
|
|
||||||
[
|
|
||||||
trigger0.bank.bus
|
|
||||||
])
|
|
||||||
|
|
||||||
# Term Test
|
|
||||||
def term_stimuli(s):
|
|
||||||
if csr_done:
|
|
||||||
s.wr(term0.i, 0xDEADBEEF)
|
|
||||||
s.wr(term1.i ,0xCAFEFADE)
|
|
||||||
s.wr(term2.i, 0xDEADBEEF)
|
|
||||||
s.wr(term3.i, 0xCAFEFADE)
|
|
||||||
|
|
||||||
|
|
||||||
# Simulation
|
|
||||||
def end_simulation(s):
|
|
||||||
s.interrupt = csr_master0.done
|
|
||||||
|
|
||||||
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, TopLevel("tb_TriggerCsr.vcd"))
|
|
||||||
sim.run(2000)
|
|
||||||
|
|
||||||
main()
|
|
||||||
print("Sim Done")
|
|
||||||
input()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,192 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl import verilog
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.sim.generic import Simulator, PureSimulable, TopLevel
|
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
|
|
||||||
from miscope.trigger import *
|
|
||||||
from miscope.recorder import *
|
|
||||||
from miscope.tools.truthtable import *
|
|
||||||
from miscope.tools.vcd import *
|
|
||||||
|
|
||||||
TRIGGER_ADDR = 0x0000
|
|
||||||
RECORDER_ADDR = 0x0200
|
|
||||||
|
|
||||||
rec_done = False
|
|
||||||
dat_rdy = False
|
|
||||||
|
|
||||||
dat_vcd = VcdDat(32)
|
|
||||||
rec_size = 64
|
|
||||||
|
|
||||||
def term_prog(off, dat):
|
|
||||||
for i in range(4):
|
|
||||||
yield TWrite(off+3-i, (dat>>(8*i))&0xFF)
|
|
||||||
|
|
||||||
|
|
||||||
def sum_prog(off, addr, dat):
|
|
||||||
we = 2
|
|
||||||
yield TWrite(off+3, addr%0xFF)
|
|
||||||
yield TWrite(off+2, (addr>>8)%0xFF)
|
|
||||||
yield TWrite(off+1, we+dat)
|
|
||||||
yield TWrite(off+0, 0)
|
|
||||||
for i in range(4):
|
|
||||||
yield TWrite(off+i,0)
|
|
||||||
|
|
||||||
def csr_transactions(trigger0, recorder0):
|
|
||||||
|
|
||||||
# Trigger Prog
|
|
||||||
##############################
|
|
||||||
|
|
||||||
# Term Prog
|
|
||||||
term_trans = []
|
|
||||||
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
|
|
||||||
|
|
||||||
# Sum Prog
|
|
||||||
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_p.base, i, sum_tt[i]))
|
|
||||||
for t in sum_trans:
|
|
||||||
for r in t:
|
|
||||||
yield r
|
|
||||||
|
|
||||||
# Recorder Prog
|
|
||||||
##############################
|
|
||||||
#Reset
|
|
||||||
yield TWrite(recorder0.address + REC_RST_BASE, 1)
|
|
||||||
yield TWrite(recorder0.address + REC_RST_BASE, 0)
|
|
||||||
|
|
||||||
# RLE
|
|
||||||
yield TWrite(REC_RLE_BASE, 0)
|
|
||||||
|
|
||||||
#Size
|
|
||||||
yield TWrite(recorder0.address + REC_SIZE_BASE + 0, 0)
|
|
||||||
yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, rec_size)
|
|
||||||
|
|
||||||
#Offset
|
|
||||||
yield TWrite(recorder0.address + REC_OFFSET_BASE + 0, 0)
|
|
||||||
yield TWrite(recorder0.address + REC_OFFSET_BASE + 1, 16)
|
|
||||||
|
|
||||||
#Arm
|
|
||||||
yield TWrite(recorder0.address + REC_ARM_BASE, 1)
|
|
||||||
yield TWrite(recorder0.address + REC_ARM_BASE, 0)
|
|
||||||
|
|
||||||
# Wait Record to be done
|
|
||||||
##############################
|
|
||||||
global rec_done
|
|
||||||
while not rec_done:
|
|
||||||
yield None
|
|
||||||
|
|
||||||
# Read recorded data
|
|
||||||
##############################
|
|
||||||
global dat_rdy
|
|
||||||
for t in range(rec_size):
|
|
||||||
yield TWrite(recorder0.address + REC_READ_BASE, 1)
|
|
||||||
dat_rdy = False
|
|
||||||
yield TWrite(recorder0.address + REC_READ_BASE, 0)
|
|
||||||
yield TRead(recorder0.address + REC_READ_DATA_BASE + 0)
|
|
||||||
yield TRead(recorder0.address + REC_READ_DATA_BASE + 1)
|
|
||||||
yield TRead(recorder0.address + REC_READ_DATA_BASE + 2)
|
|
||||||
yield TRead(recorder0.address + REC_READ_DATA_BASE + 3)
|
|
||||||
dat_rdy = True
|
|
||||||
|
|
||||||
dat_rdy = False
|
|
||||||
|
|
||||||
for t in range(512):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
|
|
||||||
trig_sig_val = 0
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
|
|
||||||
# Trigger
|
|
||||||
term0 = Term(32)
|
|
||||||
term1 = Term(32)
|
|
||||||
term2 = Term(32)
|
|
||||||
term3 = Term(32)
|
|
||||||
trigger0 = Trigger(32, [term0, term1, term2, term3], address=TRIGGER_ADDR)
|
|
||||||
|
|
||||||
# Recorder
|
|
||||||
recorder0 = Recorder(32, 1024, address=RECORDER_ADDR)
|
|
||||||
|
|
||||||
# Csr Master
|
|
||||||
csr_master0 = csr.Initiator(csr_transactions(trigger0, recorder0))
|
|
||||||
|
|
||||||
# Csr Interconnect
|
|
||||||
csrcon0 = csr.Interconnect(csr_master0.bus,
|
|
||||||
[
|
|
||||||
trigger0.bank.bus,
|
|
||||||
recorder0.bank.bus
|
|
||||||
])
|
|
||||||
|
|
||||||
trig_sig = Signal(32)
|
|
||||||
comb =[
|
|
||||||
trigger0.trig.eq(trig_sig)
|
|
||||||
]
|
|
||||||
|
|
||||||
comb += [
|
|
||||||
recorder0.dat.eq(trig_sig),
|
|
||||||
recorder0.hit.eq(trigger0.hit)
|
|
||||||
]
|
|
||||||
# Term Test
|
|
||||||
def term_stimuli(s):
|
|
||||||
global trig_sig_val
|
|
||||||
s.wr(trig_sig,trig_sig_val)
|
|
||||||
trig_sig_val += 1
|
|
||||||
trig_sig_val = trig_sig_val % 256
|
|
||||||
|
|
||||||
# Recorder Data
|
|
||||||
def recorder_data(s):
|
|
||||||
global rec_done
|
|
||||||
if s.rd(recorder0.sequencer.done) == 1:
|
|
||||||
rec_done = True
|
|
||||||
|
|
||||||
global dat_rdy
|
|
||||||
if dat_rdy:
|
|
||||||
print("%08X" %s.rd(recorder0._pull_dat.field.w))
|
|
||||||
global dat_vcd
|
|
||||||
dat_vcd.append(s.rd(recorder0._pull_dat.field.w))
|
|
||||||
|
|
||||||
|
|
||||||
# Simulation
|
|
||||||
def end_simulation(s):
|
|
||||||
s.interrupt = csr_master0.done
|
|
||||||
myvcd = Vcd()
|
|
||||||
myvcd.add(Var("trig_dat", 32, dat_vcd))
|
|
||||||
f = open("tb_miscope_out.vcd", "w")
|
|
||||||
f.write(str(myvcd))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
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, TopLevel("tb_miscope.vcd"))
|
|
||||||
sim.run(2000)
|
|
||||||
|
|
||||||
main()
|
|
||||||
print("Sim Done")
|
|
||||||
input()
|
|
142
sim/tb_recorder_csr.py
Normal file
142
sim/tb_recorder_csr.py
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.fhdl import verilog
|
||||||
|
from migen.bus import csr
|
||||||
|
from migen.sim.generic import Simulator, TopLevel
|
||||||
|
from migen.sim.icarus import Runner
|
||||||
|
from migen.bus.transactions import *
|
||||||
|
|
||||||
|
from miscope.recording import *
|
||||||
|
from miscope.std.truthtable import *
|
||||||
|
|
||||||
|
from miscope.std import cif
|
||||||
|
|
||||||
|
from mibuild.tools import write_to_file
|
||||||
|
|
||||||
|
try:
|
||||||
|
from csr_header import *
|
||||||
|
print("csr_header imported")
|
||||||
|
except:
|
||||||
|
print("csr_header not found")
|
||||||
|
|
||||||
|
class Csr2Trans():
|
||||||
|
def __init__(self):
|
||||||
|
self.t = []
|
||||||
|
|
||||||
|
def write_csr(self, adr, value):
|
||||||
|
self.t.append(TWrite(adr//4, value))
|
||||||
|
|
||||||
|
def read_csr(self, adr):
|
||||||
|
self.t.append(TRead(adr//4))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
triggered = False
|
||||||
|
dat = 0
|
||||||
|
|
||||||
|
rec_done = False
|
||||||
|
|
||||||
|
dat_rdy = False
|
||||||
|
|
||||||
|
rec_length = 128
|
||||||
|
|
||||||
|
def csr_configure():
|
||||||
|
bus = Csr2Trans()
|
||||||
|
|
||||||
|
# Length
|
||||||
|
recorder_length_write(bus, rec_length)
|
||||||
|
|
||||||
|
# Offset
|
||||||
|
recorder_offset_write(bus, 0)
|
||||||
|
|
||||||
|
# Trigger
|
||||||
|
recorder_trigger_write(bus, 1)
|
||||||
|
|
||||||
|
return bus.t
|
||||||
|
|
||||||
|
def csr_read_data():
|
||||||
|
bus = Csr2Trans()
|
||||||
|
|
||||||
|
for i in range(rec_length+100):
|
||||||
|
recorder_read_dat_read(bus)
|
||||||
|
recorder_read_en_write(bus, 1)
|
||||||
|
return bus.t
|
||||||
|
|
||||||
|
def csr_transactions():
|
||||||
|
for t in csr_configure():
|
||||||
|
yield t
|
||||||
|
|
||||||
|
for t in range(100):
|
||||||
|
yield None
|
||||||
|
|
||||||
|
global triggered
|
||||||
|
triggered = True
|
||||||
|
|
||||||
|
for t in range(512):
|
||||||
|
yield None
|
||||||
|
|
||||||
|
for t in csr_read_data():
|
||||||
|
yield t
|
||||||
|
|
||||||
|
for t in range(100):
|
||||||
|
yield None
|
||||||
|
|
||||||
|
|
||||||
|
class TB(Module):
|
||||||
|
csr_base = 0
|
||||||
|
csr_map = {
|
||||||
|
"recorder": 1,
|
||||||
|
}
|
||||||
|
def __init__(self, first_run=False):
|
||||||
|
self.csr_base = 0
|
||||||
|
|
||||||
|
# Csr Master
|
||||||
|
if not first_run:
|
||||||
|
self.submodules.master = csr.Initiator(csr_transactions())
|
||||||
|
|
||||||
|
# Recorder
|
||||||
|
self.submodules.recorder = Recorder(32, 1024)
|
||||||
|
|
||||||
|
# Csr
|
||||||
|
self.submodules.csrbankarray = csrgen.BankArray(self,
|
||||||
|
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
||||||
|
if not first_run:
|
||||||
|
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
||||||
|
|
||||||
|
# Recorder Data
|
||||||
|
def recorder_data(self, s):
|
||||||
|
s.wr(self.recorder.sink.stb, 1)
|
||||||
|
if not hasattr(self, "cnt"):
|
||||||
|
self.cnt = 0
|
||||||
|
self.cnt += 1
|
||||||
|
|
||||||
|
s.wr(self.recorder.sink.payload.d, self.cnt)
|
||||||
|
|
||||||
|
global triggered
|
||||||
|
if triggered:
|
||||||
|
s.wr(self.recorder.sink.payload.hit, 1)
|
||||||
|
triggered = False
|
||||||
|
else:
|
||||||
|
s.wr(self.recorder.sink.payload.hit, 0)
|
||||||
|
|
||||||
|
# Simulation
|
||||||
|
def end_simulation(self, s):
|
||||||
|
s.interrupt = self.master.done
|
||||||
|
|
||||||
|
|
||||||
|
def do_simulation(self, s):
|
||||||
|
self.recorder_data(s)
|
||||||
|
self.end_simulation(s)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tb = TB(first_run=True)
|
||||||
|
csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray)
|
||||||
|
write_to_file("csr_header.py", csr_py_header)
|
||||||
|
|
||||||
|
tb = TB()
|
||||||
|
sim = Simulator(tb, TopLevel("tb_recorder_csr.vcd"))
|
||||||
|
sim.run(2000)
|
||||||
|
print("Sim Done")
|
||||||
|
input()
|
||||||
|
|
||||||
|
main()
|
|
@ -1,168 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl import verilog, autofragment
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.sim.generic import Simulator, PureSimulable, TopLevel
|
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
|
||||||
from migen.bank import description, csrgen
|
|
||||||
from migen.bank.description import *
|
|
||||||
|
|
||||||
import miscope.bridges.spi2csr
|
|
||||||
|
|
||||||
def get_bit(dat, bit):
|
|
||||||
return int(dat & (1<<bit) != 0)
|
|
||||||
|
|
||||||
def set_bit(dat, bit):
|
|
||||||
return dat | (1<<bit)
|
|
||||||
|
|
||||||
def spi_transactions():
|
|
||||||
yield TWrite(0x0000, 0x5A)
|
|
||||||
yield TWrite(0x0001, 0xA5)
|
|
||||||
yield TWrite(0x0002, 0x5A)
|
|
||||||
yield TWrite(0x0003, 0xA5)
|
|
||||||
|
|
||||||
for i in range(10):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
yield TRead(0x0000)
|
|
||||||
yield TRead(0x0001)
|
|
||||||
yield TRead(0x0002)
|
|
||||||
yield TRead(0x0003)
|
|
||||||
|
|
||||||
for i in range(100):
|
|
||||||
yield None
|
|
||||||
|
|
||||||
class SpiMaster(PureSimulable):
|
|
||||||
def __init__(self, spi, clk_ratio, generator):
|
|
||||||
self.spi = spi
|
|
||||||
self.clk_ratio = clk_ratio
|
|
||||||
self.generator = generator
|
|
||||||
self.transaction_start = 0
|
|
||||||
self.transaction = None
|
|
||||||
self.done = False
|
|
||||||
self.r_dat = 0
|
|
||||||
|
|
||||||
def do_simulation(self, s):
|
|
||||||
a_w = self.spi.a_width
|
|
||||||
d_w = self.spi.d_width
|
|
||||||
|
|
||||||
if not self.done:
|
|
||||||
if self.transaction is None:
|
|
||||||
try:
|
|
||||||
self.transaction = next(self.generator)
|
|
||||||
except StopIteration:
|
|
||||||
self.done = True
|
|
||||||
self.transaction = None
|
|
||||||
if self.transaction is not None:
|
|
||||||
self.transaction_cnt = 0
|
|
||||||
self.r_dat = 0
|
|
||||||
print(self.transaction)
|
|
||||||
elif isinstance(self.transaction, TWrite):
|
|
||||||
|
|
||||||
# Clk
|
|
||||||
if (int(self.transaction_cnt/(self.clk_ratio/2)))%2:
|
|
||||||
s.wr(self.spi.spi_clk, 1)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_clk, 0)
|
|
||||||
|
|
||||||
# Mosi Addr
|
|
||||||
if self.transaction_cnt < a_w*self.clk_ratio:
|
|
||||||
bit = a_w-1-int((self.transaction_cnt)/self.clk_ratio)
|
|
||||||
if int(self.transaction_cnt/self.clk_ratio) == 0:
|
|
||||||
data = 1
|
|
||||||
else:
|
|
||||||
data = get_bit(self.transaction.address, bit)
|
|
||||||
s.wr(self.spi.spi_mosi, data)
|
|
||||||
# Mosi Data
|
|
||||||
elif self.transaction_cnt >= a_w*self.clk_ratio and self.transaction_cnt < (a_w + d_w)*self.clk_ratio:
|
|
||||||
bit = d_w-1-int((self.transaction_cnt-a_w*self.clk_ratio)/self.clk_ratio)
|
|
||||||
data = get_bit(self.transaction.data,bit)
|
|
||||||
s.wr(self.spi.spi_mosi, data)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_mosi, 0)
|
|
||||||
|
|
||||||
# Cs_n
|
|
||||||
if self.transaction_cnt < (a_w + d_w)*self.clk_ratio:
|
|
||||||
s.wr(self.spi.spi_cs_n,0)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_cs_n, 1)
|
|
||||||
s.wr(self.spi.spi_clk, 0)
|
|
||||||
s.wr(self.spi.spi_mosi, 0)
|
|
||||||
self.transaction = None
|
|
||||||
|
|
||||||
# Incr transaction_cnt
|
|
||||||
self.transaction_cnt +=1
|
|
||||||
|
|
||||||
elif isinstance(self.transaction, TRead):
|
|
||||||
|
|
||||||
# Clk
|
|
||||||
if (int(self.transaction_cnt/(self.clk_ratio/2)))%2:
|
|
||||||
s.wr(self.spi.spi_clk, 1)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_clk, 0)
|
|
||||||
|
|
||||||
# Mosi Addr
|
|
||||||
if self.transaction_cnt < a_w*self.clk_ratio:
|
|
||||||
bit = a_w-1-int((self.transaction_cnt)/self.clk_ratio)
|
|
||||||
if int(self.transaction_cnt/self.clk_ratio) == 0:
|
|
||||||
data = 0
|
|
||||||
else:
|
|
||||||
data = get_bit(self.transaction.address, bit)
|
|
||||||
s.wr(self.spi.spi_mosi, data)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_mosi, 0)
|
|
||||||
|
|
||||||
# Miso Data
|
|
||||||
if self.transaction_cnt >= a_w*self.clk_ratio and self.transaction_cnt%self.clk_ratio==self.clk_ratio/2:
|
|
||||||
bit = d_w-1-int((self.transaction_cnt-a_w*self.clk_ratio)/self.clk_ratio)
|
|
||||||
if s.rd(self.spi.spi_miso):
|
|
||||||
self.r_dat = set_bit(self.r_dat, bit)
|
|
||||||
|
|
||||||
# Cs_n
|
|
||||||
if self.transaction_cnt < (a_w + d_w)*self.clk_ratio:
|
|
||||||
s.wr(self.spi.spi_cs_n,0)
|
|
||||||
else:
|
|
||||||
s.wr(self.spi.spi_cs_n, 1)
|
|
||||||
s.wr(self.spi.spi_clk, 0)
|
|
||||||
s.wr(self.spi.spi_mosi, 0)
|
|
||||||
self.transaction = None
|
|
||||||
print("%02X" %self.r_dat)
|
|
||||||
|
|
||||||
# Incr transaction_cnt
|
|
||||||
self.transaction_cnt +=1
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Csr Slave
|
|
||||||
scratch_reg0 = RegisterField("scratch_reg0", 32, reset=0, access_dev=READ_ONLY)
|
|
||||||
scratch_reg1 = RegisterField("scratch_reg1", 32, reset=0, access_dev=READ_ONLY)
|
|
||||||
scratch_reg2 = RegisterField("scratch_reg3", 32, reset=0, access_dev=READ_ONLY)
|
|
||||||
scratch_reg3 = RegisterField("scratch_reg4", 32, reset=0, access_dev=READ_ONLY)
|
|
||||||
regs = [scratch_reg0, scratch_reg1, scratch_reg2, scratch_reg3]
|
|
||||||
bank0 = csrgen.Bank(regs,address=0x0000)
|
|
||||||
|
|
||||||
# Spi2Csr
|
|
||||||
spi2csr0 = spi2csr.Spi2Csr(16,8)
|
|
||||||
|
|
||||||
|
|
||||||
# Csr Interconnect
|
|
||||||
csrcon0 = csr.Interconnect(spi2csr0.csr,
|
|
||||||
[
|
|
||||||
bank0.interface
|
|
||||||
])
|
|
||||||
|
|
||||||
# Spi Master
|
|
||||||
spi_master0 = SpiMaster(spi2csr0, 8, spi_transactions())
|
|
||||||
|
|
||||||
# Simulation
|
|
||||||
def end_simulation(s):
|
|
||||||
s.interrupt = spi_master0.done
|
|
||||||
|
|
||||||
|
|
||||||
fragment = autofragment.from_local()
|
|
||||||
fragment += Fragment(sim=[end_simulation])
|
|
||||||
sim = Simulator(fragment, Runner(),TopLevel("tb_spi2Csr.vcd"))
|
|
||||||
sim.run(10000)
|
|
||||||
|
|
||||||
main()
|
|
||||||
input()
|
|
109
sim/tb_trigger_csr.py
Normal file
109
sim/tb_trigger_csr.py
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
from migen.fhdl.std import *
|
||||||
|
from migen.fhdl import verilog
|
||||||
|
from migen.bus import csr
|
||||||
|
from migen.sim.generic import Simulator, TopLevel
|
||||||
|
from migen.sim.icarus import Runner
|
||||||
|
from migen.bus.transactions import *
|
||||||
|
|
||||||
|
from miscope.triggering import *
|
||||||
|
from miscope.std.truthtable import *
|
||||||
|
|
||||||
|
from miscope.std import cif
|
||||||
|
|
||||||
|
from mibuild.tools import write_to_file
|
||||||
|
|
||||||
|
try:
|
||||||
|
from csr_header import *
|
||||||
|
print("csr_header imported")
|
||||||
|
except:
|
||||||
|
print("csr_header not found")
|
||||||
|
|
||||||
|
class Csr2Trans():
|
||||||
|
def __init__(self):
|
||||||
|
self.t = []
|
||||||
|
|
||||||
|
def write_csr(self, adr, value):
|
||||||
|
self.t.append(TWrite(adr//4, value))
|
||||||
|
|
||||||
|
def read_csr(self, adr):
|
||||||
|
self.t.append(TRead(adr//4))
|
||||||
|
|
||||||
|
def csr_prog_mila():
|
||||||
|
bus = Csr2Trans()
|
||||||
|
trigger_port0_mask_write(bus, 0xFFFFFFFF)
|
||||||
|
trigger_port0_trig_write(bus, 0xDEADBEEF)
|
||||||
|
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
||||||
|
trigger_port1_trig_write(bus, 0xDEADBEEF)
|
||||||
|
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
||||||
|
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
||||||
|
trigger_port1_trig_write(bus, 0xDEADBEEF)
|
||||||
|
|
||||||
|
sum_tt = gen_truth_table("i1 & i2 & i3 & i4")
|
||||||
|
sum_trans = []
|
||||||
|
for i in range(len(sum_tt)):
|
||||||
|
trigger_sum_prog_adr_write(bus, i)
|
||||||
|
trigger_sum_prog_dat_write(bus, sum_tt[i])
|
||||||
|
trigger_sum_prog_we_write(bus, 1)
|
||||||
|
|
||||||
|
return bus.t
|
||||||
|
|
||||||
|
|
||||||
|
csr_done = False
|
||||||
|
|
||||||
|
def csr_transactions():
|
||||||
|
for t in csr_prog_mila():
|
||||||
|
yield t
|
||||||
|
global csr_done
|
||||||
|
csr_done = True
|
||||||
|
for t in range(100):
|
||||||
|
yield None
|
||||||
|
|
||||||
|
class TB(Module):
|
||||||
|
csr_base = 0
|
||||||
|
csr_map = {
|
||||||
|
"trigger": 1,
|
||||||
|
}
|
||||||
|
def __init__(self, first_run=False):
|
||||||
|
|
||||||
|
|
||||||
|
# Csr Master
|
||||||
|
if not first_run:
|
||||||
|
self.submodules.master = csr.Initiator(csr_transactions())
|
||||||
|
|
||||||
|
# Trigger
|
||||||
|
term0 = Term(32)
|
||||||
|
term1 = Term(32)
|
||||||
|
term2 = Term(32)
|
||||||
|
term3 = Term(32)
|
||||||
|
self.submodules.trigger = Trigger(32, [term0, term1, term2, term3])
|
||||||
|
|
||||||
|
# Csr
|
||||||
|
self.submodules.csrbankarray = csrgen.BankArray(self,
|
||||||
|
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
||||||
|
if not first_run:
|
||||||
|
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
||||||
|
|
||||||
|
self.terms = [term0, term1, term2, term3]
|
||||||
|
|
||||||
|
def do_simulation(self, s):
|
||||||
|
for term in self.terms:
|
||||||
|
s.wr(term.sink.stb, 1)
|
||||||
|
if csr_done:
|
||||||
|
s.wr(self.terms[0].sink.payload.d, 0xDEADBEEF)
|
||||||
|
s.wr(self.terms[1].sink.payload.d ,0xCAFEFADE)
|
||||||
|
s.wr(self.terms[2].sink.payload.d, 0xDEADBEEF)
|
||||||
|
s.wr(self.terms[3].sink.payload.d, 0xCAFEFADE)
|
||||||
|
s.interrupt = self.master.done
|
||||||
|
|
||||||
|
def main():
|
||||||
|
tb = TB(first_run=True)
|
||||||
|
csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray)
|
||||||
|
write_to_file("csr_header.py", csr_py_header)
|
||||||
|
|
||||||
|
tb = TB()
|
||||||
|
sim = Simulator(tb, TopLevel("tb_trigger_csr.vcd"))
|
||||||
|
sim.run(2000)
|
||||||
|
print("Sim Done")
|
||||||
|
input()
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in a new issue