Replies: 2 comments 6 replies
-
@paili0628 for the current design, where the Would the following not work:
|
Beta Was this translation helpful? Give feedback.
-
Thanks for the detailed writeup, @paili0628; this is quite helpful! To clarify, I believe the "fantasy" way we would like to read from the register (with minimal fuss) would be something like this, right?
That is, it's sort of like an …but there's a danger with that constant assignment That's why we originally needed to do I think supporting the above code would amount to item 1 in the list. Is that right? Could this work if we made the convention that the value is not actually "consumed" until |
Beta Was this translation helpful? Give feedback.
-
When setting up test cases for the two-reader register, I realized that the current interface could be very hard for clients to use. To use it correctly users have to make sure that the read_en_* signal is immediately turned off once the corresponding read_done_* signal is high; however, there is essentially no way to do that since in the Verilog code we write for the primitive, read_done_* signal depends on read_en_* signal. Direct dependence on the read_done_* signal to turn off the read_en_* signal would in turn result in a combinational loop.
To make the interface easier to use, we could 1. internally make sure that each read_en_* signals can only consume 1 value; 2. give users a standardized, safe way of turning off the read_en_* signal once they have the value they want.
So here are a few design choices:
instead of making "out" high for one cycle, make it high until the next read_en is high. The drawback of this would be having stale values at out_* ports, which would not be a good choice if we wanted to implement barriers with this design
instead of directly outputting a register value, use a read_ready signal to limit the number of values one read_en_* signal can consume. This means that reading now takes 4 steps: 1) reader sends read_en_* signal; 2) register gets read_en_* signal and sends read_ready_* signal; 3) reader gets read_ready_* signal and sends read_* signal; 4) register sees that read_ready_* and read_* signal are both high, turns off read_ready_* immediately and sends out the value. Drawback: 1. this design is very complicated, which can potentially cause more bugs for a synchronization program. 2. Using this design, it would take 4 cycles to read, which leads to starvation especially on the side of producers(since it only takes one cycle to write).
make it so that we send out the value 1 cycle after read_done_* signal is high, so that users are able to turn off the read_en_* value immediately when the register sends out the value. In the documentation for this primitive, we could write down sample code like this:
Drawback: this design relies too much on the client
Based on 3, we can internalize the r_read signal in the sample code: create a read_ready signal that is high one cycle after read_done is high, which is the cycle that the value is sent out. This way, clients can use the read_ready signal as a guard to turn off the read_en_* signal in time.
Based on discussion with @rachitnigam and @sampsyo.
Beta Was this translation helpful? Give feedback.
All reactions