Skip to content

QMTECH XC7A35T board - manual & vendor-sample analysis

Full path: Verilog/fpga/qmtech-a35t/docs/board-notes.md

Analysis of QMTECH_XC7A35T_SDRAM-User_Manual_V01.pdf (all 14 pages, V1.0 formal release 2023-08-19), the board schematic QMTECH_XC7A15T_35T_50T_CSG325_SDRAM_V1.pdf (4 sheets, rev B 2023-07-13; sheet 2 = clock/keys/LEDs/headers, sheet 3 = SDRAM, sheet 4 = config/JTAG + full FPGA-pin-to-SDRAM-net map) and the vendor sample projects from https://github.com/ChinaQMTECH/QMTECH_XC7A15T_35T_CSG325_CORE_BOARD. Schematic cross-checks done: SDRAM pin map on sheet 4 matches the vendor sample XDC pin-for-pin; R2 (CLK_50M) is IO_L13P_T2_MRCC_34, a clock-capable MRCC pin; LED nets are USER_LED0=D8, USER_LED1=C8.

User manual - facts that matter for the ND-120 port

  • Tools/flow (2.1): Vivado 2018.2+, "Xilinx USB platform cable, Mini USB cable for power supply" - the manual itself states the Mini USB is power-only. The 5 V rail also reaches JP2/JP3 pin 1 (feed the board from the header is possible; so is accidentally shorting 5 V - see header note below).
  • Power (2.2.1): Mini USB 5 V -> TPS563201 -> 3V3 (all I/O banks are 3V3, hence LVCMOS33 everywhere); NCP1529 -> 1V0 core (max 1 A) and 1V8 AUX. LED D2 = 3.3 V present.
  • Config (2.2.2): N25Q(L)064A SPI flash, mode pins strapped M0:M1:M2 = 1:0:0 = SPI master boot at power-on. BITSTREAM.CONFIG.SPI_BUSWIDTH 4 in the vendor XDC -> use x4 when writing the flash .mcs. LED D3 (red) is wired to FPGA_DONE = configuration-loaded indicator.
  • Clock (2.2.3): 50 MHz oscillator SG-310SCN (10 ppm) on pin R2.
  • JTAG (2.2.4): 6-pin header: TCK/TDO/TDI/TMS + GND + VREF, direct to the FPGA. Platform Cable flying-lead colors documented in Figure 2-3.
  • LEDs (2.2.5): only 2 user LEDs (D1 = USER_LED0, D4 = USER_LED1, pins C8/D8 per the sample XDCs), active-low (3V3 -> 1k -> LED -> pin). D2/D3 are power/DONE, not user-drivable. The "4 user LEDs" line in the kit overview counts all four.
  • Keys (2.2.7 + schematic sheet 2): SW3 = PROG_B (reconfigure from flash), SW1 = USER_KEY0 = pin H18 (the vendor samples' sys_rst_n), SW2 = USER_KEY1 = pin H17. All active-low with 4.7k pull-ups.
  • Headers JP2/JP3 (2.2.6): 2x25, 2.54 mm, 88 non-multiplexed user I/Os total, length-matched per the kit overview. Net names are IO_<pin> so the schematic gives FPGA pins directly. Pin 1 = USB_5V and pin 2 = 3V3 on both headers.
  • SDRAM (2.2.8): W9825G6KH-6: 16-bit data bus, 13-bit address bus (A[12:0]), 2 bank pins -> 4 banks x 8192 rows x 512 cols x 16 bit = 32 MB. Both DQM lanes and CKE wired. Control lines have 4.7k pull-ups to 3V3 (safe idle state during FPGA configuration).

Vendor SDRAM sample (project_SDRAM_XC7A35T_CSG325.zip) - is there magic?

Short answer: no controller worth reusing, but three usable facts.

What it is (SDRAM_test.v + test.v): a fixed 113-step state_cnt sequence, not a controller - no arbitration, no periodic refresh, no tri-state read path (the Data bus is driven from a task argument and read back through a continuous assign), and it tests exactly one location (bank 0, row 0, col 200) with 0x5555/0xAAAA, LED low on match. The SDRAM clock is generated by a fabric register dividing a 200 MHz MMCM output by 2 (no ODDR clock forwarding). An ILA core observes the pins - precedent for ILA-over-JTAG on this board.

The three usable facts:

  1. Timing that the vendor warrants on this exact PCB: SDCLK = 100 MHz at CAS latency 2, with tRP >= 20 ns and tRFC >= 66 ns spelled out in the sequence comments. Our Tang bridge derivative needs ~66 MHz - comfortable margin on the same chip family and traces.
  2. Init sequence for the W9825G6KH-6: >=200 us NOP wait is absent here (the 8-NOP prelude only works because reset is held long by the human); the real init in sdram18.v (precharge-all -> 2x auto-refresh -> load mode register) matches what the sample does, so no surprises.
  3. Mode register value 547 (0x223): BL=8 sequential, CL=2, A9=1 = single-location write burst. Reads burst 8, writes are single-word. For our burst-of-2 bridge we will instead use BL=2 (A[2:0]=001, A9=0) or BL=1 with two explicit writes - decide in the bridge testbench.

What we take instead: the 18-bit nand2mario controller (../../tang-nano-20k/sdram-bridge/sdram18.v), hardware-proven on the Tang's SDRAM, re-parameterized for a 16-bit bus with two beats per 18-bit ND word.

Vendor LED sample (project_led_XC7A35T_CSG325.zip)

Simple 1 Hz alternating blinker on C8/D8, reset on H18, sys_clk on R2 - source of the pin facts in ../board-pins.xdc. Ships with a netlist-inserted ILA on the counter, again confirming the ILA-over-JTAG workflow.

Board setup and smoke tests (from the 08-JUL-2026 bring-up handoff)

Merged here 28-SEP-2026 from HANDOFF-qmtech-a35t-bringup.md (superseded 04-SEP-2026 by ../README.md; git history keeps it). Hardware facts, verified against the manual and the schematic in this folder:

  • Same FPGA die as the Basys3, part xc7a35tcsg325-1 (CSG325 package), plus 32 MB SDRAM, which removes the Basys3's 24 KB BRAM main-memory limit.
  • Mini USB = power only (QMTECH omits the FTDI bridge Digilent boards have). Everything else goes through a Xilinx Platform Cable USB II on the 6-pin JTAG header: programming, SPI flash, ILA, VIO. Vivado's hardware manager sees it like the Basys3's onboard JTAG, so the ../basys3/ila_*.tcl workflow carries over.
  • No UART on the board. Console options considered: a BSCANE2 JTAG-UART bridge, VIO character poking, or 2 header pins + an external 3.3 V USB-serial dongle (the shipped build uses header JP3 - see ../../QUICKSTART-qmtech-a35t.md).
  • Confirmed pins (schematic sheet 2/4; full map in ../board-pins.xdc): 50 MHz oscillator on R2 (MRCC), keys H18 (SW1) / H17 (SW2) active-low, LEDs C8/D8 active-low, 39 SDRAM pins. On headers JP2/JP3, pin 1 = 5 V, pin 2 = 3V3.

Smoke tests, for when the full build fails in a way that makes the board itself the suspect (Windows host, board powered from the Mini USB, Platform Cable on the JTAG header):

  1. led-test/: vivado -mode batch -source build.tcl (synth + impl + bitstream + JTAG program in one run). PASS = led_n[0] blinks at 1 Hz and led_n[1] lights while SW1 (H18) is held. A wrong blink rate means the clock assumption is wrong; a failed program means cable/target (check that hw_server sees the cable).
  2. mem-test/ (port of ../basys3/mem-test/, 50 MHz MMCM -> 16.667 MHz, UART TX is an internal mark_debug net): LEDs fast blink = running, 1 Hz blink = PASS, both solid = FAIL. Same die as the Basys3 where this passes, so a FAIL points at the board (clock/MMCM), not the logic. The iverilog sim (mem-test/sim/, -DNO_MMCM) passes.