From DaqWiki
Jump to navigation Jump to search

VME-PPG32 - pulse pattern generator VME FPGA board


  • [1] VME-PPG32 Rev0 (REA 198) project page on edev.triumf.ca
  • [2] VME-PPG32 Rev1 (REA 198) project page on edev.triumf.ca
  • [3] VME-PPG32 Rev2 (REA 198) project page on edev.triumf.ca
  • [4] Rev0 board schematics on edev site
  • [5] Rev1 board schematics on edev site
  • [6] Rev2 board schematics on edev site
  • File:VME-PPG32 Rev1.pdf Rev1 board schematics, local copy
  • File:VME-PPG32 Rev2.pdf Rev2 board schematics, local copy

VME-PPG32-IO32 firmware: (IO32 functions, no PPG functions)

VME-PPG32 VME CPLD firmware: (VME address decoder)

VME-PPG32 firmware: (PPG function)

  • [10] Current PPG firmware Source/binary

General characteristics

Available hardware

  • Altera cyclone 3 FPGA: EP3C40Q240C8
  • Serial flash for FPGA configuration: Altera EPCS16
  • VME interface: VME-D[31..0] bidirectional, VME-A[23..0] input only, DTACK output, no BERR, no RETRY/RESP. VME-A[31..20] input only connected only to address decoder FPGA (Altera MAX-something CPLD). This permits all single-word transfer modes, 32-bit DMA (BLT32) and 2eVME DMA (only drives D-lines, but still faster than BLT32). 64-bit DMA (MBLT64) and 2eSST are impossible.
  • 32 NIM outputs
  • 4 NIM inputs
  • 32 "NIM output" LEDs
  • 4 "NIM input" LEDs
  • 1 "VME access" LED
  • 2 output serial DAC: AD5439YRUZ, output is unipolar 0..2.5V, 10-bit accuracy.
  • Rev1 and Rev2 boards: inputs are switchable between NIM and TTL (JMP3)
  • Rev2 boards: outputs are switchable between NIM and TTL (SW1 micro switches)

PPG characteristics

  4k words (128bit words) of program memory.
  256 entry stack.
  Halt/Continue/Loop/Subroutine/Branch instructions                                     
  100Mhz clock (derived from either 50Mhz internal crystal or external 20Mhz clock input - see note 1)
  fixed 3 clk per instruction plus 32bit delay individualy programmable for each instruction
  FPGA resource Usage : 1044 LE, 500 kbits Memory

  Note 1 :
  Some modules allow an external clock frequency of 20-100MHz . Divide-downs must be programmed where external clock frequency is not 20MHz. 
  Examples of divide-down programming is shown at end of this document.

Onboard jumper settings

  • JMP1 - set to "INP" for input with 50 Ohm termination, set to "DAC" for DAC output
  • JMP2 - set to "INP" same as JMP1
  • JMP3 - set to "NIM" (pins 1-2) for NIM inputs or "TTL" (pins 2-3) for TTL inputs
  • JMP4 - "MSEL1" jumper set to "ACT" for use with the active-serial flash
  • IrqSel - leave open
  • JTAG - leave open (not a jumper block!)
  • SW1..3 - VME base address selectors (see below)

Firmware update procedure

(note1: right now the PPG firmware update procedure is unnecessary complicated because there is no ppg.pof file in the PPG firmware distribution version "1mar12" and the PPG firmware does not include the Altera active-serial programmer block.)

(note2: VME-PPG32-IO32 firmware (sof file) is required to update the PPG firmware)

Update using USB-Blaster and jic file

  • use Quartus programmer to burn the jic file through the EP3 active-serial flash loader:
  • start Quartus programmer (tools->programmer)
  • say "auto detect" - EP3, EPM1270 and EPM3032A should be detected
  • attach VME-PPG32.sof to the EP3 part (context menu "change file")
  • select "program"
  • say "start"
  • observe that 2 "red" LEDs have turned on on the PPG board (40MHz clock on outputs 4 and 20).
  • say "auto detect"
  • an "EPCS16" part should show up attached to the EP3.
  • attach ppg.jic to the EPCS16 part
  • select "program"
  • say "start"
  • observe progress bar go from 0 to 100% in about 2 minutes.
  • PPG firmware is now loaded into the board
  • cycle the power on the board to reboot into the PPG firmware
  • when running the PPG firmware, all LEDs are off after reboot.

Update using VME flash programmer

(note: VME flash programmer interface does not work in ppg firmware version "1mar12").

  • obtain the latest copy of srunner_vme (follow instructions here VME-NIMIO32#Firmware_update_procedure) (srunner_vme.cxx svn rev 214 or newer for jic support)
  • ./srunner_vme_gef.exe -program -16 ppg.jic 0x100024
  • reboot the PPG

(note: the above does not work: b) srunner_vme treats 0x10xxxx is an A24 address, but PPG firmware does not respond to A24 addresses; c) the active serial interface does not seem to work anyway)

(note: the reboot function is not available in the PPG firmware)

Update using VME flash programmer when running VME-PPG32-IO32 firmware

  • ./test_VMENIMIO32_gef.exe --addr 0x100000 --read 0 ### to confirm VME-PPG32-IO32 firmware revision
  • ./srunner_vme_gef.exe -program -16 ppg.jic 0x100020
  • ./test_VMENIMIO32_gef.exe --addr 0x100000 --reboot ### PPG will stop responding
  • ./test_a32.exe 0x100000 ### should read 0x00000000 (NOT 0xFFFFFFFF)

VME interface

VME A32/D32 access only. Rotary switches SW1, SW2 and SW3 set the upper 12 bits of the address. VME registers are listed in the table below.


Number Address Name Access Description
0 0x00000 CSR RW Control/Status Register
1 0x00004 Test RW Test Register
2 0x00008 Addr RW Program Address Register
3 0x0000C Inst_Lo RW Instruction Register Part 1/4
4 0x00010 Inst_Med RW Instruction Register Part 2/4
5 0x00014 Inst_Hi RW Instruction Register Part 3/4
6 0x00018 Inst_Top RW Instruction Register Part 4/4
7 0x0001C Inv_Mask RW Output Inversion Mask
8 0x00020 Version R Firmware Version Register
9 0x00024 Flash RW Serial Flash Control Register
10 0x00028 Serial R Serial Number Register
11 0x0002C Hardware R hardware Identification Register
12 0x00030 clock Control RW Clock Control Register
CSR Register (0x00000)

The first 5 bits control the ppg, the remaining 26 bits provide read-only status information. (writes to the 26 bits of status information are ignored, and overwritten on the next status update)

CSR Description
Bit Name Access description
0 Run R/W Run Control/Status
1 Ext-Clk-Toggle W Toggles between PPG external and internal Clk
2 Ext-Start R/W 1=Ext-PPG Start, 0=Int-PPG Start
3 PPG-Reset R/W 1=Reset, 0=Normal operation
4 Test-Mode R/W 1=Test Mode, 0=Normal operation
16 Ext-Clk-Sel R 1= External clock is selected, 0 = Internal clock selected
17 Ext-Clk good R 1= External clock is connected and is "good", 0= external clock not connected or is "bad"
?-31 Status R Readback of PC, SP, Current Delay Counter

RUN bit: Writing 1 here instructs the ppg to begin executing its program, reading this bit returns 1 if the program is still running, or 0 if halted.

Ext_Clk bit: Writing an edge here toggles the ppg logic between the internal and external CLK (connected to Nim_Input[3]). The VME interface always uses the internal clock. Note that the correct divide-down must be programmed unless external clock is the same frequency (i.e. 10MHz) as internal clock.

Ext_Start bit: Writing 1 here disables the CSR-Run-bit-start. (Reading this bit still returns the correct status), and switches control to the External Start input (NIM_INPUT[4])

Reset bit: Set bit to Reset PPG. Stops PPG pgm even if executing a long delay. Does NOT do a full reset to power-up condition. Bit must be cleared after Reset or module will not operate.

Test-Mode bit: Set bit to enable Test Mode. When Test Mode is enabled, inputs 1 and 2 become output the internal PPG clock and actual clock PPG is using, respectively. If internal clock is set, inputs 1 and 2 output identical clocks. If external clock is set, and the external clock is "good", input 1 will not change, but input 2 will show the external clock frequency. If Test-Mode bit is cleared, Normal Mode is enabled, where inputs 1 and 2 act as regular inputs.

Ext-Clk-Sel: If bit is set, external clock is selected and LED 4 will be lit. If clear, internal clock is selected

Ext-Clk Good: If bit set: external clock is connected to Nim_Input[3] and "good", LED 2 will be lit. If clear: external clock is either not connected or "bad".

Test Register (0x00004)

Simple Test Register - Value Written is preserved and can be read back.

Address Register (0x00008)

Sets PPG Program Memory Address - next instruction will be written to this location. Also when program is started, execution begins from this address. Also in test-Mode, the NIM/LED outputs follow the state of this register.

Instruction Registers (0x0000C - 0x00018)

Registers to hold the 128bit Program Instructions. Writing the Upper register triggers the storing of the entire 128bit instruction to the address currently in the address register.

The instructions format is as follows ...

Instruction Format
Bits 0-31 Bits 32-63 Bits 64-95 Bits 96-115 Bits 116-117 Bits 118-127
32 Output Set Bits 32 Output Clear Bits 32bit Delay Count 20bit Data 4bit instruction type Ignored

The 32bit delay count at 100Mhz gives maximum delay of 10 seconds per instruction.

  The instruction types are ... 
  0 - Halt
  1 - Continue
  2 - new Loop        ( 20 bit data used for count - i.e. maximum 1 million )
  3 - End Loop
  4 - Call Subroutine ( 20 bit data used for address )
  5 - Return from subroutine
  6 - Branch          ( 20 bit data used for address )
Output Inversion Mask (0x0001C)

32 individual inversion bits (1 per output) a 1 inverts the state of that output.

Firmware Version (0x00020)

Returns the 32bit unix timestamp corresponding to the date this firmware was compiled.

Serial Flash Control (0x00024)

Used for reading/Writing to the Configuration Flash device (Reading/Updating firmware)

Serial Number (0x00028)

Returns the module serial number, and Board revision (if set) or 0xdead

hardware Type (0x0002C)

Returns a 32 bit description of this hardware - which should confirm the identity of this module as a vme-ppg32

Clock Control (0x00030)

Set PLL parameters applied to external clock input. Default parameters are for 20Mhz External Clock, and multiply this by 5 to get 100Mhz ppg clock.

Register Contents as follows ...

Instruction Format
Bits 30-28 Bits 26-24 Bits 23-20 Bits 16-8 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Phase Counter Select Counter Parameter Counter Type 9 bit Data PLL Reset Up/Down PhaseStep Write Parameter reconfigure Control Trigger

The Control Trigger Bit [bit 0] enables the four control signals in bits 1,2,3,5, and needs to be toggled from off to on, to apply these 4 signals.

On rising edge of control trigger ...

  Phasestep=1       => clock phase is adjusted by 1 unit, in the direction selected by "Up/Down" [bit 4: 1=up,0=Down]
  Write Parameter=1 => 9bit-Data, Counter-Type and Counter-Param are written into the PLL reconfiguration registers
  Reconfigure=1     => PLL is reconfigured with the parameters currently in its reconfiguration registers
  PLL-Reset=1       => PLL is reset

PhaseCounterSelect ...

  0 => All Clocks
  1 => M ?
  2-6 => Clock 0-4

phasestep is applied immediately (to clocks selected by PhaseCounterSelect), and does not require a reconfiguration or reset.

The parameters below need to be written (with writeparameter=1), and then require a reconfiguration to be applied.

Counter-Parameter ...

  0: HighCount [For VCO this parameter is: PostScale K=2 Yes/No]
  1: LowCount
  4: Bypass
  5: Mode Odd/Even

Counter-Type ...

  0: N
  1: M
  2: Cp/LF
  3: VCO
  4-8: Clock 0-4
  9-D: Clock 5-9 (Stratix Only)
  E-F: Invalid

Clock frequencies are defined by ...

  VCO Frequency = Fin * M/N
  The individual clock outputs [clock0-4] are given by ... VCO / C0-C4
  Each of M,N,C0-C4 are the sum of a high and low count.
  Note - can get 50% duty cycle with odd count by setting mode=odd with high=low+1
  Each counter can be bypassed by setting bypass=1 (=> Scale=1)

Limits etc ...

  Fin  =   5 -  472 Mhz
  Fvco = 600 - 1300 Mhz
  Lock Time < 1ms

Examples ...

  For Fin = 20Mhz [defaults settings on pwerup]
  Fvco=1200,K=2 => 600Mhz .. M=30, N=1(Bypassed), C0=6(3+3) Fin=20Mhz => C0=100Mhz
  For Fin=100Mhz [and M=30,N=1,C0=6] Need to Change N to 5 ...
  Write:   0x00000305   0  0x01000205  0  0x05000105      0    0x04000005         0  0x3          0
           type=0,hi=3     type=0,lo=2    type=0,mode=odd      type=0,bypass=no      Reconfigure
  Change back from 100 to 20 - need to change N to bypassed ...
  write:   0x04000105        0    0x3          0
           type=0,bypass=no       Reconfigure
  For Deap 62.5 Mhz (20*25/8)  Fvco=1000,k=2=>500 M=8 N=1 C0=5 gives 100Mhz
                               Fvco=1000,k=2=>500 M=8 N=1 C0=8 gives 62.5Mhz
    • Note - to help debug clock setting problems the internal clock can be viewed on ppg output #1 (and the 20 Mhz internal clock on output #0), if the test-mode bit is set in the CSR [bit 4]. It is then possible to check the ppg clock is locked and at the correct frequency (100Mhz), and see the relation between the external and internal clocks.

Front Panel

NIM Inputs

  The Input assignments are (as labelled on front panel) ...
  4 - External Start - Rising Edge starts, multiple starts are (or should be) ignored.
  3 - External Clock (20Mhz, internally scaled - 100Mhz)
  2 - Unassigned
  1 - Unassigned

Input LEDs

  The Input LED assignments are (as labelled on front panel) ...
  4 - Clock setting (Lit => External Clk)
  3 - NimIn[2] status
  2 - External Clock Good indicator (Lit => Clock is good)
  1 - Program Running

Test Software

c-shell script to run 2 nested loops

  set dec_hex=( 0x0  0x1  0x2  0x3  0x4  0x5  0x6  0x7  \
                0x8  0x9  0xa  0xb  0xc  0xd  0xe  0xf  \
                0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 \
                0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f \
                0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 )
  # dly4,loop4,dly3,loop6,dly2,end,end
  set inst=(                                                \
     0xff  0x00  0x4  0x100000   0x0   0x0   0x0  0x200004  \
     0x1   0x1   0x3  0x100000   0x0   0x0   0x0  0x200006  \
     0x2   0x2   0x2  0x100000   0x0   0x0   0x0  0x300000  \
     0x0   0x0   0x0  0x300000   0x0   0x0   0x0  0x000000  )
  set i=0
  set j=0
  while( $i < $#inst )
     @ j++; vme_poke -a VME_A32UD -A 0x00100008 -d VME_D32 $dec_hex[$j]
     @ i++; vme_poke -a VME_A32UD -A 0x0010000c -d VME_D32 $inst[$i]
     @ i++; vme_poke -a VME_A32UD -A 0x00100010 -d VME_D32 $inst[$i]
     @ i++; vme_poke -a VME_A32UD -A 0x00100014 -d VME_D32 $inst[$i]
     @ i++; vme_poke -a VME_A32UD -A 0x00100018 -d VME_D32 $inst[$i]
  # start program (from addr 0)...
  vme_poke -a VME_A32UD -A 0x00100008 -d VME_D32 0x0
  vme_poke -a VME_A32UD -A 0x00100000 -d VME_D32 0x1

c-shell script to set divide-downs for 100MHz frequency

This would be used with an external frequency input of 100MHz

 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x00000305   # set hi counter to 3
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x01000205   # set lo counter to 2
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x05000105   # set mode counter to odd 
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x04000005   # set counter bypass to 0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x3
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0

c-shell script to set divide-downs for 10MHz frequency

This would be used when returning to the internal frequency of 10MHz :

 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x04000105  # set counter bypass to 1
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0         # prepare for next cmd
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x3         # reconfig clock
 vme_poke -a VME_A32UD -A 0x00100030 -d VME_D32 0x0         # prepare for next cmd

Procedure for newly assembled board startup and test

(note1: VME-PPG32-IO32 firmware is used to test the board)

(note2: TTL inputs and outputs are not tested)

(note3: DAC outputs are not tested)

(note4: shorts between NIM outputs are not tested)

  • check the board for shorts of power to ground. Use multimeter in "ohm" mode, measure resistance between "gnd" and "1.2V", "-3.3V", "VME +12V", 2.5V" and "3.3V". None should measure 0 ohm.
  • set VME address jumper A20-23 to "1", jumpers A24-27 and A28-31 to "0"
  • set inputs and outputs to "NIM" mode
  • connect JTAG USB blaster
  • power up the board (standalone or in a VME crate)
  • start Quartus programmer
  • select correct USB blaster
  • run "auto detect", 3 devices should be detected: EP3C40Q240 (Cyclone3 FPGA), EPM1270 (parallel flash loader CPLD), EPM3032AT44 (VME address decoder CPLD)
  • flash the VME address decoder pof file into the EPM3032 part (get pof file from here: https://ladd00.triumf.ca/viewvc/daqsvn/trunk/VME-NIMIO32/MAX3000A_Addr_decode/VME_Addr_decode.pof?view=log)
  • (do not do this) flash the CFI parallel flash loader into the EPM1270 part (get pof file where?!?)
  • load the VME-PPG32-IO32 firmware sof file into the EP3 part (get sof file here: https://ladd00.triumf.ca/viewvc/daqsvn/trunk/VME-NIMIO32/VME-NIMIO32/PPG32-Rev1/VME-PPG32.sof?view=log)
  • run "vmescan_gef.exe", it should detect the IO32 board at A24 VME address 0x00100000, data should correspond to the sof file revision date code
  • confirm VME access LED is working (flashes during vme scan).
  • confirm VME Data bus is okey: "./test_VMENIMIO32_gef.exe --addr 0x100000 --testbits 4"
  • (do not do this) follow the firmware update instructions to flash the firmware pof file using the VME flash programmer at VME-NIMIO32#Firmware_update_procedure (get VME-PPG32-IO32 pof file from here: https://ladd00.triumf.ca/viewvc/daqsvn/trunk/VME-NIMIO32/VME-NIMIO32/PPG32-Rev1/VME-PPG32.pof?view=log)
  • (do not do this) confirm FPGA reboot is working - "./test_VMENIMIO32_gef.exe --addr 0x100000 --reboot" prints 0xFFFFFFFF on the second read of firmware revision
  • test NIM inputs and LEDs: use NIM pulse generator or any NIM module inverted output, connect to each NIM input, observe that corresponding "green" LEDs is lighting up
  • test NIM outputs and LEDs: "./test_VMENIMIO32_gef.exe --addr 0x100000 --nimout 3 1 --pulsenim", observe all "red" LEDs are flashing, connect NIM outputs to NIM scaler, observe scaler counts at each LED flash
  • load PPG firmware into the active serial flash (follow instructions here: #Update_using_VME_flash_programmer_when_running_VME-PPG32-IO32_firmware
  • unplug the board from VME, wait 10 sec, plug it back in, confirm that it is detected by vmescan if running VME-PPG32-IO32 firmware or test_a32 or PPG test tools if running the PPG firmware (confirms the flash memory contents is good)

VME-PPG32-IO32 firmware

The VME-PPG32 board can run a special version of VME-NIMIO32 firmware (subproject "PPG32-Rev1" of the VME-NIMIO32 firmware). For instructions, please refer to the VME-NIMIO32 documentation.

Update 2018-Dec-05 - use /daq/daqshare/olchansk/altera/ to build this PPG32 firmware. K.O.