I'm watching a lecture on designing pipelines in HDL, and it's mentioned that the buffers (for intermediate values) between pipeline stages should be master-slave flip flops to avoid race conditions. Why is this preferable to common edge-sensitive D flip flops? Looking at other places where similar questions were asked, I find answers of why the T operation in JK flip flops causes a race condition (not relevant to D flip flops) or why a master-slave D flip flop must be used instead of a D latch (obvious). What are the differences between a standard edge-triggered D flip flop and a master-slave D flip flop and why is the latter preferable?
When you are building a pipeline, you need to introduce a delay in the datapath - that is basically what a pipeline does.
If you use "naked" D flops, they will all change their output on the same clock edge. Assume you have a D flop barrier, your combinatorial logic, and then another barrier: this is your basic pipeline building block. When the clock edge comes, the input and output barriers sample their input, and immediately present it at their output. This means that there is the possibility that the input of the output barrier will change while it is sampling it, possibly violating hold times.
If you instead use master slave flops, this does not happen, as the input is sampled on one edge, and copied to the output on the opposing edge.