NeTV FPGA architecture

From Studio Kousagi Wiki
Jump to: navigation, search

Development Background

NeTV's FPGA source is written in Verilog, and is compiled using Xilinx ISE tools. The freely available Webpack download will compile the code for the Spartan 6 XC6SLX9-2TQG144C contained within NeTV. Version 13.2 was used for development of the current release code.

When generating the bitfile, use the argument "-g binary:yes" to create a file with the extension .bin. Or, you can remove the ASCII header on the .bit file using dd if you prefer. Once you have the .bin file, reconfiguring the FPGA is done with the following commands:

fpga_ctl r  # this resets the FPGA
cat your_file.bin > /dev/fpga  # this blasts the configuration into the FPGA

A 26 MHz clock is provided to the FPGA, and the FPGA also has access to clocks provided on the video ports as well, but the rate of those clocks is variable.

Internal Architecture

Coming soon.

Register Set

Below is the I2C register set used to set parameters of the design as writ. This is up to date as of version 0xD of the FPGA.

  //// I2C internal control wiring ////
  /////////////////
  /// register 0: control snoop state (SNOOP_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         | MODEBNK |         |         | HPD_FRC | SQUASH  |  RD_STB |  RD_HDCP
  //
  //  bit 0 - RD_HDCP. When 1, select readback of the HDCP set; when 0, select EDID set
  //  bit 1 - RD_STB. When high, update the contents of SNOOP_DAT with data at SNOOP_ADR
  //  bit 2 - enable EDID squashing
  //  bit 3 - when high, force HPD to show that nothing is plugged in; low, act as normal
  //  bit 6 - sets the bank to write with register 0x13 (yah yah this is a hack)
  //
  /////////////////
  /// register 1: snoop readback address (SNOOP_ADR r/w)
  //  bits 7:0 are the address to read back  from the snoop unit
  //
  /////////////////
  /// register 2: snoop readback data (SNOOP_DAT ro)
  //  bits 7:0 are the data corresponding to the last loaded snoop address as
  //     selected by RD_HDCP bits in SNOOP_CTL when RD_STB was last toggled
  //
  //  REVISION -- now dynamically relays the value specified by snoop_adr without having
  //     to toggle RD_STB. RD_STB has no effect currently.
  /////////////////
  //  register 3: Compositing control (COMP_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  KM_SEM | RST_GNLK| SMRTLCK | RST_PLL |  SELF   | COMP_ON |  KM_RDY |  HDCP_ON
  //
  //  bit 0 - enable HDCP encryption of the composited stream. Enables HDCP encryption
  //          only if the HDCP cipher is used. If the input stream has no HDCP on it
  //          then this bit has no meaning.
  //  bit 1 - indicates that Km is ready and loaded (currently ignored)
  //  bit 2 - enable compositing of incoming data from LCD port to HDMI stream
  //  bit 3 - when set, ignore incoming data and generate sync based on LCD port signals
  //  bit 4 - when set, resets PLLs only on the paths designated by bit3 ("self")
  //  bit 5 - when set, enable "smart locking", i.e., genlock turns off once we're locked
  //  bit 6 - reset the genlock control machine
  //  bit 7 - Km semaphore -- used to indicate to the kernel whether an existing process
  //          is controlling the Km derivation process. This is to resolve the issue where
  //          the HPD will generate two events to cover Km generation in the case that
  //          the final protocol requires a "restart" to get the correct Km value to stick
  //
  /////////////////

`ifdef REGWINDOWS

  ///////////// REGISTER 4 - B are now DEPRECATED.
  //  register 4: window width
  //  bits 7:0 are LSB of window width
  //
  /////////////////
  //  register 5: window width
  //  bits 7:0 are MSB of window width
  //
  /////////////////
  //  register 6: window height
  //  bits 7:0 are LSB of window height
  //
  /////////////////
  //  register 7: window height
  //  bits 6:0 are MSB of window height
  //  bit 7 is the "update" bit which informs the system to take the new values on the next
  //    vsync period
  //
  /////////////////
  //  register 8: window X position
  //  bits 7:0 are LSB of window X position
  //
  /////////////////
  //  register 9: window X position
  //  bits 7:0 are MSB of window X position
  //
  /////////////////
  //  register A: window Y position
  //  bits 7:0 are LSB of window Y position
  //
  /////////////////
  //  register B: window Y position
  //  bits 7:0 are MSB of window Y position
  //
  /////////////////////////// END DEPRACATION BLOCK

`endif

  /////////////////
  //  register C: extended control set (EXT1_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         |         |         |         |         |         | CHROMA  |
  //
  //  bit 1: when set, turn on chroma keying; otherwise, always blend in
  //
  /////////////////
  //  NOTE: these are now hard-wired to 240, 0, 240. These registers will likely be deprecated soon.
  //  register D: chroma R value, 8 bits
  //  register E: chroma G value, 8 bits
  //  register F: chroma B value, 8 bits
  //
  /////////////////
  //  register 0x10 is read-only:
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  HDCPDET| VSYNCPOL| HSYNCPOL| LOWVOLT |         |  CEC    | LOCKED  |  BEND
  //  bit 0: chumby_bend pin state (tied off to insure configuratios as an input)
  //  bit 1: indicates that the genlock machine has locked LCD to HDMI streams
  //  bit 2: CEC pin state (tied off to insure configuratios as an input)
  //  bit 4: when high indicates that a low voltage condition was detected; only active during condition
  //         there is also an interrupt to the CPU that fires
  //  bit 5: indicates the polarity of the HSYNC detected on the HDMI stream, 1 = active high
  //  bit 6: indicates the polarity of the VSYNC detected on the HDMI stream, 1 = active high
  //  bit 7: when high, indicates that an HDCP stream is being encrypted. Not active during
  //         horiz and vert sync periods.
  //
  /////////////////
  //  register 0x11-12:
  //    lock tolerance, in pixels, in little-endian byte order
  //    This defines the tolerance of the "lock" threshold. This value matters mostly when
  //    "smart locking" is turned on, i.e., when we want to disable genlock once we're within
  //    our locking tolerance window.
  //
  /////////////////
  //  register 0x13 is address of modeline RAM to write
  //  7 is a write strobe (write when high)
  //  6:0 is the actual modeline address
  //
  /////////////////
  //  register 0x14 is the data to write into the modeline RAM
  //  7:0 is the data
  //
  /////////////////
  //  registers 0x15-0x17:
  //    lock target count, in pixels, in little-endian byte order.
  //    Lock target count is the amount of time that the LCD interface should lead the
  //    HDMI inteface for producing data. The amount of time should be large enough to
  //    absorb timing variations in the interrupt latency handling of the PXA168, but
  //    in all cases smaller than 8 lines of video (that's the size of the line buffers).
  //
  //    The total time should be expressed in units of pixels, not lines.
  //
  /////////////////
  //  register 0x18 is read-only:
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  RX_VLD |  B_RDY  |  G_RDY  |  R_RDY  | ALGNERR |  SYNLCK | TXLCK   |  RXLCK
  //  bit 0: rx PLL is locked, indicates that a clock is present and cable is plugged in
  //  bit 1: tx PLL is locked. This should generally always be the case.
  //  bit 2: synthesizer DCM is locked. This should generally always be the case.
  //  bit 3: rx alignment error
  //  bit 4: red channel has received a valid pixel
  //  bit 5: green chanel has received a valid pixel
  //  bit 6: blue channel has received a valid pixel
  //  bit 7: all RX chanels are phase aligned and producing valid data
  //   
  /////////////////
  //  registers 0x19-0x1f: Km
  //  56-bit value of Km, entered in little-endian order.
  //
  /////////////////
  //  All registers after this point are read-only, and byte-order is little-endian
  /////////////////
  //  register 0x20-21: horizontal active in pixels
  //  register 0x22-23: vertical active in lines
  //  register 0x24-25: horizontal total width in pixels
  //  register 0x26-28: vertical total height in pixels (not lines)
  //  register 0x29: horizontal front porch in pixels
  //  register 0x2a: horizontal back porch in pixels
  //  register 0x2b-2d: vertical front porch in pixels (not lines)
  //  register 0x2e-30: vertical back porch in pixels (not lines)
  //  register 0x31: horizontal sync width in pixels
  //  register 0x32-0x34: vertical sync width in pixels (not lines)
  //  register 0x35-0x37: reference clock count cycles
  //
  //  register 0x38-0x3e: device ID (7 bytes)
  //
  //  register 0x3f: version number

Motor Register Set

  //// I2C internal control wiring ////
  /////////////////
  /// register 0: control snoop state (SNOOP_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         | MODEBNK |         |         | HPD_FRC | SQUASH  |  RD_STB |  RD_HDCP
  //
  //  bit 0 - RD_HDCP. When 1, select readback of the HDCP set; when 0, select EDID set
  //  bit 1 - RD_STB. When high, update the contents of SNOOP_DAT with data at SNOOP_ADR
  //  bit 2 - enable EDID squashing
  //  bit 3 - when high, force HPD to show that nothing is plugged in; low, act as normal
  //  bit 6 - sets the bank to write with register 0x13 (yah yah this is a hack)
  //
  /////////////////
  /// register 1: snoop readback address (SNOOP_ADR r/w)
  //  bits 7:0 are the address to read back  from the snoop unit
  //
  /////////////////
  /// register 2: snoop readback data (SNOOP_DAT ro)
  //  bits 7:0 are the data corresponding to the last loaded snoop address as
  //     selected by RD_HDCP bits in SNOOP_CTL when RD_STB was last toggled
  //
  //  REVISION -- now dynamically relays the value specified by snoop_adr without having
  //     to toggle RD_STB. RD_STB has no effect currently.
  /////////////////
  //  register 3: Compositing control (COMP_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  KM_SEM | RST_GNLK| SMRTLCK | RST_PLL |  SELF   | COMP_ON |  KM_RDY |  HDCP_ON
  //
  //  bit 0 - enable HDCP encryption of the composited stream. Enables HDCP encryption
  //          only if the HDCP cipher is used. If the input stream has no HDCP on it
  //          then this bit has no meaning.
  //  bit 1 - indicates that Km is ready and loaded (currently ignored)
  //  bit 2 - enable compositing of incoming data from LCD port to HDMI stream
  //  bit 3 - when set, ignore incoming data and generate sync based on LCD port signals
  //  bit 4 - when set, resets PLLs only on the paths designated by bit3 ("self")
  //  bit 5 - when set, enable "smart locking", i.e., genlock turns off once we're locked
  //  bit 6 - reset the genlock control machine
  //  bit 7 - Km semaphore -- used to indicate to the kernel whether an existing process
  //          is controlling the Km derivation process. This is to resolve the issue where
  //          the HPD will generate two events to cover Km generation in the case that
  //          the final protocol requires a "restart" to get the correct Km value to stick
  //
  /////////////////


  /////////////////
  //  register 8-B: read-only debug registers, meaning reserved
  //
  
  /////////////////
  //  register C: extended control set (EXT1_CTL r/w)
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         |         |         |         |         |         | CHROMA  |
  //
  //  bit 1: when set, turn on chroma keying; otherwise, always blend in
  //
  /////////////////
  //  register D:
  //    PWM rate divider = value + 1
  //    i.e., base PWM rate = 1.625 MHz / (value + 1)
  //
  /////////////////
  //  register 0x10 is read-only:
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  HDCPDET| VSYNCPOL| HSYNCPOL| LOWVOLT |         |  CEC    | LOCKED  |  BEND
  //  bit 0: chumby_bend pin state (tied off to insure configuratios as an input)
  //  bit 1: indicates that the genlock machine has locked LCD to HDMI streams
  //  bit 2: CEC pin state (tied off to insure configuratios as an input)
  //  bit 4: when high indicates that a low voltage condition was detected; only active during condition
  //         there is also an interrupt to the CPU that fires
  //  bit 5: indicates the polarity of the HSYNC detected on the HDMI stream, 1 = active high
  //  bit 6: indicates the polarity of the VSYNC detected on the HDMI stream, 1 = active high
  //  bit 7: when high, indicates that an HDCP stream is being encrypted. Not active during
  //         horiz and vert sync periods.
  //
  /////////////////
  //  register 0x11:
  //     reserved
  //
  /////////////////
  //  register 0x12-0x14:
  //    Servo period, a 24-bit number (0x12 is LSB, 0x14 is MSB) which specifies how long the
  //    servo period is in 38.4615ns (1/26 MHz) increments.
  //    This setting only impacts the servo PWMs, has nothing to do with motor PWMs.
  //
  /////////////////
  //  registers 0x15-0x17:
  //    Servo 1 pulse width, a 24-bit number (0x15 is LSB, 0x17 is MSB) which specifies how long
  //    the positive going pulse of the servo PWM period is in 38.4615ns increments
  //    In order for this parameter to be recgonized, bit 6 of register 0x19 (SERVO1) must be set.
  //
  /////////////////
  //  registers 0x9-0xb:
  //    Servo 2 pulse width, a 24-bit number (0x15 is LSB, 0x17 is MSB) which specifies how long
  //    the positive going pulse of the servo PWM period is in 38.4615ns increments
  //    In order for this parameter to be recgonized, bit 7 of register 0x19 (SERVO2) must be set.
  //
  /////////////////
  //  register 0x18 is read-only:
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         |         |         |         |         |  SYNLCK | TXLCK   |  
  //  bit 1: tx PLL is locked. This should generally always be the case.
  //  bit 2: synthesizer DCM is locked. This should generally always be the case.
  //   
  /////////////////
  //  register 0x19: board control
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //  SERVO2 |  SERVO1 | DINSAMP |   GO    | ADC_DIG |  CHAN2  |  CHAN1  |  CHAN0
  //  bit 7: setting this bit puts channel 2 into servo timing mode; clearing puts it into motor mode
  //         In servo mode, PWM timing comes from servo period/pulse specifier. In motor mode, timing
  //         comes from motor PWM/period specifiers.
  //  bit 6: setting this bit puts channel 1 into servo timing mode; clearing puts it into motor mode
  //  bit 5: sample the digital input channels (rising edge triggered)
  //  bit 4: rising edge initiate read-in/write-out transaction as modified by bit 3
  //  bit 3: bit set selects ADC for read-in, bit clear selects digital for read-in/read-out
  //  bits 2-0: which ADC channel to sample
  //
  /////////////////
  //  register 0x1a: digital output values
  //
  /////////////////
  //  register 0x1b: motor enables
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //   M4B   |   M4A   |   M3B   |   M3A   |   M2B   |   M2A   |   M1B   |   M1A
  //
  /////////////////
  //  register 0x1c: motor 1 PWM
  //    value represents duty cycle as (value / 255) percent on
  //
  /////////////////
  //  register 0x1d: motor 2 PWM
  //    value represents duty cycle as (value / 255) percent on
  //
  /////////////////
  //  register 0x1e: motor 3 PWM
  //    value represents duty cycle as (value / 255) percent on
  //
  /////////////////
  //  register 0x1f: motor 4 PWM
  //    value represents duty cycle as (value / 255) percent on
  //
  
  /////////////////
  //  All registers after this point are read-only, and byte-order is little-endian
  /////////////////
  //  register 0x20: digital input
  //
  //  register 0x21: ADC input (LSB)
  //
  //  register 0x22: ADC input (MSB)
  //
  //  register 0x23: ADC channel that input data came from
  //  bit 7  |  bit 6  |  bit 5  |  bit 4  |  bit 3  |  bit 2  |  bit 1  |  bit 0
  //         |  BUSY   |         |  DGOOD  |  GOOD   |  CHAN2  |  CHAN1  |  CHAN0
  //  bit 6: set indicates that the serial chain is busy
  //  bit 4 - when set, digital input is stable and good
  //  bit 3 - when set, ADC input data is good (reflects most recent "go" request)
  //  bit 2:0 - channel originating the ADC input data
  //
  //  register 0x38-0x3e: device ID (7 bytes)
  //
  //  register 0x3f: version number