From 3f9a100e7c30051077f0c4231cf4f5e2fc6648ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20I=2E=20B=C3=B6ttcher?= Date: Wed, 25 Mar 2026 20:20:07 +0100 Subject: [PATCH 1/3] fpga spi_slave: longer sclk timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The µC needs about 5 µs between bytes. The 128 mclk timeout @32MHz is 4.3µs. This commit extends the timeout to 1024 mclk cycles. --- fpga/solo | 2 +- fpga/thhor_crs.qsf | 1 + fpga/thhor_crs.warnings | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/fpga/solo b/fpga/solo index 60aae89..9bbfeb3 160000 --- a/fpga/solo +++ b/fpga/solo @@ -1 +1 @@ -Subproject commit 60aae89495f05eedb48c9c1468e4c8d4dd92f79f +Subproject commit 9bbfeb3316098af16370c10355c94ed7ec06f5ee diff --git a/fpga/thhor_crs.qsf b/fpga/thhor_crs.qsf index c45be38..06f3b11 100644 --- a/fpga/thhor_crs.qsf +++ b/fpga/thhor_crs.qsf @@ -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" diff --git a/fpga/thhor_crs.warnings b/fpga/thhor_crs.warnings index 6b3a106..041d5a7 100644 --- a/fpga/thhor_crs.warnings +++ b/fpga/thhor_crs.warnings @@ -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 From a88421a781719743b7337a9b8d69da98a5842910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20I=2E=20B=C3=B6ttcher?= Date: Wed, 25 Mar 2026 20:25:15 +0100 Subject: [PATCH 2/3] avr: fpga_cmd fixes --- src/fpga.c | 33 +++++++++++++++++---------------- src/fpga.h | 11 +++++++++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/fpga.c b/src/fpga.c index aaf375b..07d549d 100644 --- a/src/fpga.c +++ b/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; diff --git a/src/fpga.h b/src/fpga.h index 165ff6e..109d992 100644 --- a/src/fpga.h +++ b/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); From 4c36c00e64545530b37de2c2d09830a54dc9849f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20I=2E=20B=C3=B6ttcher?= Date: Wed, 25 Mar 2026 20:25:48 +0100 Subject: [PATCH 3/3] python: fpga commands --- src/dose.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/src/dose.py b/src/dose.py index 88546d6..bee6fb6 100755 --- a/src/dose.py +++ b/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(" 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())