Compare commits
3 commits
bc82d2658f
...
4c36c00e64
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c36c00e64 | ||
|
|
a88421a781 | ||
|
|
3f9a100e7c |
6 changed files with 121 additions and 19 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 60aae89495f05eedb48c9c1468e4c8d4dd92f79f
|
||||
Subproject commit 9bbfeb3316098af16370c10355c94ed7ec06f5ee
|
||||
|
|
@ -231,3 +231,4 @@ set_global_assignment -name VERILOG_MACRO "L2_AHEPAM=1"
|
|||
set_global_assignment -name VERILOG_MACRO "WITH_SPI_SSEL=1"
|
||||
set_global_assignment -name VERILOG_MACRO "AX_PORT=1"
|
||||
set_global_assignment -name VERILOG_MACRO "SER_FIFO_ALTERA=1"
|
||||
set_global_assignment -name VERILOG_MACRO "SPI_TIMEOUT_1024=1"
|
||||
|
|
|
|||
|
|
@ -137,6 +137,6 @@ quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[4]" has no
|
|||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[5]" has no driver
|
||||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[6]" has no driver
|
||||
quartus/thhor_crs.map.rpt: Warning (13040): bidirectional pin "P33[7]" has no driver
|
||||
quartus/thhor_crs.map.rpt:Info: Quartus Prime Analysis & Synthesis was successful. 0 errors, 237 warnings
|
||||
quartus/thhor_crs.map.rpt:Info: Quartus Prime Analysis & Synthesis was successful. 0 errors, 238 warnings
|
||||
quartus/thhor_crs.sta.rpt:Warning (18236): Number of processors has not been specified which may cause overloading on shared machines. Set the global assignment NUM_PARALLEL_PROCESSORS in your QSF to an appropriate value for best performance.
|
||||
quartus/thhor_crs.sta.rpt:Info: Quartus Prime Timing Analyzer was successful. 0 errors, 1 warning
|
||||
|
|
|
|||
91
src/dose.py
91
src/dose.py
|
|
@ -128,7 +128,7 @@ class dose_cmd(uart.uart):
|
|||
d = bytes(d)
|
||||
if s is None:
|
||||
s = len(d)
|
||||
d = struct.pack("<HBB", a,s,ccp) + d + b'\0\0\0\0\0\0\0\0\0\0\0\0'
|
||||
d = struct.pack("<HBB", a,s,ccp) + d + bytes(12)
|
||||
cc, nn, dd = self.cmd(c, d[:16])
|
||||
if dd and nn:
|
||||
aa,ss,cc = struct.unpack("<HBB", dd[:4])
|
||||
|
|
@ -139,6 +139,9 @@ class dose_cmd(uart.uart):
|
|||
return name, d
|
||||
return cc, nn, dd
|
||||
|
||||
def peek_byte(self, a):
|
||||
return self.peek(a)[-1][0]
|
||||
|
||||
def more(self, flags=b''):
|
||||
return self.cmd(self.last_cmd + b'=' + flags)
|
||||
|
||||
|
|
@ -371,6 +374,92 @@ class dose_cmd(uart.uart):
|
|||
print(f"Power was {("off", "ON")[r[1]]}", file=sys.stderr)
|
||||
return r
|
||||
|
||||
def fpga_reset(self):
|
||||
return self.cmd("C@")
|
||||
|
||||
FPGA_FLGS = {
|
||||
"ABORT": 0x01,
|
||||
"ABORTED": 0x10,
|
||||
"BUSY": 0x20,
|
||||
"SUBMITTED": 0x40,
|
||||
"CONFIG": 0x80,
|
||||
"NOOP": 0x8000,
|
||||
}
|
||||
|
||||
def fpga_cmd(self, c, read=0, wait=0, flags=()):
|
||||
n = len(c) & 0xe
|
||||
if n != len(c):
|
||||
raise ValueError(f"FPGA command must be even 2…14 bytes {c!r}")
|
||||
n |= flags2int(self.FPGA_FLGS, flags)
|
||||
z = read << 1
|
||||
if wait:
|
||||
if wait > 7 or z > 14:
|
||||
raise ValueError("FPGA cannot wait-read more than 14 bytes")
|
||||
z |= wait << 4
|
||||
z |= 1
|
||||
z |= n >> 8
|
||||
n &= 0xff
|
||||
c = bytes((n, z)) + c + bytes(14)
|
||||
r, e, d = self.cmd("C", c[:16])
|
||||
s = int2flags(self.FPGA_FLGS, d[0])
|
||||
print(f"FPGA cmd status {s!r}", file=sys.stderr)
|
||||
return d
|
||||
|
||||
def fpga_config(self, filename="../fpga/quartus/thhor_crs.rbf"):
|
||||
self.fpga_reset()
|
||||
n = 0
|
||||
nn = 0
|
||||
with open(filename, "rb") as f:
|
||||
c = f.read(14)
|
||||
while c:
|
||||
if len(c) & 1:
|
||||
c += b'\0'
|
||||
d = fpga_cmd(c, flags="CONFIG")
|
||||
if d[0] & self.FPGA_FLGS["SUBMITTED"]:
|
||||
n += len(c)
|
||||
c = f.read(14)
|
||||
if n > nn + 1024:
|
||||
if ~self.peek_byte("VPORTA_IN") & 0x10:
|
||||
raise FPGA_Error("nSTATUS went low during config")
|
||||
print(f"{n} bytes sent", file=sys.stderr)
|
||||
nn += 1024
|
||||
return n
|
||||
|
||||
def icmd(self, c, p=None, r=2):
|
||||
w = [c | 0x8000]
|
||||
if p is not None:
|
||||
w[0] |= 0x4000
|
||||
w.append(p)
|
||||
if r:
|
||||
w.extend([0x8001]*(r-1))
|
||||
w.append(0)
|
||||
d = struct.pack(f">{len(w)}H", *w)
|
||||
print(f"icmd → {[f"{ww:04x}" for ww in w]}")
|
||||
d = self.fpga_cmd(d)
|
||||
r = struct.unpack(f">{len(w)+1}H", d[:2*len(w)+2])
|
||||
print(f" ← {[f"{rr:04x}" for rr in r]}")
|
||||
return r
|
||||
|
||||
def flags2int(FLAGS, flags):
|
||||
r = 0
|
||||
if isinstance(flags, int):
|
||||
return flags
|
||||
if isinstance(flags, str):
|
||||
return FLAGS[flags]
|
||||
for f in flags:
|
||||
if isinstance(f, int):
|
||||
r |= f
|
||||
else:
|
||||
r |= FLAGS[f]
|
||||
return r
|
||||
|
||||
def int2flags(FLAGS, flags):
|
||||
r = []
|
||||
for f in FLAGS:
|
||||
if flags & FLAGS[f]:
|
||||
r.append(f)
|
||||
return r
|
||||
|
||||
if tty:
|
||||
tty = dose_cmd(tty, baud)
|
||||
tty._export(globals())
|
||||
|
|
|
|||
33
src/fpga.c
33
src/fpga.c
|
|
@ -22,36 +22,37 @@ void fpga_reset()
|
|||
|
||||
void fpga_cmd(struct fpga_cmd *c)
|
||||
{
|
||||
uint8_t n = c->n;
|
||||
uint8_t z = c->z;
|
||||
if (fpga_reset_poll()) {
|
||||
c->n |= 0x20; // busy flag
|
||||
c->n = n | fpga_busy;
|
||||
return;
|
||||
}
|
||||
if (c->n & 1 && spi_abort()) {
|
||||
c->n |= 0x10; // aborted flag
|
||||
if (n & fpga_abort && spi_abort()) {
|
||||
c->n = n | fpga_aborted;
|
||||
return;
|
||||
}
|
||||
else if (spi_busy_p()) {
|
||||
c->n |= 0x20; // busy flag
|
||||
c->n = n | fpga_busy;
|
||||
return;
|
||||
}
|
||||
c->n &=~ 0x10; // not busy
|
||||
if (c->n & 0x40)
|
||||
c->n = n & ~fpga_busy;
|
||||
if (n & fpga_submitted)
|
||||
return;
|
||||
c->n |= 0x40; // submitted flag
|
||||
uint8_t n = c->n & 0x0e; // send up to seven cmd words
|
||||
uint8_t z = c->z & 0x7e; // and up to 63 zeros
|
||||
spi_select(0);
|
||||
spi.zero = c->n & 0x80; // send nop: 0x8080 (please), or zeros
|
||||
spi.csize = n;
|
||||
c->n = n | fpga_submitted;
|
||||
|
||||
spi_select(n & fpga_config ? SPI_CONFIG : 0);
|
||||
spi.csize = n &= fpga_size;
|
||||
spi.zero = z & 0x80; // send 0x0000 or 0x8080
|
||||
spi.cmd = c->d;
|
||||
spi.rdata = c->d;
|
||||
if (c->z & 0x80) {
|
||||
spi.isize = n + z>>3 & 0x0e; // ignore cmd ± (z[6:4])
|
||||
spi.zsize = spi.rsize = z & 0x0e; // read x[3:1] words
|
||||
if (z & fpga_wait_nonzero) {
|
||||
spi.isize = n + (z>>3 & fpga_size); // ignore cmd ± (z[6:4])
|
||||
spi.zsize = spi.rsize = z & fpga_size; // read x[3:1] words
|
||||
spi.mask = 0xff; // start reading at the first nonzero byte after cmd
|
||||
}
|
||||
else {
|
||||
spi.zsize = z; // send z zeros/nop after cmd
|
||||
spi.zsize = z &= 0x7e; // send z zeros/nop after cmd
|
||||
spi.rsize = 14; // save the last 7 words returned
|
||||
if (n + z > 14)
|
||||
spi.isize = n + z - 14;
|
||||
|
|
|
|||
11
src/fpga.h
11
src/fpga.h
|
|
@ -7,6 +7,17 @@ struct fpga_cmd {
|
|||
uint8_t d[14];
|
||||
};
|
||||
|
||||
enum fpga_flags {
|
||||
fpga_abort = 0x01,
|
||||
fpga_size = 0x0e,
|
||||
fpga_aborted = 0x10,
|
||||
fpga_busy = 0x20,
|
||||
fpga_submitted = 0x40,
|
||||
fpga_config = 0x80,
|
||||
|
||||
fpga_wait_nonzero = 0x01,
|
||||
};
|
||||
|
||||
void fpga_reset();
|
||||
uint8_t fpga_reset_poll();
|
||||
void fpga_cmd(struct fpga_cmd *c);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue