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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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