Logic Analyzer core: Trigger Terms

From DP

Jump to: navigation , search

A trigger term is pretty simple. It compares the logic analyzer input against a target. If the input matches the target, it signals a hit. Trigger terms work the same in both basic & advanced triggers.

To make things a little more useful, the fpga also supports masking (or ignoring) parts of the input. The mask determines which bits must match, so you only compare them & nothing else.

As shown below, the compare is done with an XNOR (exclusive inverted or), which goes high when both inputs match. Masking is done by an AND gate.


OLS-documentation-TriggerTermCompare.png

Figure 7 - Masked Compare


To implement something like this normally requires flops to hold the target, flops to hold the mask, and logic for the XNOR & OR gates. So around 64 flops plus 32 logic blocks.

However, a better way exists. In an fpga, LUT's can handle everything. The 32-bit target & mask values, and logic are all encoded directly into only eight LUT's.

Mask  Input  Target  Hit
 0      0      0      0
 0      0      1      0
 0      1      0      0
 0      1      1      0
 1      0      0      1
 1      0      1      0
 1      1      0      0
 1      1      1      1

Figure 8 - Truth Table


Quite a savings, but there is a downside. Programming the LUT is non-trivial.

The "complexity" of the masked compare doesn't go away -- its simply transferred elsewhere. Thus in the advanced trigger, the eight LUT's need 128 bits of configuration supplied by the client.

The LUT memory is programmed with the -results- of a masked compare. The target & mask are known, and the input sample is one of sixteen possible values.

Thus we simply run through all combinations in advance. ie:

LUT address 0 stores result of: (0 ^ value) & mask)==0
LUT address 1 stores result of: (1 ^ value) & mask)==0
LUT address 2 stores result of: (2 ^ value) & mask)==0
LUT address 3 stores result of: (3 ^ value) & mask)==0
LUT address 4 stores result of: (4 ^ value) & mask)==0
etc…


OLS-documentation-clb-term2.png

Figure 9 - Trigger Term LUT

For each of the eight LUT's, the above is repeated with different 4 bit chunks of value & mask.


3.1 Programming Lookup Tables

To enable easier LUT programming, the fpga contains a built in parallel-to-serial converter. You simply write a long SUMP command to the chain address. Note the SUMP protocol dictates the least significant data byte be output first.

OLS-documentation-TriggerAdvData.png

Once the fpga receives the long command, the bytes are organized MSB first (bits 31 downto 0), and then serially shifted into the LUT chain.

OLS-documentation-LUTInit.png

Some of the advanced trigger modules are quite complex and need multiple writes to fully load their LUT chains. Chains vary in length up to 512 bits.

3.2 Example (Trigger Term Initialization)

#define write_select(value) write_long_command (0x9E, value)
#define write_chain(value) write_long_command (0x9F, value)
 
void write_term (int term_number, unsigned int target, unsigned int mask)
{
 unsigned int bitmask=1;
 unsigned int lutvalue0=0;
 unsigned int lutvalue1=0;
 unsigned int lutvalue2=0;
 unsigned int lutvalue3=0;
 
 for (int i=0; i<16; i=i+1) {
  if (((i ^ (target & 0xF)) & (mask & 0xF))==0) lutvalue0 |= bitmask;
  if (((i ^ ((target>>4) & 0xF)) & ((mask>>4) & 0xF))==0) lutvalue0 |= (bitmask<<16);
  if (((i ^ ((target>>8) & 0xF)) & ((mask>>8) & 0xF))==0) lutvalue1 |= bitmask;
  if (((i ^ ((target>>12) & 0xF)) & ((mask>>12) & 0xF))==0) lutvalue1 |= (bitmask<<16);
  if (((i ^ ((target>>16) & 0xF)) & ((mask>>16) & 0xF))==0) lutvalue2 |= bitmask;
  if (((i ^ ((target>>20) & 0xF)) & ((mask>>20) & 0xF))==0) lutvalue2 |= (bitmask<<16);
  if (((i ^ ((target>>24) & 0xF)) & ((mask>>24) & 0xF))==0) lutvalue3 |= bitmask;
  if (((i ^ ((target>>28) & 0xF)) & ((mask>>28) & 0xF))==0) lutvalue3 |= (bitmask<<16);
  bitmask <<= 1;
 }
 
 // Write data into LUT serial chain. MSB must goes in first. Total of 128 bits.
 write_select (0x20 + (term_number%10));
 write_chain (lutvalue3);
 write_chain (lutvalue2);
 write_chain (lutvalue1);
 write_chain (lutvalue0);
}

Figure 10 - Initialize Trigger Term LUT Values

License note

This document is Copyright © 2011 Ian Davis
Released under the  GNU General Public License