-
Notifications
You must be signed in to change notification settings - Fork 0
Digital Pattern Generator DPG1 Guide
Welcome to the Digital_Pattern_Generator_DPG1 wiki!
The firmware emulates a virtual serial device, and understands currently (as of svn-4) the following commands:
CONFIG <value> STATUS? WRITEW <v1> <v2>.... *IDN?
This interface is not very nice yet, but it allows to program the table with text-based code or scripts.
CONFIG? queries the last configuration value NIMOUT <value> selects mode for NIMOUT output 0: outline[24], 1: delayed outline[24], 2: masterclock, 3: refclk NIMOUT? queries setting of NIMOUT HOOKS <value> sets the value of the two hook bits (value ranges from 0...3) HOOKS? queries last value set for hooks PARAM <v0> <v1>.... write 16 bit parameters in parameter registers, starting from register 0 TTL sets the input sensitivity to TTL level (positive polarity) NIM sets the input sensitivity to NIM level (negative polarity) LEVEL? queries the input polarity (0: NIM, 1: TTL) TSTAT? extracts the readback pattern in outline[31:28] from the status word INSTAT? extracts the status of the input lines from the status word HOLDADR forces the row address pointer to the startaddress value (0 by default) RUN releases the table address pointer and enables the sequencer RAMPROG swiches to ram programming mode (as opposed to parameter writing)
Use the Python based library for a quick start to the device. Otherwise, refer to the guide below to write a series of WRITEW four-word command to program the sequence of I/O. There are four 16-bit words per WRITEW command, each with their own function.
Before writing the WRITEW words, one can first set the state and running parameters of the device, with CONFIG and PARAM command. They are described below.
This register determines the overall behavior of the device. Its bits have the following meaning:
Bits | what | interpretation | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
9:8 | tablehooks | these two bits can be used in conditional jumps in the table entry to redirect the sequence to different branches | ||||||||||
7:6 | clockselect |
these two bits determine the master clock selection for the table sequencer according as shown below:
|
||||||||||
5:4 | auxlineselect |
Determines the NIM output line on the main board according to the following selection:
|
||||||||||
3 | parameterwrite | if set to 1, data is written to parameter register bank. When 0, data is written to the pattern RAM | ||||||||||
2 | addressreset | when set, the table address is loaded with the startaddress register content. Otherwise, the next address is generated from the table entry (direct or conditional jumps | ||||||||||
1 | level | input line discipline. 0: input are NIM levels, 1: inputs are TTL level | ||||||||||
0 | tablereset | RAM register reset; not clear if this is needed in conjunction with addressreset |
This 16 bit wide register reflects the status of the pattern generator; it can be read out at any time, with the following interpretation of the bits:
bits | What | Interpretation |
---|---|---|
10 | level | reflects the setting of the level bit (NIM:0 or TTL:1) |
9 | PLL_lock | internal PLL lock status (i.e., when set, it gives good 100 MHz ) |
8 | CLK_OK | external clock status. Is set if external frequency is between 9 and 11 MHz |
7:4 | inlines | reflects the status of the four input lines, corrected for the respective discipline (TTL or NIM); 1 means line is active |
3:0 | patternstatus | reflects the pattern status lines stored in each table entry |
There are 8 words of 16 bit wide parameter registers which can be set when the PARAM
line if the status register is set. The parameters are written consecutively to the write address, which is reset to 0 at a write to the configuration register, and incremented by 1 after each 16 bit word write. The following parameters are currently implemented:
Write address | Register | Comment |
---|---|---|
0 | tablestart |
Start address of the RAM. When the addressreset bit in the configuration register is set, the value of this register is loaded in the read address pointer of the lookup table.
|
1...4 | extcntload | Reload value for the four counters that get decremented through external events |
5..8 | intcntload | Reload value for the four internal counters that get decremented through a special command. This can be used to set up loops |
This is an internal RAM bank, organized in 512x64 bits for the table replay, and in 2048x16 entries for writing data to it. The content is written consecutively to a write address, which is reset to 0 at a write to the configuration register, and incremented by 1 after each 16 bit word write. The table gets replayed by the internal sequencer. Write address 0...3 correspsond to table row 0, write address 4...7 to row address 1, write address 8..11 to row address 3 and so on. The bits have the following meaning:
Write addr | What | Interpretation |
---|---|---|
row*4+0 | outlines[15:0] | determines the output pattern for two of the 8-bit outputs. Port 0 represents outlines[7:0], and Port 1 represents outlines[15:8] |
row*4+1 | outlines[31:16] |
outlines[23:16] determine the Port 2 output lines. outlines[24] can be connected to the NIM output on the main board, depending on the setting auxlinesel in the configuration register.
|
row*4+2 | timelines | Determines the wait cycles before the sequencer jumps to the next address. A value of 0 means that the next table row is played after 1 master clock cycle, or 10ns for the standard 100 MHz clock. For example, an entry of 9999 corresponds to a switch to the next table row after (9999+1)*10ns = 100μsec for a 100 MHz clock. Note that the largest value is 65535, corresponding to 655.36μs duration for a table row (for a 100MHz master clock). |
row*4+3 | addresslines | Determines the next row for the table sequencer, or executes a special command (in which case, the row address following the current one is chosen as next row). |
Address line interpretation: The choice of the next table entry, and some special events, are determined by the 16 bit wide addressline register in each table row. The bit pattern is interpreted as shown below:
Action | bits 15:12 | bits 11:8 | bits 7:4 | bits 3:0 |
---|---|---|---|---|
unconditional jump | 0 | next row address | ||
special command | 1 | decrement internal counter 3:0 | load internal counter 3:0 | load external counter 3:0 |
conditional jump on hook 0 | 2 | address of next row entry if tablehook[0] is set (otherwise, the next address is chosen) | ||
conditional jump on hook 1 | 3 | address of next row entry if tablehook[1] is set (otherwise, the next address is chosen) | ||
conditional jump on input line 1 | 4 | address of next row entry if inline 1 is set (otherwise, the next address is chosen) | ||
conditional jump on input line 2 | 5 | address of next row entry if inline 2 is set (otherwise, the next address is chosen) | ||
conditional jump on input line 3 | 6 | address of next row entry if inline 3 is set (otherwise, the next address is chosen) | ||
conditional jump on input line 4 | 7 | address of next row entry if inline 4 is set (otherwise, the next address is chosen) | ||
conditional jump on external counter 1 | 8 | address of next row entry if extcounter 1 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on external counter 2 | 9 | address of next row entry if extcounter 2 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on external counter 3 | 10 | address of next row entry if extcounter 3 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on external counter 4 | 11 | address of next row entry if extcounter 4 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on internal counter 1 | 12 | address of next row entry if internal counter 1 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on internal counter 2 | 13 | address of next row entry if internal counter 2 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on internal counter 3 | 14 | address of next row entry if internal counter 3 is nonzero (otherwise, the next address is chosen) | ||
conditional jump on internal counter 4 | 15 | address of next row entry if internal counter 4 is nonzero (otherwise, the next address is chosen) |
Desired pattern (time axis is not to scale):
Code to send to card, assuming a standard clock frequency of 100MHz:
# Set device to programming mode: reset table, reset RAM, program params config 13 writew 0; # basic address is 0 config 5; # switch to RAM write # This is the RAM sequence writew 1,256,9,1; # channel 1 pulse, sync pulse, 100nsec writew 0,0,989,2; # off for 9.9usec writew 2,0,9,3, 0,0,89,4, 2,0,9,5; # 2 pulses, total len 1.1usec writew 0,0,889,6; # pause for 8.9 usec writew 4,0,9,7, 0,0,89,8, 4,0,9,9, 0,0,89,10, 4,0,9,11; # 3 pulses, 2.1us writew 0,0,7789,0; # wait 77.9 usec, go back to 0 # start pattern config 0
Code to send to the card, assuming a 100MHz internal clock:
config 15; # parameter write writew 0; # reset address to 0 config 7; # write to RAM, set addr counter to 0 writew 1,256,9,1; # row 0: 100nsec, unconditional jump to row 1 writew 0,0,9,16384; # row 1: 100nsec, conditional jump to row 0 writew 1,256,49,3; # row 2: 500nsec, uncond jump to row 3 writew 0,0,9,16384; # row 3: 100nsec, conditional jump to 0 writew 0,0,39,2; # row 4: 400nsec, unconditional jump to 2 config 2; # run the sequence
The following code uses two parameter registers: One to implement a burst pulse counter, the other one to have an extended delay in multiples of 1ms:
config 13 writew 0, 0,0,0,0, 10,2; # startrow 0, no external regs, 10 pulse burst, 2x 1ms wait config 5 writew 0,0,0,4144; # row 0: load burst counter, load wait counter: 0x1030 writew 1,256,9,4352; # row 1: 100 nsec on, decrement burst cnt (0x1100) writew 2,0,9,49153; # row 2: 100 nsec off, cond jump to row 1 on nonzero cnt writew 4,0,49999,4608; # row 3: 500 usec, decrement cnt2 (0x1200) writew 8,0,49999,53251; # row 4: 500 usec, jump to row 3 on nonzero (0xd003) writew 16,0,0,0; # row 5: uncond jump to row 0 config 0; # start sequence
In this demo code, the pulse burst ends up on the NIMOUT connection, and outputs 0..4 reflect the position in different rows.
The following code measures the number of events in a 10ms wide time interval; if the number exceeds a value of 100, it switches on the NIMOUT line, and sets the table status to 1 (can be tested with TSTAT?). The code implements two such loops, and its output status reflects the finding of the last 10ms test periode. Take note that the example below uses PARAM commands and the like, instead of config commands. This works properly only as of firmware svn-9.
param 0,100,0,0,0,10; # startrow 0, 100 into ext cnt, 10 into int cnt holdadr; ramprog; # for programming pattern # Stay in this loop if counts were low (NIMOUT=0) writew 0,0,0,4113; # row 0: load int and ext counters (0x1011) writew 1,0,49999,4352; # row 1: 500 usec, decrement int cnt1 (0x1100) writew 2,0,49999,49153; # row 2: 500usec, jmp to 1 on nonzer int cnt (0xc001) writew 4,0,0,32768; # row 3: 10nsec, jump to 0 on nonzero ext cnt (0x8000) # Stay in this loop if counts were high (NIMOUT=1, tablestat=1) writew 8,4352,0,4113; # row 4: load int and ext counters (0x1011) writew 16,4352,49999,4352; # row 5: 500 usec, decrement int cnt1 (0x1100) writew 32,4352,49999,49157;# row 6: 500usec, jmp to 5 on nonzer int cnt (0xc005) writew 64,4352,0,32768; # row 7: 10nsec, jump to 0 on nonzero ext cnt (0x8000) writew 64,256,0,4; # row 8: 10ns, unconditional jump to row 4 run; # start sequence