HTR VME PRIMER for Altera versions 3E and higher

Older versions here

VME Addressing Scheme

Rev4 and Rev3 of the HTR boards have 24 VME address lines and 24 VME data lines implemented. This reduction allows us to implement VME with a non-BGA PLD, while staying in compliance with the new CMS VME standards. This document serves as a guide for the new version. Conceptually, think of the HTR as having a VME bus, and a Localbus, and an Altera ACEX which serves as a VME/Localbus interface. The devices on the Localbus are the following:

The addressing scheme is described in the following table:

VME Address bits
VME Slot
Compared to VME_GA[4:0] inverted
Localbus Device
VSR=0, XTOP=1, XBOT=2, FTOP=4, FBOT=5, ITOP=6, IBOT=7, SLB1-6=8-13
Localbus Address
Direct 1:1 mapping

Note that all VME operations will be A24 based, and the HTR will respond to VME Address Modifiers 0x39, 0x3A, 0x3D, and 0x3E.

Since there are only 7 Localbus Devices, it is easy to just construct the relevant C++ definitions by hand:
#define HTR_VSR 0x0
#define HTR_XILINX_TOP 0x8000
#define HTR_XILINX_BOT 0x10000
#define HTR_FLASH_TOP 0x20000
#define HTR_FLASH_BOT 0x28000
#define HTR_IND_TOP 0x30000
#define HTR_IND_BOT 0x38000
#define HTR_SLB_1 0x10000   //or equivalently, (SLB+7)<<15 where 1<=SLB<=8 is the SLB number
As an example, if you have a HTR in VME Slot 4, and you want to do a read or a write to Localbus address 0x20 on the TOP Xilinx, you would build the VME addressing in the following way:
  1. VME Slot: shift 0x4 19 bits to the left
  2. Localbus Device: 0x8000
  3. Localbus Address: as is

This would result in a vme address (VME_A) of
int vme_slot = 4;
int localbus_address = 0x20;
int VME_A = vme_slot<<19 + HTR_XILINX_TOP + localbus_address;

This would result in VME_A = 0x00208020

VSR Registers (VME Status Registers)

To access the HTR VSR you would set the Localbus device to VSR (device=0). The Localbus Addresses are interpreted as commands. Legal addresses are:

Name Value R/W Bits Comments
ID 0x00 R 24 Returns 0xEDCAFE, indicates HTR present in the slot
Reset 0x04 W none Causes internal reset (limited use, mostly for XILINX config reset)
Configure TOP 0x08 W none Initiates configuration of Xilinx TOP from TOP FLASH
Version 0x0C R 24 VME FPGA firmware version
Status Register 0x10 R 24 Concatenation of internal bits (see below)
Configure BOTTOM 0x14 W none Initiates configuration of Xilinx BOTTOM from BOTTOM FLASH
Test Register 1 0x18 R/W 24 Test I/O
Test Register 2 0x1C R/W 24 Test I/O
TOP XILINX FLASH CRC 0x20 R 24 Read the 24-bit CRC calculation for the TOP flash
BOT XILINX FLASH CRC 0x24 R 24 Read the 24-bit CRC calculation for the BOT flash
TOP Indirect Global Address 0x28 R/W 9

Sets the indirect global (page) register for the TOP Xilinx

BOT Indirect Global Address 0x2C R/W 9 Sets the indirect global (page) register for the BOT Xilinx
TTCrx I2C_{data[], dir, address[6:0]} 0x34 R/W 16 I2C bus to TTCrx (probably bad, missing pullup resistors)
TTCrx I2C_start 0x38 W 1 I2C bus to TTCrx (probably bad, missing pullup resistors)
TTCrx I2C_{start, busy, success, DOut[7:0]} 0x3C R 11 I2C bus to TTCrx (probably bad, missing pullup resistors)
HTR_ID 0x40 R 9 HTR ID = SN on the label

The Status Register read operation (see Status Register in table above) returns the following data:

Flash Operations

There is one HTR Flash per Xilinx FPGA (TOP and BOTTOM Flash for TOP and BOTTOM Xilinx respectively). Since we are limited to 15 bits of Localbus Addressing via VME (actually 13 since the bottom 2 VME addressing bits are not to be used), we can't write into the FLASH by mapping the VME address into Localbus address space. Instead, we will invent a set of commands to the FLASH that will control what Localbus Address the ACEX is pointing to. These commands are summarized in the following table:

Name VME_A bit R/W Bits Comment
Reset Internal Address Pointer VME_A[2] W None Resets the internal Flash address to zero
Write Data VME_A[3] W 8 Writes VME_D[7:0] into Flash using internal Address Pointer
Read Data VME_A[4] R 8 Reads one byte from Flash using internal Address Pointer, outputs onto VME_D[7:0]
Flash Reset VME_A[5] W none Reset FLASH state machine
Flash Erase VME_A[6] W none Puts Flash into Erase cycle
Increment Internal Address Pointer VME_A[7] W none Increments internal Flash address pointer by 1
Read Internal Address Pointer VME_A[8] R 21 Reads internal Flash address pointer

The sequence for programming the Flash is the following:

Note that for each VME operation, you still have to set the Localbus Device to either Flash TOP or Flash BOTTOM, and of course you have to set the VME slot number.

Localbus Indirect Addressing Operations

The Localbus inside the HTR is a 21-bit addressable bus. However,the VME address bus is restricted to 24 bits total (A24). In addition, the VME address bits 23:19 are reserved for slot identification, bits 18:15 are reserved for Localbus Device selection, and the bottom 2 bits are off limits since we are running in D32 mode. This leaves only 13 bits (14:2) for legitimate addresses. In order to make an address access that has more than 13 bits, we need another scheme. This is the origin of the indirect addressing in the HTR.

So far (as of 2004) the only "devices" inside the HTR which need more than 13 bits of address space are the Look-up Tables (LUTs) and simulated data rams (RAMS) for injecting data into the front-end of the HTR Xilinx (bypassing the TLK2501 deserializers). These are described below:

Look-up Tables (LUTS)

There are 2 types of LUTS:

Injection RAMs (RAMS)

We have the ability to inject data into the HTR to mimic raw data coming up from the Front-end boards. This will allow you to debug without the need of fiber data, if necessary.

There will be 8 RAMS per Xilinx FPGA, 1 per fiber. You write to the indirect address register of the Altera (VSR, see below) (0x28 for TOP and 0x2C for BOT) and in the low 9 bits of the VME data word you put the fiber number (from 0 to 7) + 0x180. The Altera FPGA latches these values. This will tell the Xilinx FPGA which RAM you will be reading from or writing to. Then you write to the relative address (a total of 10 bits, so there are 1024 different RAM addresses).

For example, say you want to read or write to RAM addresses for fiber 2 (8 fibers, 1 to 8) of the TOP Xilinx of the HTR in VME slot 12. The sequence is:

Then, to read from or write into any of the 1024 individual RAM addresses, you read/write to that address over VME (shifted over 2 bits to the left) with the indirect device set. So, with the above example already done (writing 0x181 to 0x600028) say you would like to write 0x5432 to RAM address 0xF, you would write the 0x5432 as VME data to VME address 0x600000 + 0x30000 + (0xF <<2) = 0x63003C.

To use this, we suggest the following sequence (which you can do inside htr):

The following .htr file (htr macro, sent via ./htr -x <file>) will set gaussians to each fiber, with a different gaussian mean and sigma 1 for all 8 fibers, then send a TTC broadcast command ("test") to get things rolling:

   slot 12   #or whatever slot you are working in
   #fiber 1 gaussian at 3 width 1
   gen 0 3 1
   #fiber 2 gaussian at 6 width 1
   fiber 2
   gen 0 6 1
   #fiber 3 gaussian at 9 width 1
   fiber 3
   gen 0 9 1
   #fiber 4 gaussian at 12 width 1
   fiber 4
   gen 0 12 1
   #fiber 5 gaussian at 15 width 1
   fiber 5
   gen 0 15 1
   #fiber 6 gaussian at 18 width 1
   fiber 6
   gen 0 18 1
   #fiber 7 gaussian at 21 width 1
   fiber 7
   gen 0 21 1
   #fiber 8 gaussian at 24 width 1
   fiber 8
   gen 0 24 1
   # now enabl the rams and put in repeat mode
   control 1 1
   # now send the ttc command
   bro 20 1

Indirect Addressing (memory paging)

Since there are 24 LUTs per type, and 2 types ("Input_LUT" and "Output_LUT"), we need at least 6 bits to determine which LUT we are working with. The Output_LUT needs 10 bits for addressing, which makes 16 bits total. This number exceeds the 13 bits available over VME (see above). To get around this limitation, we defined a "global indirect address" to "point" to which LUT or RAM we are working with, then we do the reads and writes using the "indirect address" for the individual LUT or RAM.

Setting the "Global Indirect Address" is done via a write to the VSR space (Localbus Device = 0). For the TOP Xilinx, you write the global address to the register at 0x28 and for the BOT Xilinx, you write to 0x2C. For example, if you wanted to read/write the global indirect address for the TOP HTR in slot 16, the VME address would be:

16<<19 + 0x0 + 0x28 = 0x01000028

Similary for the BOT xilinx (0x0100002C)

Indirect Global Addressing Pages
Type Page Address Address Size Data Size
RAM 0x180 + fiber number [0-7] 1024 per fiber 18 bits {ER,DV,16 bit half of 32 bit QIE word from FE}
Input LUT 0x81 + QIE[0-23] 7 bits per QIE 11 bits {Feature bit, 10 bits of linearized ET)
Output LUT 0x99 + QIE[0-23] 10 bits per QIE 8 bits of RCT-type TPG data


Last Update 10Oct2005 Drew Baden