Full picture
14

CRC32 Controller

14.1 Overview

On an 8-bit computer, verifying data integrity, such as before flashing firmware or after receiving data from an unreliable interface, can be challenging. Simple checksums like CRC8 or CRC16 may be either insufficient for error detection or too slow when processing large data sets.

To simplify this, Zeal Video Board includes a hardware CRC32 Controller that offloads the computation from the host processor.

Like other controllers, the CRC32 Controller can be mapped into the device bank starting at address 0xA0 on the I/O port. Its device index is 2.

14.2 Calculating a Checksum

Computing the CRC32 of a data block can be done as follows:

  1. Reset the Controller:

    • Set the RESET bit in the CTRL register to 1.
    • The reset is immediate and the bit is automatically cleared by hardware — no need to write it back to 0.
    • This initializes the internal 32-bit CRC register to 0xFFFFFFFF.
  2. Feed the Data:

    • Write each byte of the data block, one at a time, to the DATAIN register.
  3. Read the Result:

    • After all bytes have been written, the final 32-bit CRC value can be read from:
    • These registers are read-only.

The polynomial used for the calculation is 0xEDB88320.

Timing Note: After writing each byte, Zeal Video Board requires 2 clock cycles (@ 50 MHz) to update the CRC. Since typical 8-bit processors run at much lower speeds, no additional delays or nop instructions are required between writes.

14.3 Example (Z80)

Let's say we have a Z80-based host system, and the CRC32 controller is mapped in the 0xA0 I/O bank. Calculating the CRC32 of an array of byte pointed by HL can be done as follows:

    ; Parameters:
    ;   HL - Array of bytes
    ;   BC - Size of the array
    ; Returns:
    ;   DEHL - 32-bit CRC 32
calculate_crc32:
    ; Reset the controller
    ld a, 1
    out (0xa0), a
    ; Write all the bytes to `DATAIN` (offset 1).
    ; We could use `otir` instruction, but let's keep this example simple.
_crc32_next_byte:
    ; Check if BC is 0, end if 0.
    ld a, b
    or c
    jr z _crc32_end
    ld a, (hl)
    out (0xa1), a
    inc hl
    dec bc
    jr _crc32_next_byte
_crc32_end:
    ; Read resulting CRC32
    in a, (0x4)
    ld l, a
    in a, (0x5)
    ld h, a
    in a, (0x6)
    ld e, a
    in a, (0x7)
    ld d, a
    ret

14.4 Registers Summary

Name Description Base-relative address Access
CTRL Control register for CRC32 controller 0x00 WO
DATAIN Input data byte for CRC computation 0x01 WO
CRC32_BYTE0 CRC32 result byte 0 (least significant byte) 0x04 RO
CRC32_BYTE1 CRC32 result byte 1 0x05 RO
CRC32_BYTE2 CRC32 result byte 2 0x06 RO
CRC32_BYTE3 CRC32 result byte 3 (most significant byte) 0x07 RO

14.5 Registers

CTRL (0x00)
Control register for CRC32 controller
(reserved)
RESET
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
RESET
Reset the CRC32 controller state, shall be done before calculating the checksum of a new set of data (WO)
DATAIN (0x01)
Input data byte for CRC computation
DATA
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
DATA
Byte of input data to feed into the CRC32 computation (WO)
CRC32_BYTE0 (0x04)
CRC32 result byte 0 (least significant byte)
DATA
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
DATA
LSB of computed CRC32 value (RO)
CRC32_BYTE1 (0x05)
CRC32 result byte 1
DATA
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
DATA
Byte 1 of computed CRC32 value (RO)
CRC32_BYTE2 (0x06)
CRC32 result byte 2
DATA
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
DATA
Byte 2 of computed CRC32 value (RO)
CRC32_BYTE3 (0x07)
CRC32 result byte 3 (most significant byte)
DATA
7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0
Reset
DATA
MSB of computed CRC32 value (RO)