mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
refactor code
This commit is contained in:
parent
b766af0d99
commit
7a489b3135
32 changed files with 601 additions and 1158 deletions
|
@ -1,12 +0,0 @@
|
||||||
all: build/soc-de0nano.sta
|
|
||||||
|
|
||||||
build/soc-de0nano.sta:
|
|
||||||
./make.py
|
|
||||||
|
|
||||||
load:
|
|
||||||
cd build && quartus_pgm -m jtag -c USB-Blaster[USB-0] -o "p;soc-de0nano.sof"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf build/*
|
|
||||||
|
|
||||||
.PHONY: load clean
|
|
|
@ -1,57 +0,0 @@
|
||||||
from miscope import miio
|
|
||||||
from miscope.com.uart2csr.host.uart2csr import *
|
|
||||||
|
|
||||||
from csr import *
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# P A R A M E T E R S
|
|
||||||
#==============================================================================
|
|
||||||
|
|
||||||
uart = Uart2Csr(3, 115200)
|
|
||||||
|
|
||||||
class MiIoCtrl():
|
|
||||||
def __init__(self, bus):
|
|
||||||
self.bus = bus
|
|
||||||
|
|
||||||
def write(self, value):
|
|
||||||
miio_o_write(self.bus, value)
|
|
||||||
|
|
||||||
def read(self):
|
|
||||||
return miio_i_read(self.bus)
|
|
||||||
|
|
||||||
miio = MiIoCtrl(uart)
|
|
||||||
|
|
||||||
def led_anim0():
|
|
||||||
for i in range(10):
|
|
||||||
miio.write(0xA5)
|
|
||||||
time.sleep(0.1)
|
|
||||||
miio.write(0x5A)
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
def led_anim1():
|
|
||||||
for j in range(4):
|
|
||||||
#Led <<
|
|
||||||
ledData = 1
|
|
||||||
for i in range(8):
|
|
||||||
miio.write(ledData)
|
|
||||||
time.sleep(i*i*0.0020)
|
|
||||||
ledData = (ledData<<1)
|
|
||||||
#Led >>
|
|
||||||
ledData = 128
|
|
||||||
for i in range(8):
|
|
||||||
miio.write(ledData)
|
|
||||||
time.sleep(i*i*0.0020)
|
|
||||||
ledData = (ledData>>1)
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# T E S T M I I O
|
|
||||||
#==============================================================================
|
|
||||||
|
|
||||||
print("- Led Animation...")
|
|
||||||
led_anim0()
|
|
||||||
time.sleep(1)
|
|
||||||
led_anim1()
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
print("- Read Switch: ",end=' ')
|
|
||||||
print("%02X" %miio.read())
|
|
|
@ -1,99 +0,0 @@
|
||||||
from miscope import mila
|
|
||||||
from miscope.std.truthtable import *
|
|
||||||
from miscope.std.vcd import *
|
|
||||||
from miscope.com.uart2csr.host.uart2csr import *
|
|
||||||
from csr import *
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# P A R A M E T E R S
|
|
||||||
#==============================================================================
|
|
||||||
|
|
||||||
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 enable_rle(self):
|
|
||||||
mila_rle_enable_write(self.bus, 1)
|
|
||||||
|
|
||||||
def disable_rle(self):
|
|
||||||
mila_rle_enable_write(self.bus, 0)
|
|
||||||
|
|
||||||
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
|
|
||||||
trig_w = 16
|
|
||||||
dat_w = 16
|
|
||||||
rec_length = 512
|
|
||||||
rec_offset = 0
|
|
||||||
rle = True
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# T E S T M I L A
|
|
||||||
#==============================================================================
|
|
||||||
dat_vcd = VcdDat(dat_w)
|
|
||||||
|
|
||||||
mila = MiLaCtrl(uart)
|
|
||||||
|
|
||||||
def capture():
|
|
||||||
global dat_vcd
|
|
||||||
sum_tt = gen_truth_table("term")
|
|
||||||
mila.prog_sum(sum_tt)
|
|
||||||
mila.trigger(rec_offset, rec_length)
|
|
||||||
print("-Recorder [Triggered]")
|
|
||||||
print("-Waiting Trigger...", end=' ')
|
|
||||||
while(not mila.is_done()):
|
|
||||||
time.sleep(0.1)
|
|
||||||
print("[Done]")
|
|
||||||
|
|
||||||
print("-Receiving Data...", end=' ')
|
|
||||||
sys.stdout.flush()
|
|
||||||
dat_vcd += mila.read()
|
|
||||||
print("[Done]")
|
|
||||||
|
|
||||||
print("Capturing ...")
|
|
||||||
print("----------------------")
|
|
||||||
if rle:
|
|
||||||
mila.enable_rle()
|
|
||||||
mila.prog_term(0x0000, 0xFFFF)
|
|
||||||
capture()
|
|
||||||
|
|
||||||
mila_layout = [
|
|
||||||
("freqgen", 1),
|
|
||||||
("event_rising", 1),
|
|
||||||
("event_falling", 1),
|
|
||||||
("cnt", 8),
|
|
||||||
]
|
|
||||||
|
|
||||||
if rle:
|
|
||||||
dat_vcd = dat_vcd.decode_rle()
|
|
||||||
|
|
||||||
myvcd = Vcd()
|
|
||||||
myvcd.add_from_layout(mila_layout, dat_vcd)
|
|
||||||
myvcd.write("test_mila.vcd")
|
|
|
@ -1,42 +0,0 @@
|
||||||
#!/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()
|
|
|
@ -1,29 +0,0 @@
|
||||||
from math import ceil
|
|
||||||
|
|
||||||
Hz = 1
|
|
||||||
KHz = 10**3
|
|
||||||
MHz = 10**6
|
|
||||||
GHz = 10**9
|
|
||||||
|
|
||||||
s = 1
|
|
||||||
ms = 1/KHz
|
|
||||||
us = 1/MHz
|
|
||||||
ns = 1/GHz
|
|
||||||
|
|
||||||
class t2n:
|
|
||||||
def __init__(self, clk_period_ns):
|
|
||||||
self.clk_period_ns = clk_period_ns
|
|
||||||
self.clk_period_us = clk_period_ns*(MHz/GHz)
|
|
||||||
self.clk_period_ms = clk_period_ns*(KHz/GHz)
|
|
||||||
def ns(self,t,margin=True):
|
|
||||||
if margin:
|
|
||||||
t += self.clk_period_ns/2
|
|
||||||
return ceil(t/self.clk_period_ns)
|
|
||||||
def us(self,t,margin=True):
|
|
||||||
if margin:
|
|
||||||
t += self.clk_period_us/2
|
|
||||||
return ceil(t/self.clk_period_us)
|
|
||||||
def ms(self,t,margin=True):
|
|
||||||
if margin:
|
|
||||||
t += self.clk_period_ms/2
|
|
||||||
return ceil(t/self.clk_period_ms)
|
|
|
@ -1,106 +0,0 @@
|
||||||
################################################################################
|
|
||||||
# _____ _ ____ _ _ _ _
|
|
||||||
# | __|___ |_|___ _ _ | \|_|___|_| |_ ___| |
|
|
||||||
# | __| | | | . | | | | | | | . | | _| .'| |
|
|
||||||
# |_____|_|_|_| |___|_ | |____/|_|_ |_|_| |__,|_|
|
|
||||||
# |___| |___| |___|
|
|
||||||
#
|
|
||||||
# Copyright 2013 / Florent Kermarrec / florent@enjoy-digital.fr
|
|
||||||
#
|
|
||||||
# miscope example on De0 Nano
|
|
||||||
# --------------------------------
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# I M P O R T
|
|
||||||
#==============================================================================
|
|
||||||
from migen.fhdl.std import *
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.bank import csrgen
|
|
||||||
|
|
||||||
from miscope.std.misc import *
|
|
||||||
|
|
||||||
from miscope.trigger import Term
|
|
||||||
from miscope.miio import MiIo
|
|
||||||
from miscope.mila import MiLa
|
|
||||||
|
|
||||||
from miscope.com import uart2csr
|
|
||||||
|
|
||||||
from timings import *
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# P A R A M E T E R S
|
|
||||||
#==============================================================================
|
|
||||||
|
|
||||||
# Timings Param
|
|
||||||
clk_freq = 50*MHz
|
|
||||||
|
|
||||||
# Mila Param
|
|
||||||
mila_width = 16
|
|
||||||
mila_depth = 4096
|
|
||||||
|
|
||||||
#==============================================================================
|
|
||||||
# M I S C O P E E X A M P L E
|
|
||||||
#==============================================================================
|
|
||||||
class SoC(Module):
|
|
||||||
csr_base = 0xe0000000
|
|
||||||
csr_map = {
|
|
||||||
"miio": 1,
|
|
||||||
"mila": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, platform):
|
|
||||||
# MiIo
|
|
||||||
self.submodules.miio = MiIo(8)
|
|
||||||
|
|
||||||
# MiLa
|
|
||||||
term = Term(mila_width)
|
|
||||||
self.submodules.mila = MiLa(mila_width, mila_depth, [term], rle=True)
|
|
||||||
|
|
||||||
# Uart2Csr
|
|
||||||
self.submodules.uart2csr = uart2csr.Uart2Csr(platform.request("serial"), clk_freq, 115200)
|
|
||||||
|
|
||||||
# Csr Interconnect
|
|
||||||
self.submodules.csrbankarray = csrgen.BankArray(self,
|
|
||||||
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
|
||||||
self.submodules.csrcon = csr.Interconnect(self.uart2csr.csr, self.csrbankarray.get_buses())
|
|
||||||
|
|
||||||
# Led
|
|
||||||
self.led = Cat(*[platform.request("user_led", i) for i in range(8)])
|
|
||||||
|
|
||||||
# Misc
|
|
||||||
self.cnt = Signal(16)
|
|
||||||
self.submodules.freqgen = FreqGen(clk_freq, 500*KHz)
|
|
||||||
self.submodules.eventgen_rising = EventGen(RISING_EDGE, clk_freq, 100*ns)
|
|
||||||
self.submodules.eventgen_falling = EventGen(FALLING_EDGE, clk_freq, 100*ns)
|
|
||||||
self.comb += [
|
|
||||||
self.eventgen_rising.i.eq(self.freqgen.o),
|
|
||||||
self.eventgen_falling.i.eq(self.freqgen.o)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
#
|
|
||||||
# Miio
|
|
||||||
#
|
|
||||||
|
|
||||||
# Output
|
|
||||||
self.comb += self.led.eq(self.miio.o)
|
|
||||||
|
|
||||||
# Input
|
|
||||||
self.comb += self.miio.i.eq(self.miio.o)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Mila
|
|
||||||
#
|
|
||||||
self.comb +=[
|
|
||||||
self.mila.sink.stb.eq(1),
|
|
||||||
self.mila.sink.dat.eq(Cat(
|
|
||||||
self.freqgen.o,
|
|
||||||
self.eventgen_rising.o,
|
|
||||||
self.eventgen_falling.o,
|
|
||||||
self.cnt[8:12])
|
|
||||||
)
|
|
||||||
]
|
|
||||||
self.sync += self.cnt.eq(self.cnt+1)
|
|
|
@ -1,180 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.module import *
|
|
||||||
from migen.bus import csr
|
|
||||||
from migen.genlib.fsm import FSM, NextState
|
|
||||||
|
|
||||||
from miscope.com.uart2csr.uart import *
|
|
||||||
|
|
||||||
WRITE_CMD = 0x01
|
|
||||||
READ_CMD = 0x02
|
|
||||||
CLOSE_CMD = 0x03
|
|
||||||
|
|
||||||
class Uart2Csr(Module):
|
|
||||||
def __init__(self, pads, clk_freq, baud):
|
|
||||||
|
|
||||||
# Csr interface
|
|
||||||
self.csr = csr.Interface()
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
self.submodules.uart = UART(clk_freq, baud)
|
|
||||||
uart = self.uart
|
|
||||||
|
|
||||||
#
|
|
||||||
# In/Out
|
|
||||||
#
|
|
||||||
self.comb +=[
|
|
||||||
uart.rx.eq(pads.rx),
|
|
||||||
pads.tx.eq(uart.tx)
|
|
||||||
]
|
|
||||||
|
|
||||||
cmd = Signal(8)
|
|
||||||
cnt = Signal(3)
|
|
||||||
sr = Signal(32)
|
|
||||||
burst_cnt = Signal(8)
|
|
||||||
addr = Signal(32)
|
|
||||||
data = Signal(8)
|
|
||||||
|
|
||||||
# FSM
|
|
||||||
self.submodules.fsm = FSM(reset_state="IDLE")
|
|
||||||
|
|
||||||
fsm = self.fsm
|
|
||||||
|
|
||||||
#
|
|
||||||
# Global
|
|
||||||
#
|
|
||||||
self.sync +=[
|
|
||||||
If(fsm.ongoing("IDLE"), cnt.eq(0)
|
|
||||||
).Elif(uart.rx_ev, cnt.eq(cnt + 1)),
|
|
||||||
|
|
||||||
If(uart.rx_ev, sr.eq(Cat(uart.rx_dat, sr[0:24])))
|
|
||||||
]
|
|
||||||
|
|
||||||
# State done signals
|
|
||||||
get_bl_done = Signal()
|
|
||||||
get_addr_done = Signal()
|
|
||||||
get_addr_done_d = Signal()
|
|
||||||
get_data_done = Signal()
|
|
||||||
send_data_done = Signal()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Idle
|
|
||||||
#
|
|
||||||
fsm.act("IDLE",
|
|
||||||
If(uart.rx_ev & ((uart.rx_dat == WRITE_CMD) | (uart.rx_dat == READ_CMD)),
|
|
||||||
NextState("GET_BL")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.sync += If(fsm.ongoing("IDLE") & uart.rx_ev, cmd.eq(uart.rx_dat))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Get burst length
|
|
||||||
#
|
|
||||||
fsm.act("GET_BL",
|
|
||||||
If(get_bl_done,
|
|
||||||
NextState("GET_ADDR")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Get address
|
|
||||||
#
|
|
||||||
fsm.act("GET_ADDR",
|
|
||||||
If(get_addr_done & (cmd == WRITE_CMD),
|
|
||||||
NextState("GET_DATA")
|
|
||||||
).Elif(get_addr_done & (cmd == READ_CMD),
|
|
||||||
NextState("READ_CSR0")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
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 += [
|
|
||||||
If(get_addr_done_d,
|
|
||||||
addr.eq(sr)
|
|
||||||
).Elif(fsm.leaving("WRITE_CSR") | send_data_done,
|
|
||||||
addr.eq(addr + 1)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Get data
|
|
||||||
#
|
|
||||||
fsm.act("GET_DATA",
|
|
||||||
If(get_data_done,
|
|
||||||
NextState("WRITE_CSR")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.comb += get_data_done.eq(uart.rx_ev & fsm.ongoing("GET_DATA"))
|
|
||||||
self.sync += [
|
|
||||||
If(get_data_done,
|
|
||||||
burst_cnt.eq(burst_cnt-1),
|
|
||||||
data.eq(uart.rx_dat)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#
|
|
||||||
# Write Csr
|
|
||||||
#
|
|
||||||
fsm.act("WRITE_CSR",
|
|
||||||
If((burst_cnt==0),
|
|
||||||
NextState("IDLE")
|
|
||||||
).Else(NextState("GET_DATA"))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Read Csr0
|
|
||||||
#
|
|
||||||
fsm.act("READ_CSR0",
|
|
||||||
NextState("READ_CSR1")
|
|
||||||
)
|
|
||||||
|
|
||||||
self.sync += If(fsm.entering("READ_CSR0"), burst_cnt.eq(burst_cnt-1))
|
|
||||||
|
|
||||||
#
|
|
||||||
# Read Csr1
|
|
||||||
#
|
|
||||||
fsm.act("READ_CSR1",
|
|
||||||
NextState("SEND_DATA")
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Send Data
|
|
||||||
#
|
|
||||||
fsm.act("SEND_DATA",
|
|
||||||
If(send_data_done & (burst_cnt==0),
|
|
||||||
NextState("IDLE")
|
|
||||||
).Elif(send_data_done,
|
|
||||||
NextState("READ_CSR0")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
self.comb += send_data_done.eq(fsm.ongoing("SEND_DATA") & uart.tx_ev)
|
|
||||||
|
|
||||||
self.sync += [
|
|
||||||
uart.tx_dat.eq(self.csr.dat_r),
|
|
||||||
uart.tx_we.eq(fsm.entering("SEND_DATA")),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Csr access
|
|
||||||
#
|
|
||||||
self.comb += self.csr.adr.eq(addr)
|
|
||||||
self.sync +=[
|
|
||||||
self.csr.dat_w.eq(data),
|
|
||||||
If(fsm.ongoing("WRITE_CSR"),
|
|
||||||
self.csr.we.eq(1)
|
|
||||||
).Else(
|
|
||||||
self.csr.we.eq(0)
|
|
||||||
)
|
|
||||||
]
|
|
|
@ -1,91 +0,0 @@
|
||||||
import string
|
|
||||||
import time
|
|
||||||
import serial
|
|
||||||
from struct import *
|
|
||||||
import time
|
|
||||||
from migen.fhdl.structure import *
|
|
||||||
|
|
||||||
WRITE_CMD = 0x01
|
|
||||||
READ_CMD = 0x02
|
|
||||||
CLOSE_CMD = 0x03
|
|
||||||
|
|
||||||
def write_b(uart, data):
|
|
||||||
uart.write(pack('B',data))
|
|
||||||
|
|
||||||
class Uart2Csr:
|
|
||||||
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 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, burst_length)
|
|
||||||
addr = addr//4
|
|
||||||
write_b(self.uart, (addr & 0xff000000) >> 24)
|
|
||||||
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
|
||||||
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
|
||||||
write_b(self.uart, (addr & 0x000000ff))
|
|
||||||
values = []
|
|
||||||
for i in range(burst_length):
|
|
||||||
read = self.uart.read(1)
|
|
||||||
val = int(read[0])
|
|
||||||
if self.debug:
|
|
||||||
print("RD %02X @ %08X" %(val, addr + 4*i))
|
|
||||||
values.append(val)
|
|
||||||
if burst_length == 1:
|
|
||||||
return values[0]
|
|
||||||
else:
|
|
||||||
return values
|
|
||||||
|
|
||||||
def read_n(self, addr, n, endianess = "LE"):
|
|
||||||
r = 0
|
|
||||||
words = int(2**bits_for(n-1)/8)
|
|
||||||
for i in range(words):
|
|
||||||
if endianess == "BE":
|
|
||||||
r += self.read(addr+i)<<(8*i)
|
|
||||||
elif endianess == "LE":
|
|
||||||
r += self.read(addr+words-1-i)<<(8*i)
|
|
||||||
if self.debug:
|
|
||||||
print("RD @ %04X" %addr)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def write_csr(self, addr, data):
|
|
||||||
if isinstance(data, list):
|
|
||||||
burst_length = len(data)
|
|
||||||
else:
|
|
||||||
burst_length = 1
|
|
||||||
write_b(self.uart, WRITE_CMD)
|
|
||||||
write_b(self.uart, burst_length)
|
|
||||||
addr = addr//4
|
|
||||||
self.uart.write([(addr & 0xff000000) >> 24,
|
|
||||||
(addr & 0x00ff0000) >> 16,
|
|
||||||
(addr & 0x0000ff00) >> 8,
|
|
||||||
(addr & 0x000000ff)])
|
|
||||||
if isinstance(data, list):
|
|
||||||
for i in range(len(data)):
|
|
||||||
write_b(self.uart, data[i])
|
|
||||||
if self.debug:
|
|
||||||
print("WR %02X @ %08X" %(data[i], addr + 4*i))
|
|
||||||
else:
|
|
||||||
write_b(self.uart, data)
|
|
||||||
if self.debug:
|
|
||||||
print("WR %02X @ %08X" %(data, addr))
|
|
||||||
|
|
||||||
def write_n(self, addr, data, n, endianess = "LE"):
|
|
||||||
words = int(2**bits_for(n-1)/8)
|
|
||||||
for i in range(words):
|
|
||||||
if endianess == "BE":
|
|
||||||
self.write(addr+i, (data>>(8*i)) & 0xFF)
|
|
||||||
elif endianess == "LE":
|
|
||||||
self.write(addr+words-1-i, (data>>(8*i)) & 0xFF)
|
|
||||||
if self.debug:
|
|
||||||
print("WR %08X @ %04X" %(data, addr))
|
|
|
@ -1,107 +0,0 @@
|
||||||
from migen.fhdl.structure import *
|
|
||||||
from migen.fhdl.module import Module
|
|
||||||
from migen.genlib.cdc import MultiReg
|
|
||||||
from migen.bank.description import *
|
|
||||||
from migen.bank.eventmanager import *
|
|
||||||
|
|
||||||
class UART(Module):
|
|
||||||
def __init__(self, clk_freq, baud=115200):
|
|
||||||
|
|
||||||
self.rx_ev = Signal()
|
|
||||||
self.rx_dat = Signal(8)
|
|
||||||
|
|
||||||
self.tx_we = Signal()
|
|
||||||
self.tx_ev = Signal()
|
|
||||||
self.tx_dat = Signal(8)
|
|
||||||
|
|
||||||
self.divisor = Signal(16, reset=int(clk_freq/baud/16))
|
|
||||||
|
|
||||||
self.tx = Signal(reset=1)
|
|
||||||
self.rx = Signal()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
enable16 = Signal()
|
|
||||||
enable16_counter = Signal(16)
|
|
||||||
self.comb += enable16.eq(enable16_counter == 0)
|
|
||||||
self.sync += [
|
|
||||||
enable16_counter.eq(enable16_counter - 1),
|
|
||||||
If(enable16,
|
|
||||||
enable16_counter.eq(self.divisor - 1))
|
|
||||||
]
|
|
||||||
|
|
||||||
# TX
|
|
||||||
tx_reg = Signal(8)
|
|
||||||
tx_bitcount = Signal(4)
|
|
||||||
tx_count16 = Signal(4)
|
|
||||||
tx_done = self.tx_ev
|
|
||||||
tx_busy = Signal()
|
|
||||||
self.sync += [
|
|
||||||
tx_done.eq(0),
|
|
||||||
If(self.tx_we,
|
|
||||||
tx_reg.eq(self.tx_dat),
|
|
||||||
tx_bitcount.eq(0),
|
|
||||||
tx_count16.eq(1),
|
|
||||||
tx_busy.eq(1),
|
|
||||||
self.tx.eq(0)
|
|
||||||
).Elif(enable16 & tx_busy,
|
|
||||||
tx_count16.eq(tx_count16 + 1),
|
|
||||||
If(tx_count16 == 0,
|
|
||||||
tx_bitcount.eq(tx_bitcount + 1),
|
|
||||||
If(tx_bitcount == 8,
|
|
||||||
self.tx.eq(1)
|
|
||||||
).Elif(tx_bitcount == 9,
|
|
||||||
self.tx.eq(1),
|
|
||||||
tx_busy.eq(0),
|
|
||||||
tx_done.eq(1)
|
|
||||||
).Else(
|
|
||||||
self.tx.eq(tx_reg[0]),
|
|
||||||
tx_reg.eq(Cat(tx_reg[1:], 0))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
# RX
|
|
||||||
rx = Signal()
|
|
||||||
self.specials += MultiReg(self.rx, rx, "sys")
|
|
||||||
rx_r = Signal()
|
|
||||||
rx_reg = Signal(8)
|
|
||||||
rx_bitcount = Signal(4)
|
|
||||||
rx_count16 = Signal(4)
|
|
||||||
rx_busy = Signal()
|
|
||||||
rx_done = self.rx_ev
|
|
||||||
rx_data = self.rx_dat
|
|
||||||
self.sync += [
|
|
||||||
rx_done.eq(0),
|
|
||||||
If(enable16,
|
|
||||||
rx_r.eq(rx),
|
|
||||||
If(~rx_busy,
|
|
||||||
If(~rx & rx_r, # look for start bit
|
|
||||||
rx_busy.eq(1),
|
|
||||||
rx_count16.eq(7),
|
|
||||||
rx_bitcount.eq(0)
|
|
||||||
)
|
|
||||||
).Else(
|
|
||||||
rx_count16.eq(rx_count16 + 1),
|
|
||||||
If(rx_count16 == 0,
|
|
||||||
rx_bitcount.eq(rx_bitcount + 1),
|
|
||||||
|
|
||||||
If(rx_bitcount == 0,
|
|
||||||
If(rx, # verify start bit
|
|
||||||
rx_busy.eq(0)
|
|
||||||
)
|
|
||||||
).Elif(rx_bitcount == 9,
|
|
||||||
rx_busy.eq(0),
|
|
||||||
If(rx, # verify stop bit
|
|
||||||
rx_data.eq(rx_reg),
|
|
||||||
rx_done.eq(1)
|
|
||||||
)
|
|
||||||
).Else(
|
|
||||||
rx_reg.eq(Cat(rx_reg[1:], rx))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
|
@ -1,89 +0,0 @@
|
||||||
import string
|
|
||||||
import time
|
|
||||||
import serial
|
|
||||||
from struct import *
|
|
||||||
import time
|
|
||||||
|
|
||||||
WRITE_CMD = 0x01
|
|
||||||
READ_CMD = 0x02
|
|
||||||
CLOSE_CMD = 0x03
|
|
||||||
|
|
||||||
def write_b(uart, data):
|
|
||||||
uart.write(pack('B',data))
|
|
||||||
|
|
||||||
class Uart2Wb:
|
|
||||||
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 open(self):
|
|
||||||
self.uart.write("\nuart2wb\n".encode('ascii'))
|
|
||||||
self.uart.flush()
|
|
||||||
time.sleep(0.1)
|
|
||||||
self.uart.close()
|
|
||||||
self.uart.open()
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
for i in range(16):
|
|
||||||
write_b(self.uart, CLOSE_CMD)
|
|
||||||
self.uart.close()
|
|
||||||
|
|
||||||
def read(self, addr, burst_length=1):
|
|
||||||
write_b(self.uart, READ_CMD)
|
|
||||||
write_b(self.uart, burst_length)
|
|
||||||
write_b(self.uart, (addr & 0xff000000) >> 24)
|
|
||||||
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
|
||||||
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
|
||||||
write_b(self.uart, (addr & 0x000000ff))
|
|
||||||
values = []
|
|
||||||
for i in range(burst_length):
|
|
||||||
read = self.uart.read(4)
|
|
||||||
val = (int(read[0]) << 24) | (int(read[1]) << 16) | (int(read[2]) << 8) | int(read[3])
|
|
||||||
if self.debug:
|
|
||||||
print("RD %08X @ %08X" %(val, addr + 4*i))
|
|
||||||
values.append(val)
|
|
||||||
if burst_length == 1:
|
|
||||||
return values[0]
|
|
||||||
else:
|
|
||||||
return values
|
|
||||||
|
|
||||||
def read_csr(self, addr, burst_length=1):
|
|
||||||
values = self.read(addr, burst_length)
|
|
||||||
if isinstance(values, list):
|
|
||||||
for i in range(len(values)):
|
|
||||||
values[i] = values[i]&0xff
|
|
||||||
else:
|
|
||||||
values = values & 0xff
|
|
||||||
return values
|
|
||||||
|
|
||||||
def write(self, addr, data):
|
|
||||||
if isinstance(data, list):
|
|
||||||
burst_length = len(data)
|
|
||||||
else:
|
|
||||||
burst_length = 1
|
|
||||||
write_b(self.uart, WRITE_CMD)
|
|
||||||
write_b(self.uart, burst_length)
|
|
||||||
self.uart.write([(addr & 0xff000000) >> 24,
|
|
||||||
(addr & 0x00ff0000) >> 16,
|
|
||||||
(addr & 0x0000ff00) >> 8,
|
|
||||||
(addr & 0x000000ff)])
|
|
||||||
if isinstance(data, list):
|
|
||||||
for i in range(len(data)):
|
|
||||||
self.uart.write([(data[i] & 0xff000000) >> 24,
|
|
||||||
(data[i] & 0x00ff0000) >> 16,
|
|
||||||
(data[i] & 0x0000ff00) >> 8,
|
|
||||||
(data[i] & 0x000000ff)])
|
|
||||||
if self.debug:
|
|
||||||
print("WR %08X @ %08X" %(elt, addr + 4*i))
|
|
||||||
else:
|
|
||||||
self.uart.write([(data & 0xff000000) >> 24,
|
|
||||||
(data & 0x00ff0000) >> 16,
|
|
||||||
(data & 0x0000ff00) >> 8,
|
|
||||||
(data & 0x000000ff)])
|
|
||||||
if self.debug:
|
|
||||||
print("WR %08X @ %08X" %(data, addr))
|
|
||||||
|
|
||||||
def write_csr(self, addr, data):
|
|
||||||
self.write(addr, data)
|
|
|
@ -1,53 +0,0 @@
|
||||||
// Use this code in your LM32 code to control CSR
|
|
||||||
// over uart
|
|
||||||
|
|
||||||
#define WRITE_CMD 0x01
|
|
||||||
#define READ_CMD 0x02
|
|
||||||
#define CLOSE_CMD 0x03
|
|
||||||
#define MMPTR(x) (*((volatile unsigned int *)(x)))
|
|
||||||
|
|
||||||
static void uart2wb(void)
|
|
||||||
{
|
|
||||||
unsigned char cmd;
|
|
||||||
unsigned char burst_length;
|
|
||||||
unsigned char adr_t[4];
|
|
||||||
unsigned int adr;
|
|
||||||
char data_t[4];
|
|
||||||
unsigned int data;
|
|
||||||
unsigned char i;
|
|
||||||
unsigned char j;
|
|
||||||
|
|
||||||
while(cmd != CLOSE_CMD)
|
|
||||||
{
|
|
||||||
cmd = readchar();
|
|
||||||
|
|
||||||
if (cmd == WRITE_CMD)
|
|
||||||
{
|
|
||||||
burst_length = readchar();
|
|
||||||
for(i=0;i<4;i++) adr_t[i] = readchar();
|
|
||||||
adr = adr_t[0]<<24 | adr_t[1]<<16 | adr_t[2]<<8 | adr_t[3];
|
|
||||||
for(i=0;i<burst_length;i++)
|
|
||||||
{
|
|
||||||
for(j=0;j<4;j++) data_t[j] = readchar();
|
|
||||||
data = data_t[0]<<24 | data_t[1]<<16 | data_t[2]<<8 | data_t[3];
|
|
||||||
MMPTR(adr+4*i) = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd == READ_CMD)
|
|
||||||
{
|
|
||||||
burst_length = readchar();
|
|
||||||
for(i=0;i<4;i++) adr_t[i] = readchar();
|
|
||||||
adr = adr_t[0]<<24 | adr_t[1]<<16 | adr_t[2]<<8 | adr_t[3];
|
|
||||||
for(i=0;i<burst_length;i++)
|
|
||||||
{
|
|
||||||
data = MMPTR(adr+4*i);
|
|
||||||
data_t[0] = (data & 0xff000000)>>24;
|
|
||||||
data_t[1] = (data & 0x00ff0000)>>16;
|
|
||||||
data_t[2] = (data & 0x0000ff00)>>8;
|
|
||||||
data_t[3] = (data & 0x000000ff);
|
|
||||||
for(j=0;j<4;j++) putchar(data_t[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
11
miscope/host/cpuif.py
Normal file
11
miscope/host/cpuif.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from migen.bank.description import CSRStatus
|
||||||
|
|
||||||
|
def get_csr_csv(csr_base, bank_array):
|
||||||
|
r = ""
|
||||||
|
for name, csrs, mapaddr, rmap in bank_array.banks:
|
||||||
|
reg_base = csr_base + 0x800*mapaddr
|
||||||
|
for csr in csrs:
|
||||||
|
nr = (csr.size + 7)//8
|
||||||
|
r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
|
||||||
|
reg_base += 4*nr
|
||||||
|
return r
|
63
miscope/host/drivers.py
Normal file
63
miscope/host/drivers.py
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
class MiIoDriver():
|
||||||
|
def __init__(self, regs, name):
|
||||||
|
self.regs = regs
|
||||||
|
self.name = name
|
||||||
|
self.build_miio()
|
||||||
|
|
||||||
|
def build_miio(self):
|
||||||
|
for key, value in self.regs.d.items():
|
||||||
|
if self.name in key:
|
||||||
|
key.replace(self.name, "miio")
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
def write(self, value):
|
||||||
|
self.miio_o.write(value)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
return self.miio_i.read()
|
||||||
|
|
||||||
|
class MiLaDriver():
|
||||||
|
def __init__(self, regs, name):
|
||||||
|
self.regs = regs
|
||||||
|
self.name = name
|
||||||
|
self.build_mila()
|
||||||
|
|
||||||
|
def build_mila(self):
|
||||||
|
for key, value in self.regs.d.items():
|
||||||
|
if self.name in key:
|
||||||
|
key.replace(self.name, "mila")
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
def prog_term(self, trigger, mask):
|
||||||
|
self.mila_trigger_port0_trig.write(trigger)
|
||||||
|
self.mila_trigger_port0_mask.write(mask)
|
||||||
|
|
||||||
|
def prog_sum(self, datas):
|
||||||
|
for adr, dat in enumerate(datas):
|
||||||
|
self.mila_trigger_sum_prog_adr.write(adr)
|
||||||
|
self.mila_trigger_sum_prog_dat.write(dat)
|
||||||
|
self.mila_trigger_sum_prog_we.write(1)
|
||||||
|
|
||||||
|
def enable_rle(self):
|
||||||
|
self.mila_rle_enable.write(1)
|
||||||
|
|
||||||
|
def disable_rle(self):
|
||||||
|
self.mila_rle_enable.write(0)
|
||||||
|
|
||||||
|
def is_done(self):
|
||||||
|
return self.mila_recorder_done.read()
|
||||||
|
|
||||||
|
def trigger(self, offset, length):
|
||||||
|
self.mila_recorder_offset.write(offset)
|
||||||
|
self.mila_recorder_length.write(length)
|
||||||
|
self.mila_recorder_trigger.write(1)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
r = []
|
||||||
|
empty = self.mila_recorder_read_empty.read()
|
||||||
|
while(not empty):
|
||||||
|
r.append(self.mila_recorder_read_dat.read())
|
||||||
|
empty = self.mila_recorder_read_empty.read()
|
||||||
|
self.mila_recorder_read_en.write(1)
|
||||||
|
return r
|
48
miscope/host/regs.py
Normal file
48
miscope/host/regs.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import csv
|
||||||
|
|
||||||
|
class MappedReg:
|
||||||
|
def __init__(self, readfn, writefn, name, addr, length, mode):
|
||||||
|
self.readfn = readfn
|
||||||
|
self.writefn = writefn
|
||||||
|
self.addr = addr
|
||||||
|
self.length = length
|
||||||
|
self.mode = mode
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
if self.mode not in ["rw", "ro"]:
|
||||||
|
raise KeyError(name + "register not readable")
|
||||||
|
r = 0
|
||||||
|
for i in range(self.length):
|
||||||
|
r |= self.readfn(self.addr + 4*i)
|
||||||
|
if i != (self.length-1):
|
||||||
|
r <<= 8
|
||||||
|
return r
|
||||||
|
|
||||||
|
def write(self, value):
|
||||||
|
if self.mode not in ["rw", "wo"]:
|
||||||
|
raise KeyError(name + "register not writable")
|
||||||
|
for i in range(self.length):
|
||||||
|
dat = (value >> ((self.length-1-i)*8)) & 0xff
|
||||||
|
self.writefn(self.addr + 4*i, dat)
|
||||||
|
|
||||||
|
class MappedRegs:
|
||||||
|
def __init__(self, d):
|
||||||
|
self.d = d
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
try:
|
||||||
|
return self.__dict__['d'][attr]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
raise KeyError("No such register " + attr)
|
||||||
|
|
||||||
|
def build_map(addrmap, readfn, writefn):
|
||||||
|
csv_reader = csv.reader(open(addrmap), delimiter=',', quotechar='#')
|
||||||
|
d = {}
|
||||||
|
for item in csv_reader:
|
||||||
|
name, addr, length, mode = item
|
||||||
|
addr = int(addr.replace("0x", ""), 16)
|
||||||
|
length = int(length)
|
||||||
|
d[name] = MappedReg(readfn, writefn, name, addr, length, mode)
|
||||||
|
return MappedRegs(d)
|
78
miscope/host/uart2wishbone.py
Normal file
78
miscope/host/uart2wishbone.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import string
|
||||||
|
import serial
|
||||||
|
from struct import *
|
||||||
|
from migen.fhdl.structure import *
|
||||||
|
from miscope.host.regs import *
|
||||||
|
|
||||||
|
def write_b(uart, data):
|
||||||
|
uart.write(pack('B',data))
|
||||||
|
|
||||||
|
class Uart2Wishbone:
|
||||||
|
WRITE_CMD = 0x01
|
||||||
|
READ_CMD = 0x02
|
||||||
|
def __init__(self, port, baudrate, addrmap=None, debug=False):
|
||||||
|
self.port = port
|
||||||
|
self.baudrate = baudrate
|
||||||
|
self.debug = debug
|
||||||
|
self.uart = serial.Serial(port, baudrate, timeout=0.25)
|
||||||
|
self.regs = build_map(addrmap, self.read, self.write)
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
self.uart.flushOutput()
|
||||||
|
self.uart.close()
|
||||||
|
self.uart.open()
|
||||||
|
self.uart.flushInput()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.uart.close()
|
||||||
|
|
||||||
|
def read(self, addr, burst_length=1):
|
||||||
|
self.uart.flushInput()
|
||||||
|
write_b(self.uart, self.READ_CMD)
|
||||||
|
write_b(self.uart, burst_length)
|
||||||
|
addr = addr//4
|
||||||
|
write_b(self.uart, (addr & 0xff000000) >> 24)
|
||||||
|
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
||||||
|
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
||||||
|
write_b(self.uart, (addr & 0x000000ff))
|
||||||
|
values = []
|
||||||
|
for i in range(burst_length):
|
||||||
|
val = 0
|
||||||
|
for j in range(4):
|
||||||
|
val = val << 8
|
||||||
|
val |= ord(self.uart.read())
|
||||||
|
if self.debug:
|
||||||
|
print("RD %08X @ %08X" %(val, (addr+i)*4))
|
||||||
|
values.append(val)
|
||||||
|
if burst_length == 1:
|
||||||
|
return values[0]
|
||||||
|
else:
|
||||||
|
return values
|
||||||
|
|
||||||
|
def write(self, addr, data):
|
||||||
|
if isinstance(data, list):
|
||||||
|
burst_length = len(data)
|
||||||
|
else:
|
||||||
|
burst_length = 1
|
||||||
|
write_b(self.uart, self.WRITE_CMD)
|
||||||
|
write_b(self.uart, burst_length)
|
||||||
|
addr = addr//4
|
||||||
|
write_b(self.uart, (addr & 0xff000000) >> 24)
|
||||||
|
write_b(self.uart, (addr & 0x00ff0000) >> 16)
|
||||||
|
write_b(self.uart, (addr & 0x0000ff00) >> 8)
|
||||||
|
write_b(self.uart, (addr & 0x000000ff))
|
||||||
|
if isinstance(data, list):
|
||||||
|
for i in range(len(data)):
|
||||||
|
dat = data[i]
|
||||||
|
for j in range(4):
|
||||||
|
write_b(self.uart, (dat & 0xff000000) >> 24)
|
||||||
|
dat = dat << 8
|
||||||
|
if self.debug:
|
||||||
|
print("WR %08X @ %08X" %(data[i], (addr + i)*4))
|
||||||
|
else:
|
||||||
|
dat = data
|
||||||
|
for j in range(4):
|
||||||
|
write_b(self.uart, (dat & 0xff000000) >> 24)
|
||||||
|
dat = dat << 8
|
||||||
|
if self.debug:
|
||||||
|
print("WR %08X @ %08X" %(data, (addr * 4)))
|
|
@ -7,7 +7,7 @@ from migen.bank.description import *
|
||||||
|
|
||||||
from miscope.std import *
|
from miscope.std import *
|
||||||
from miscope.trigger import Trigger
|
from miscope.trigger import Trigger
|
||||||
from miscope.storage import RunLengthEncoder, Recorder
|
from miscope.storage import Recorder, RunLengthEncoder
|
||||||
|
|
||||||
class MiLa(Module, AutoCSR):
|
class MiLa(Module, AutoCSR):
|
||||||
def __init__(self, width, depth, ports, rle=False):
|
def __init__(self, width, depth, ports, rle=False):
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
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,89 +0,0 @@
|
||||||
from migen.fhdl.std import *
|
|
||||||
|
|
||||||
def dec2bin(d, nb=0):
|
|
||||||
if d=="x":
|
|
||||||
return "x"*nb
|
|
||||||
elif d==0:
|
|
||||||
b="0"
|
|
||||||
else:
|
|
||||||
b=""
|
|
||||||
while d!=0:
|
|
||||||
b="01"[d&1]+b
|
|
||||||
d=d>>1
|
|
||||||
return b.zfill(nb)
|
|
||||||
|
|
||||||
class RisingEdge(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.i = Signal()
|
|
||||||
self.o = Signal()
|
|
||||||
####
|
|
||||||
i_d = Signal()
|
|
||||||
self.sync += i_d.eq(self.i)
|
|
||||||
self.comb += self.o.eq(self.i & ~i_d)
|
|
||||||
|
|
||||||
class FallingEdge(Module):
|
|
||||||
def __init__(self):
|
|
||||||
self.i = Signal()
|
|
||||||
self.o = Signal()
|
|
||||||
####
|
|
||||||
i_d = Signal()
|
|
||||||
self.sync += i_d.eq(self.i)
|
|
||||||
self.comb += self.o.eq(~self.i & i_d)
|
|
||||||
|
|
||||||
class FreqGen(Module):
|
|
||||||
def __init__(self, clk_freq, freq):
|
|
||||||
cnt_max = int(clk_freq/freq/2)
|
|
||||||
self.o = Signal()
|
|
||||||
####
|
|
||||||
cnt = Signal(max=cnt_max)
|
|
||||||
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, level=RISING_EDGE, clk_freq=0, length=1):
|
|
||||||
cnt_max = int(length*clk_freq)
|
|
||||||
self.o = Signal()
|
|
||||||
###
|
|
||||||
cnt = Signal(max=cnt_max)
|
|
||||||
|
|
||||||
if level == RISING_EDGE:
|
|
||||||
self.submodules.edge_detect = RisingEdge()
|
|
||||||
elif level == FALLING_EDGE:
|
|
||||||
self.submodules.edge_detect = FallingEdge()
|
|
||||||
|
|
||||||
self.i = self.edge_detect.i
|
|
||||||
|
|
||||||
self.sync += [
|
|
||||||
If(self.edge_detect.o == 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):
|
|
||||||
self.ratio = Signal(width)
|
|
||||||
self.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)
|
|
||||||
]
|
|
297
miscope/uart2wishbone.py
Normal file
297
miscope/uart2wishbone.py
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
from migen.fhdl.structure import *
|
||||||
|
from migen.fhdl.module import *
|
||||||
|
from migen.genlib.record import *
|
||||||
|
from migen.genlib.cdc import MultiReg
|
||||||
|
from migen.genlib.fsm import FSM, NextState
|
||||||
|
from migen.genlib.misc import split, displacer, chooser
|
||||||
|
from migen.bank.description import *
|
||||||
|
from migen.bus import wishbone
|
||||||
|
|
||||||
|
|
||||||
|
# Todo
|
||||||
|
# ----
|
||||||
|
# - implement timeout in fsm to prevent deadlocks
|
||||||
|
|
||||||
|
def rec_rx():
|
||||||
|
layout = [
|
||||||
|
("stb", 1, DIR_M_TO_S),
|
||||||
|
("dat", 8, DIR_M_TO_S)
|
||||||
|
]
|
||||||
|
return Record(layout)
|
||||||
|
|
||||||
|
def rec_tx():
|
||||||
|
layout = [
|
||||||
|
("stb", 1, DIR_M_TO_S),
|
||||||
|
("ack", 1, DIR_S_TO_M),
|
||||||
|
("dat", 8, DIR_M_TO_S)
|
||||||
|
]
|
||||||
|
return Record(layout)
|
||||||
|
|
||||||
|
class UART(Module):
|
||||||
|
def __init__(self, pads, clk_freq, baud=115200):
|
||||||
|
|
||||||
|
self.rx = rec_rx()
|
||||||
|
self.tx = rec_tx()
|
||||||
|
|
||||||
|
self.divisor = Signal(16, reset=int(clk_freq/baud/16))
|
||||||
|
|
||||||
|
pads.tx.reset = 1
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
enable16 = Signal()
|
||||||
|
enable16_counter = Signal(16)
|
||||||
|
self.comb += enable16.eq(enable16_counter == 0)
|
||||||
|
self.sync += [
|
||||||
|
enable16_counter.eq(enable16_counter - 1),
|
||||||
|
If(enable16,
|
||||||
|
enable16_counter.eq(self.divisor - 1))
|
||||||
|
]
|
||||||
|
|
||||||
|
# TX
|
||||||
|
tx_reg = Signal(8)
|
||||||
|
tx_bitcount = Signal(4)
|
||||||
|
tx_count16 = Signal(4)
|
||||||
|
tx_done = self.tx.ack
|
||||||
|
tx_busy = Signal()
|
||||||
|
tx_stb_d = Signal()
|
||||||
|
self.sync += [
|
||||||
|
tx_stb_d.eq(self.tx.stb & ~tx_done),
|
||||||
|
tx_done.eq(0),
|
||||||
|
If(self.tx.stb & ~tx_stb_d,
|
||||||
|
tx_reg.eq(self.tx.dat),
|
||||||
|
tx_bitcount.eq(0),
|
||||||
|
tx_count16.eq(1),
|
||||||
|
tx_busy.eq(1),
|
||||||
|
pads.tx.eq(0)
|
||||||
|
).Elif(enable16 & tx_busy,
|
||||||
|
tx_count16.eq(tx_count16 + 1),
|
||||||
|
If(tx_count16 == 0,
|
||||||
|
tx_bitcount.eq(tx_bitcount + 1),
|
||||||
|
If(tx_bitcount == 8,
|
||||||
|
pads.tx.eq(1)
|
||||||
|
).Elif(tx_bitcount == 9,
|
||||||
|
pads.tx.eq(1),
|
||||||
|
tx_busy.eq(0),
|
||||||
|
tx_done.eq(1)
|
||||||
|
).Else(
|
||||||
|
pads.tx.eq(tx_reg[0]),
|
||||||
|
tx_reg.eq(Cat(tx_reg[1:], 0))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
# RX
|
||||||
|
rx = Signal()
|
||||||
|
self.specials += MultiReg(pads.rx, rx, "sys")
|
||||||
|
rx_r = Signal()
|
||||||
|
rx_reg = Signal(8)
|
||||||
|
rx_bitcount = Signal(4)
|
||||||
|
rx_count16 = Signal(4)
|
||||||
|
rx_busy = Signal()
|
||||||
|
rx_done = self.rx.stb
|
||||||
|
rx_data = self.rx.dat
|
||||||
|
self.sync += [
|
||||||
|
rx_done.eq(0),
|
||||||
|
If(enable16,
|
||||||
|
rx_r.eq(rx),
|
||||||
|
If(~rx_busy,
|
||||||
|
If(~rx & rx_r, # look for start bit
|
||||||
|
rx_busy.eq(1),
|
||||||
|
rx_count16.eq(7),
|
||||||
|
rx_bitcount.eq(0)
|
||||||
|
)
|
||||||
|
).Else(
|
||||||
|
rx_count16.eq(rx_count16 + 1),
|
||||||
|
If(rx_count16 == 0,
|
||||||
|
rx_bitcount.eq(rx_bitcount + 1),
|
||||||
|
|
||||||
|
If(rx_bitcount == 0,
|
||||||
|
If(rx, # verify start bit
|
||||||
|
rx_busy.eq(0)
|
||||||
|
)
|
||||||
|
).Elif(rx_bitcount == 9,
|
||||||
|
rx_busy.eq(0),
|
||||||
|
If(rx, # verify stop bit
|
||||||
|
rx_data.eq(rx_reg),
|
||||||
|
rx_done.eq(1)
|
||||||
|
)
|
||||||
|
).Else(
|
||||||
|
rx_reg.eq(Cat(rx_reg[1:], rx))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
class Counter(Module):
|
||||||
|
def __init__(self, width):
|
||||||
|
self.value = Signal(width)
|
||||||
|
self.clr = Signal()
|
||||||
|
self.inc = Signal()
|
||||||
|
self.sync += [
|
||||||
|
If(self.clr,
|
||||||
|
self.value.eq(0)
|
||||||
|
).Elif(self.inc,
|
||||||
|
self.value.eq(self.value+1)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
class UARTPads:
|
||||||
|
def __init__(self):
|
||||||
|
self.rx = Signal()
|
||||||
|
self.tx = Signal()
|
||||||
|
|
||||||
|
class UARTMux(Module):
|
||||||
|
def __init__(self, pads, nb):
|
||||||
|
self.sel = Signal(max=nb)
|
||||||
|
self.pads = [UARTPads() for i in range(nb)]
|
||||||
|
|
||||||
|
###
|
||||||
|
# Route Rx pad to all modules
|
||||||
|
for i in range(nb):
|
||||||
|
self.comb += self.pads[i].rx.eq(pads.rx)
|
||||||
|
|
||||||
|
# Route only selected module to Tx pad
|
||||||
|
pads_tx = [self.pads[i].tx for i in range(nb)]
|
||||||
|
self.comb += chooser(Cat(pads_tx), self.sel, pads.tx, n=nb)
|
||||||
|
|
||||||
|
|
||||||
|
class UART2Wishbone(Module, AutoCSR):
|
||||||
|
WRITE_CMD = 0x01
|
||||||
|
READ_CMD = 0x02
|
||||||
|
def __init__(self, pads, clk_freq, baud, share_uart=False):
|
||||||
|
|
||||||
|
# Wishbone interface
|
||||||
|
self.wishbone = wishbone.Interface()
|
||||||
|
if share_uart:
|
||||||
|
self._sel = CSRStorage()
|
||||||
|
|
||||||
|
###
|
||||||
|
if share_uart:
|
||||||
|
self.submodules.uart_mux = UARTMux(pads, 2)
|
||||||
|
self.submodules.uart = UART(self.uart_mux.pads[1], clk_freq, baud)
|
||||||
|
self.shared_pads = self.uart_mux.pads[0]
|
||||||
|
self.comb += self.uart_mux.sel.eq(self._sel.storage)
|
||||||
|
else:
|
||||||
|
self.submodules.uart = UART(pads, clk_freq, baud)
|
||||||
|
|
||||||
|
uart = self.uart
|
||||||
|
|
||||||
|
fsm = FSM()
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
|
word_cnt = Counter(3)
|
||||||
|
burst_cnt = Counter(8)
|
||||||
|
self.submodules += word_cnt, burst_cnt
|
||||||
|
|
||||||
|
###
|
||||||
|
cmd = Signal(8)
|
||||||
|
fsm.act("WAIT_CMD",
|
||||||
|
If(uart.rx.stb,
|
||||||
|
If( (uart.rx.dat == self.WRITE_CMD) |
|
||||||
|
(uart.rx.dat == self.READ_CMD),
|
||||||
|
NextState("RECEIVE_BURST_LENGTH")
|
||||||
|
),
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
burst_cnt.clr.eq(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.sync += If(fsm.ongoing("WAIT_CMD") & uart.rx.stb, cmd.eq(uart.rx.dat))
|
||||||
|
|
||||||
|
####
|
||||||
|
burst_length = Signal(8)
|
||||||
|
fsm.act("RECEIVE_BURST_LENGTH",
|
||||||
|
word_cnt.inc.eq(uart.rx.stb),
|
||||||
|
If(word_cnt.value == 1,
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
NextState("RECEIVE_ADDRESS")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.sync += \
|
||||||
|
If(fsm.ongoing("RECEIVE_BURST_LENGTH") & uart.rx.stb, burst_length.eq(uart.rx.dat))
|
||||||
|
|
||||||
|
####
|
||||||
|
address = Signal(32)
|
||||||
|
fsm.act("RECEIVE_ADDRESS",
|
||||||
|
word_cnt.inc.eq(uart.rx.stb),
|
||||||
|
If(word_cnt.value == 4,
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
If(cmd == self.WRITE_CMD,
|
||||||
|
NextState("RECEIVE_DATA")
|
||||||
|
).Elif(cmd == self.READ_CMD,
|
||||||
|
NextState("READ_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.sync += \
|
||||||
|
If(fsm.ongoing("RECEIVE_ADDRESS") & uart.rx.stb,
|
||||||
|
address.eq(Cat(uart.rx.dat, address[0:24]))
|
||||||
|
)
|
||||||
|
|
||||||
|
###
|
||||||
|
data = Signal(32)
|
||||||
|
|
||||||
|
###
|
||||||
|
fsm.act("RECEIVE_DATA",
|
||||||
|
word_cnt.inc.eq(uart.rx.stb),
|
||||||
|
If(word_cnt.value == 4,
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
NextState("WRITE_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("WRITE_DATA",
|
||||||
|
self.wishbone.adr.eq(address + burst_cnt.value),
|
||||||
|
self.wishbone.dat_w.eq(data),
|
||||||
|
self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1),
|
||||||
|
self.wishbone.stb.eq(1),
|
||||||
|
self.wishbone.we.eq(1),
|
||||||
|
self.wishbone.cyc.eq(1),
|
||||||
|
If(self.wishbone.ack,
|
||||||
|
burst_cnt.inc.eq(1),
|
||||||
|
If(burst_cnt.value == (burst_length-1),
|
||||||
|
NextState("WAIT_CMD")
|
||||||
|
).Else(
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
NextState("RECEIVE_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
###
|
||||||
|
fsm.act("READ_DATA",
|
||||||
|
self.wishbone.adr.eq(address + burst_cnt.value),
|
||||||
|
self.wishbone.sel.eq(2**flen(self.wishbone.sel)-1),
|
||||||
|
self.wishbone.stb.eq(1),
|
||||||
|
self.wishbone.we.eq(0),
|
||||||
|
self.wishbone.cyc.eq(1),
|
||||||
|
If(self.wishbone.stb & self.wishbone.ack,
|
||||||
|
word_cnt.clr.eq(1),
|
||||||
|
NextState("SEND_DATA")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("SEND_DATA",
|
||||||
|
word_cnt.inc.eq(uart.tx.ack),
|
||||||
|
If(word_cnt.value == 4,
|
||||||
|
burst_cnt.inc.eq(1),
|
||||||
|
If(burst_cnt.value == (burst_length-1),
|
||||||
|
NextState("WAIT_CMD")
|
||||||
|
).Else(
|
||||||
|
NextState("READ_DATA")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
uart.tx.stb.eq(1),
|
||||||
|
chooser(data, word_cnt.value, uart.tx.dat, n=4, reverse=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
###
|
||||||
|
self.sync += \
|
||||||
|
If(fsm.ongoing("RECEIVE_DATA") & uart.rx.stb,
|
||||||
|
data.eq(Cat(uart.rx.dat, data[0:24]))
|
||||||
|
).Elif(fsm.ongoing("READ_DATA") & self.wishbone.stb & self.wishbone.ack,
|
||||||
|
data.eq(self.wishbone.dat_r)
|
||||||
|
)
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -7,7 +7,7 @@ from setuptools import find_packages
|
||||||
here = os.path.abspath(os.path.dirname(__file__))
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
README = open(os.path.join(here, "README")).read()
|
README = open(os.path.join(here, "README")).read()
|
||||||
|
|
||||||
required_version = (3, 1)
|
required_version = (3, 3)
|
||||||
if sys.version_info < required_version:
|
if sys.version_info < required_version:
|
||||||
raise SystemExit("Migscope requires python {0} or greater".format(
|
raise SystemExit("Migscope requires python {0} or greater".format(
|
||||||
".".join(map(str, required_version))))
|
".".join(map(str, required_version))))
|
||||||
|
|
11
sim/cpuif.py
Normal file
11
sim/cpuif.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from migen.bank.description import CSRStatus
|
||||||
|
|
||||||
|
def get_csr_csv(csr_base, bank_array):
|
||||||
|
r = ""
|
||||||
|
for name, csrs, mapaddr, rmap in bank_array.banks:
|
||||||
|
reg_base = csr_base + 0x800*mapaddr
|
||||||
|
for csr in csrs:
|
||||||
|
nr = (csr.size + 7)//8
|
||||||
|
r += "{}_{},0x{:08x},{},{}\n".format(name, csr.name, reg_base, nr, "ro" if isinstance(csr, CSRStatus) else "rw")
|
||||||
|
reg_base += 4*nr
|
||||||
|
return r
|
|
@ -1,21 +1,17 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl import verilog
|
from migen.fhdl import verilog
|
||||||
from migen.bus import csr
|
from migen.bus import csr
|
||||||
from migen.sim.generic import Simulator, TopLevel
|
from migen.sim.generic import run_simulation
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
from migen.bus.transactions import *
|
||||||
|
|
||||||
from miscope.std import cif
|
from miscope.std import *
|
||||||
from miscope.std.truthtable import *
|
|
||||||
from miscope.storage import *
|
from miscope.storage import *
|
||||||
|
|
||||||
from mibuild.tools import write_to_file
|
from mibuild.tools import write_to_file
|
||||||
|
from miscope.tools.regs import *
|
||||||
|
from miscope.tools.truthtable import *
|
||||||
|
|
||||||
try:
|
from cpuif import *
|
||||||
from csr_header import *
|
|
||||||
print("csr_header imported")
|
|
||||||
except:
|
|
||||||
print("csr_header not found")
|
|
||||||
|
|
||||||
class Csr2Trans():
|
class Csr2Trans():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -38,30 +34,26 @@ dat_rdy = False
|
||||||
|
|
||||||
rec_length = 128
|
rec_length = 128
|
||||||
|
|
||||||
def csr_configure():
|
def csr_configure(bus, regs):
|
||||||
bus = Csr2Trans()
|
|
||||||
|
|
||||||
# Length
|
# Length
|
||||||
recorder_length_write(bus, rec_length)
|
regs.recorder_length.write(rec_length)
|
||||||
|
|
||||||
# Offset
|
# Offset
|
||||||
recorder_offset_write(bus, 0)
|
regs.recorder_offset.write(0)
|
||||||
|
|
||||||
# Trigger
|
# Trigger
|
||||||
recorder_trigger_write(bus, 1)
|
regs.recorder_trigger.write(1)
|
||||||
|
|
||||||
return bus.t
|
return bus.t
|
||||||
|
|
||||||
def csr_read_data():
|
def csr_read_data(bus, regs):
|
||||||
bus = Csr2Trans()
|
|
||||||
|
|
||||||
for i in range(rec_length+100):
|
for i in range(rec_length+100):
|
||||||
recorder_read_dat_read(bus)
|
regs.recorder_read_dat.read()
|
||||||
recorder_read_en_write(bus, 1)
|
regs.recorder_read_en.write(1)
|
||||||
return bus.t
|
return bus.t
|
||||||
|
|
||||||
def csr_transactions():
|
def csr_transactions(bus, regs):
|
||||||
for t in csr_configure():
|
for t in csr_configure(bus, regs):
|
||||||
yield t
|
yield t
|
||||||
|
|
||||||
for t in range(100):
|
for t in range(100):
|
||||||
|
@ -73,7 +65,7 @@ def csr_transactions():
|
||||||
for t in range(512):
|
for t in range(512):
|
||||||
yield None
|
yield None
|
||||||
|
|
||||||
for t in csr_read_data():
|
for t in csr_read_data(bus, regs):
|
||||||
yield t
|
yield t
|
||||||
|
|
||||||
for t in range(100):
|
for t in range(100):
|
||||||
|
@ -85,56 +77,57 @@ class TB(Module):
|
||||||
csr_map = {
|
csr_map = {
|
||||||
"recorder": 1,
|
"recorder": 1,
|
||||||
}
|
}
|
||||||
def __init__(self, first_run=False):
|
def __init__(self, addrmap=None):
|
||||||
self.csr_base = 0
|
self.csr_base = 0
|
||||||
|
|
||||||
# Csr Master
|
|
||||||
if not first_run:
|
|
||||||
self.submodules.master = csr.Initiator(csr_transactions())
|
|
||||||
|
|
||||||
# Recorder
|
# Recorder
|
||||||
self.submodules.recorder = Recorder(32, 1024)
|
self.submodules.recorder = Recorder(32, 1024)
|
||||||
|
|
||||||
# Csr
|
# Csr
|
||||||
self.submodules.csrbankarray = csrgen.BankArray(self,
|
self.submodules.csrbankarray = csrgen.BankArray(self,
|
||||||
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
||||||
if not first_run:
|
|
||||||
|
# Csr Master
|
||||||
|
csr_header = get_csr_csv(self.csr_base, self.csrbankarray)
|
||||||
|
write_to_file("csr.csv", csr_header)
|
||||||
|
|
||||||
|
bus = Csr2Trans()
|
||||||
|
regs = build_map(addrmap, bus.read_csr, bus.write_csr)
|
||||||
|
self.submodules.master = csr.Initiator(csr_transactions(bus, regs))
|
||||||
|
|
||||||
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
||||||
|
|
||||||
# Recorder Data
|
# Recorder Data
|
||||||
def recorder_data(self, s):
|
def recorder_data(self, selfp):
|
||||||
s.wr(self.recorder.sink.stb, 1)
|
selfp.recorder.dat_sink.stb = 1
|
||||||
if not hasattr(self, "cnt"):
|
if not hasattr(self, "cnt"):
|
||||||
self.cnt = 0
|
self.cnt = 0
|
||||||
self.cnt += 1
|
self.cnt += 1
|
||||||
|
|
||||||
s.wr(self.recorder.sink.payload.d, self.cnt)
|
selfp.recorder.dat_sink.dat = self.cnt
|
||||||
|
|
||||||
global triggered
|
global triggered
|
||||||
if triggered:
|
if triggered:
|
||||||
s.wr(self.recorder.sink.payload.hit, 1)
|
selfp.recorder.trig_sink.stb = 1
|
||||||
|
selfp.recorder.trig_sink.hit = 1
|
||||||
triggered = False
|
triggered = False
|
||||||
else:
|
else:
|
||||||
s.wr(self.recorder.sink.payload.hit, 0)
|
selfp.recorder.trig_sink.stb = 0
|
||||||
|
selfp.recorder.trig_sink.hit = 0
|
||||||
|
|
||||||
# Simulation
|
# Simulation
|
||||||
def end_simulation(self, s):
|
def end_simulation(self, selfp):
|
||||||
s.interrupt = self.master.done
|
if self.master.done:
|
||||||
|
raise StopSimulation
|
||||||
|
|
||||||
|
def do_simulation(self, selfp):
|
||||||
def do_simulation(self, s):
|
self.recorder_data(selfp)
|
||||||
self.recorder_data(s)
|
self.end_simulation(selfp)
|
||||||
self.end_simulation(s)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
tb = TB(first_run=True)
|
tb = TB(addrmap="csr.csv")
|
||||||
csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray)
|
run_simulation(tb, ncycles=2000, vcd_name="tb_recorder_csr.vcd")
|
||||||
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")
|
print("Sim Done")
|
||||||
input()
|
input()
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl import verilog
|
from migen.sim.generic import run_simulation
|
||||||
from migen.sim.generic import Simulator, TopLevel
|
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
|
|
||||||
from miscope.storage import RunLengthEncoder
|
|
||||||
|
|
||||||
|
from miscope import storage
|
||||||
|
|
||||||
rle_test_seq = iter(
|
rle_test_seq = iter(
|
||||||
[ 0x00AA,
|
[ 0x00AA,
|
||||||
|
@ -29,20 +26,19 @@ class TB(Module):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# Rle
|
# Rle
|
||||||
self.submodules.rle = RunLengthEncoder(16, 32)
|
self.submodules.rle = storage.RunLengthEncoder(16, 32)
|
||||||
|
|
||||||
def do_simulation(self, s):
|
def do_simulation(self, selfp):
|
||||||
s.wr(self.rle._r_enable.storage, 1)
|
selfp.rle._r_enable.storage = 1
|
||||||
s.wr(self.rle.sink.stb, 1)
|
selfp.rle.sink.stb = 1
|
||||||
try:
|
try:
|
||||||
s.wr(self.rle.sink.dat, next(rle_test_seq))
|
selfp.rle.sink.dat = next(rle_test_seq)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
tb = TB()
|
tb = TB()
|
||||||
sim = Simulator(tb, TopLevel("tb_rle.vcd"))
|
run_simulation(tb, ncycles=8000, vcd_name="tb_rle.vcd")
|
||||||
sim.run(2000)
|
|
||||||
print("Sim Done")
|
print("Sim Done")
|
||||||
input()
|
input()
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
from migen.fhdl.std import *
|
from migen.fhdl.std import *
|
||||||
from migen.fhdl import verilog
|
from migen.fhdl import verilog
|
||||||
from migen.bus import csr
|
from migen.bus import csr
|
||||||
from migen.sim.generic import Simulator, TopLevel
|
from migen.sim.generic import run_simulation
|
||||||
from migen.sim.icarus import Runner
|
|
||||||
from migen.bus.transactions import *
|
from migen.bus.transactions import *
|
||||||
|
|
||||||
from miscope.std import cif
|
from miscope.std import *
|
||||||
from miscope.std.truthtable import *
|
|
||||||
from miscope.trigger import *
|
from miscope.trigger import *
|
||||||
|
|
||||||
from mibuild.tools import write_to_file
|
from mibuild.tools import write_to_file
|
||||||
|
from miscope.tools.regs import *
|
||||||
|
from miscope.tools.truthtable import *
|
||||||
|
|
||||||
try:
|
from cpuif import *
|
||||||
from csr_header import *
|
|
||||||
print("csr_header imported")
|
|
||||||
except:
|
|
||||||
print("csr_header not found")
|
|
||||||
|
|
||||||
class Csr2Trans():
|
class Csr2Trans():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -27,30 +23,29 @@ class Csr2Trans():
|
||||||
def read_csr(self, adr):
|
def read_csr(self, adr):
|
||||||
self.t.append(TRead(adr//4))
|
self.t.append(TRead(adr//4))
|
||||||
|
|
||||||
def csr_prog_mila():
|
def csr_prog_mila(bus, regs):
|
||||||
bus = Csr2Trans()
|
regs.trigger_port0_mask.write(0xFFFFFFFF)
|
||||||
trigger_port0_mask_write(bus, 0xFFFFFFFF)
|
regs.trigger_port0_trig.write(0xDEADBEEF)
|
||||||
trigger_port0_trig_write(bus, 0xDEADBEEF)
|
regs.trigger_port1_mask.write(0xFFFFFFFF)
|
||||||
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
regs.trigger_port1_trig.write(0xDEADBEEF)
|
||||||
trigger_port1_trig_write(bus, 0xDEADBEEF)
|
regs.trigger_port1_mask.write(0xFFFFFFFF)
|
||||||
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
regs.trigger_port1_mask.write(0xFFFFFFFF)
|
||||||
trigger_port1_mask_write(bus, 0xFFFFFFFF)
|
regs.trigger_port1_trig.write(0xDEADBEEF)
|
||||||
trigger_port1_trig_write(bus, 0xDEADBEEF)
|
|
||||||
|
|
||||||
sum_tt = gen_truth_table("i1 & i2 & i3 & i4")
|
sum_tt = gen_truth_table("i1 & i2 & i3 & i4")
|
||||||
sum_trans = []
|
sum_trans = []
|
||||||
for i in range(len(sum_tt)):
|
for i in range(len(sum_tt)):
|
||||||
trigger_sum_prog_adr_write(bus, i)
|
regs.trigger_sum_prog_adr.write(i)
|
||||||
trigger_sum_prog_dat_write(bus, sum_tt[i])
|
regs.trigger_sum_prog_dat.write(sum_tt[i])
|
||||||
trigger_sum_prog_we_write(bus, 1)
|
regs.trigger_sum_prog_we.write(1)
|
||||||
|
|
||||||
return bus.t
|
return bus.t
|
||||||
|
|
||||||
|
|
||||||
csr_done = False
|
csr_done = False
|
||||||
|
|
||||||
def csr_transactions():
|
def csr_transactions(bus, regs):
|
||||||
for t in csr_prog_mila():
|
for t in csr_prog_mila(bus, regs):
|
||||||
yield t
|
yield t
|
||||||
global csr_done
|
global csr_done
|
||||||
csr_done = True
|
csr_done = True
|
||||||
|
@ -62,12 +57,8 @@ class TB(Module):
|
||||||
csr_map = {
|
csr_map = {
|
||||||
"trigger": 1,
|
"trigger": 1,
|
||||||
}
|
}
|
||||||
def __init__(self, first_run=False):
|
def __init__(self, addrmap=None):
|
||||||
|
self.csr_base = 0
|
||||||
|
|
||||||
# Csr Master
|
|
||||||
if not first_run:
|
|
||||||
self.submodules.master = csr.Initiator(csr_transactions())
|
|
||||||
|
|
||||||
# Trigger
|
# Trigger
|
||||||
term0 = Term(32)
|
term0 = Term(32)
|
||||||
|
@ -79,29 +70,32 @@ class TB(Module):
|
||||||
# Csr
|
# Csr
|
||||||
self.submodules.csrbankarray = csrgen.BankArray(self,
|
self.submodules.csrbankarray = csrgen.BankArray(self,
|
||||||
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
|
||||||
if not first_run:
|
|
||||||
|
# Csr Master
|
||||||
|
csr_header = get_csr_csv(self.csr_base, self.csrbankarray)
|
||||||
|
write_to_file("csr.csv", csr_header)
|
||||||
|
|
||||||
|
bus = Csr2Trans()
|
||||||
|
regs = build_map(addrmap, bus.read_csr, bus.write_csr)
|
||||||
|
self.submodules.master = csr.Initiator(csr_transactions(bus, regs))
|
||||||
|
|
||||||
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
self.submodules.csrcon = csr.Interconnect(self.master.bus, self.csrbankarray.get_buses())
|
||||||
|
|
||||||
self.terms = [term0, term1, term2, term3]
|
self.terms = [term0, term1, term2, term3]
|
||||||
|
|
||||||
def do_simulation(self, s):
|
def do_simulation(self, selfp):
|
||||||
for term in self.terms:
|
for term in selfp.terms:
|
||||||
s.wr(term.sink.stb, 1)
|
term.sink.stb = 1
|
||||||
if csr_done:
|
if csr_done:
|
||||||
s.wr(self.terms[0].sink.payload.d, 0xDEADBEEF)
|
selfp.terms[0].sink.dat = 0xDEADBEEF
|
||||||
s.wr(self.terms[1].sink.payload.d ,0xCAFEFADE)
|
selfp.terms[1].sink.dat = 0xCAFEFADE
|
||||||
s.wr(self.terms[2].sink.payload.d, 0xDEADBEEF)
|
selfp.terms[2].sink.dat = 0xDEADBEEF
|
||||||
s.wr(self.terms[3].sink.payload.d, 0xCAFEFADE)
|
selfp.terms[3].sink.dat = 0xCAFEFADE
|
||||||
s.interrupt = self.master.done
|
raise StopSimulation
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
tb = TB(first_run=True)
|
tb = TB(addrmap="csr.csv")
|
||||||
csr_py_header = cif.get_py_csr_header(tb.csr_base, tb.csrbankarray)
|
run_simulation(tb, ncycles=2000, vcd_name="tb_trigger_csr.vcd")
|
||||||
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")
|
print("Sim Done")
|
||||||
input()
|
input()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue