The valid-ready protocol is probably the most frequently used handshake mechanism in digital design and verification, and it is a hot topic in hardware interview questions. In a nutshell, it has the following properties:
- Valid is asserted by the master when it has data to transfer, while ready is asserted by the slave when it has space to accept the data. Data transfer happens when both valid and ready are asserted.
- When valid is asserted, master should keep data stable until the data transfer completes.
- Master can wait until ready is asserted before asserting valid, or slave can wait until valid is asserted before asserting ready. However master and slave cannot wait for each other at the same time, otherwise it will introduce a deadlock.
Fairly simple, isn’t it? What if, physical designers see a timing violation between master and slave and timing fixes cannot help? Consider inserting register slice between master and slave.
Forward Register Slice
If “valid” path has a timing violation but “ready” path is fine, we can insert “forward register slice”, shown below, to cut “valid” path, but leave “ready” path as it is.
Both “data_out” and “valid_out” are driven by registers directly, and “ready_out” is asserted whenever either “data_reg” does not have valid data, or “ready_in” is asserted.
“Data Reg” samples “data_in” and “Valid Reg” is asserted every time a data transfer happens between master and register slice; “Valid Reg” is de-asserted when a data transfer happens between register slice and slave, but no data transfer between master and register slice.
Backward Register Slice
If “ready” path has a timing violation but “ready” path is fine, we can insert “backward register slice”, shown below, to cut “ready” path, but leave “valid” path as it is.
Compared to its “forward” counterpart, “backward register slice” is trickier. Consider the case where “ready_out” is 1 but “ready_in” is 0, slave is not ready for the data transfer but master thinks a data transfer can complete, therefore we need a temporary data storage “Data Reg” inside the register slice to handle this case. In addition, we need a flag “Data Reg Valid“ to indicate whether “Data Reg” has valid data. “Data Reg Valid” is used to statically mux between “Data Reg” and “data_in” for “data_out”. Whenever temporary data storage is valid or “valid_in” is asserted, “valid_out” is also asserted.
Full Register Slice
We will need to insert “full register slice” if both “valid” path and “ready” path have timing violations. “Full register slice” is essentially equivalent to a ping-pong FIFO, not “empty” serves as valid signal to slave, and not “full” serves as ready signal to master.
Although register slice insertion helps with timing, “forward register slice” and “full register slice” add one extra cycle latency to the datapath. Use these techniques with caution if your design is latency sensitive.
Related Interview Questions
- Timing Questions