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 4in the vendor XDC -> use x4 when writing the flash.mcs. LED D3 (red) is wired toFPGA_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, pinsC8/D8per 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= pinH18(the vendor samples'sys_rst_n), SW2 =USER_KEY1= pinH17. 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:
- 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.
- 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. - 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_*.tclworkflow 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 onR2(MRCC), keysH18(SW1) /H17(SW2) active-low, LEDsC8/D8active-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):
led-test/:vivado -mode batch -source build.tcl(synth + impl + bitstream + JTAG program in one run). PASS =led_n[0]blinks at 1 Hz andled_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).mem-test/(port of../basys3/mem-test/, 50 MHz MMCM -> 16.667 MHz, UART TX is an internalmark_debugnet): 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.