Arlen -
A good place to start learning about clock crossing and async fifos is by looking at app notes from companies like Xilinx. Simply realizing the problem exists and realizing it is important is a great first step.
Issues in clock crossing are flip-flop metastability, passing busses of data between domains, and Req/Ack handshaking between domains.
Metastability is discussed in many papers that you can look for on the web. Basically if you violate the setup/hold time on a flip-flop, it's going to be angry for a while, ie, potentially in a non 1/0 state. I t may hover at an inbetween voltage level, it many oscillate a bit, it may take longer to settle, etc. You r logic has to deal with this. Traditionally, a 2 stage flip-flop chain is considered good enough for this. This solution depends on clock and data rates!
Passing data/address/counters between domains is trickier. Assume you send an 8 bit value between domains. Because of delays in the gates and in routing, each bit of the bus arrives at the target flip-flops at a **slightly** different time. Because of this difference, when the targe clock tries to grab the data, it may latch some old data and some new data. In a perfect world, all the incoming bits would arrive at the exact same time and the target flip-flops would grab ALL of either old or new data. In the real world, the target flip flops will grab SOME new data and some old. So, if you are passing fifo address pointers between domains, you have potential problems in getting correct values at each clock edge. Solution: look into Gray coded values to pass back and forth. Since only one bit of a gray counter changes at a time, there is no problem with the receiving flip flops.
Sending Req/Ack handshake between domains is another area that can be trickier than one would like. There are efficient ways to do this, I'd suggest some Googling as part of your education.
Thought experiments in this area of domain crossing are very educational.
Clock crossing is one area where you MUST be paranoid. The problems in general are hard or impossible to simulate and hard to find in the real world. Since they are semi-random, you can spend a lot of effort tracking down a problem that only happens once an hour.
I hope this helps!
John P