caravel
caravel copied to clipboard
CDC Issues
The housekeeping signals: rdstb
, wrstb
, iaddr
and idata
are crossing from the SCK
domain to the wb_clk_i
domain w/o any synchronizers. They must be synchronized w/ the wb_clk_i
clock to avoid metastability.
Actually, several signals (e.g., gpio_configure
) are crossing from SCK
to wb_clk_i w/o passing through synchronizers.
I went through this code with you at length several weeks ago and explained how the two domains (SCK
, by the way, not CSB
, which is not a clock domain) are kept from interacting. In essence, the two clock domains cannot collide except in a limited scenario that can be avoided simply by spec'ing the housekeeping SPI to run run slower than, if I recall correctly, half the core clock frequency.
The only way not cause an issue is to stop the CPU and the WB bus when CSB
is low (active)
Signal definitions:
wbbd_sck = Wishbone(core) clock SCK = mgmt_gpio_in[4] = SPI clock csclk = wbbd_sck if wbbd_busy == 1 SCK if spi_is_active == 1 0 otherwise wbbd_busy = 0 if wbbd_state == idle 1 otherwise spi_is_active = 1 if spi_is_enabled and (CSB == 0) 0 otherwise spi_is_enabled = 1 if (GPIO[3] (CSB pin) configured as input) and (hkspi_disable == 0) 0 otherwise spi_is_busy = 1 if spi_is_enabled and (SPI asserts read or write strobe) 0 otherwise hkspi_disable = (memory-mapped register bit)
Clock contention possibilities
- SPI attempts access during an ongoing wishbone access During wishbone access, wbbd_busy is 1 and so SCK cannot affect csclk. Potentially, SCK could happen during a wishbone access and could cause an SPI write not to happen. This can be prevented by specifying the SPI clock rate as slow enough that an SCK high pulse is always longer than a wishbone access.
- Wishbone attempts access during an ongoing SPI access: The wishbone will stall the CPU by not returning an acknowledge until the SPI read or write completes.
NOTE: The SCK clock should be synchronized to the core clock and arbitrated with the wishbone clock. Why this was not done: The housekeeping SPI should operate in the absence of a core clock. Best solution (?): Use a clock activity detection circuit to detect the presence or absence of a core clock. When the core clock is present, synchronize the SPI clock to the wishbone clock. When it is not present, pass the SPI clock, unsynchronized.
NOTE: For the design as of MPW-seven (at least), the clock contention will be handled purely by spec: To ensure correct operation, the housekeeping SPI should only read or write registers when the CPU is in reset, and the CPU should only read or write housekeeping registers when the housekeeping SPI has been disabled. All other usage is "generally" contention free but clock contention cannot be absolutely guaranteed.