SPI Master Configurable Polarity and Phase
System-on-Chip designs communicate with diverse external peripherals like flash memory, sensors, and displays via the Serial Peripheral Interface (SPI). Because different manufacturers use different clock polarities and phases, a generic SPI controller must dynamically support all four SPI modes to communicate with any device.
The module receives an 8-bit tx_data payload and initiates an SPI transaction when start is asserted. It drives the active-low chip select cs_n low, generates the SPI clock sclk based on the clock polarity cpol, shifts out tx_data MSB-first on mosi, and samples the miso input into an internal shift register based on the clock phase cpha. Once all 8 bits are transmitted and received, it returns to an idle state, asserts done for one cycle, and outputs the received bytes on rx_data.
The core challenge is generating a glitch-free sclk and aligning the mosi launch edges and miso sample edges perfectly according to the four standard SPI modes: • Mode 0 (CPOL=0, CPHA=0): Idle sclk is 0. Sample on the leading (rising) edge, shift on the trailing (falling) edge. • Mode 1 (CPOL=0, CPHA=1): Idle sclk is 0. Shift on the leading (rising) edge, sample on the trailing (falling) edge. • Mode 2 (CPOL=1, CPHA=0): Idle sclk is 1. Sample on the leading (falling) edge, shift on the trailing (rising) edge. • Mode 3 (CPOL=1, CPHA=1): Idle sclk is 1. Shift on the leading (falling) edge, sample on the trailing (rising) edge.
To standardise the design, the module operates on a strict 18-cycle transaction timeline driven by the system clk. The SPI baud rate is exactly half the system clock frequency ($f_{clk}/2$). • $T_0$: start is asserted. • $T_1$: cs_n is driven low. If CPHA=0, the first bit (tx_data[7]) is immediately driven onto mosi. • $T_2$ to $T_{17}$: sclk toggles exactly once per system clock cycle, creating 16 alternating edges. • $T_{18}$: cs_n is driven high, sclk returns to its idle state, done is asserted for exactly 1 cycle, and rx_data contains the 8 sampled bits.
| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk | input | 1 | Positive-edge triggered system clock | | rst_n | input | 1 | Asynchronous active-low reset; resets all outputs to their idle values | | cpol | input | 1 | Clock polarity configuration (0: idle low, 1: idle high) | | cpha | input | 1 | Clock phase configuration (0: sample leading, 1: sample trailing) | | start | input | 1 | 1-cycle pulse to initiate the SPI transaction | | tx_data| input | 8 | Data byte to transmit (shifted out MSB first) | | miso | input | 1 | Master In Slave Out; sampled from the peripheral | | sclk | output | 1 | SPI Clock; tracks cpol when idle and toggles every cycle when active | | cs_n | output | 1 | Active-low chip select; resets to 1 | | mosi | output | 1 | Master Out Slave In; resets to 0 | | rx_data| output | 8 | Received data byte; resets to 8'b0 | | done | output | 1 | 1-cycle pulse asserted when the transaction completes; resets to 0 |
Constraints
- The entire transaction must take exactly 18
clkcycles from the cycle afterstartis asserted. sclkmust be fully registered or glitch-free; it must immediately reflectcpolwhen the module is idle.- Assume
cpolandcphaonly change when the module is idle and remain stable during a transaction. - For CPHA=0, the first data bit must be stable on
mosibefore the firstsclkedge occurs. mosimust hold its final value or return to 0 when the transaction completes; it must not glitch whencs_ngoes high.- Priority rules: If
startis asserted while a transaction is already in progress, it must be ignored.
Topics
Solve this problem
Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.
This problem is part of Codiode Pro. The statement above is free to read.
The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.