The key to deadlocks is usually, but not always, that you have multiple different queries, not the same query, that are accessing the various tables in different orders. Meaning, one batch inserts into TABLEA and then selects from TABLEB. The other batch selects from TABLEB, then inserts into TABLEA. Each one has to wait on the other to complete, but neither can complete until the other is finished. A deadly embrace, a deadlock.
Deadlocks are also performance related. Even with the example above, if everything is completed really quickly, you'll never notice that the code is out of order.
So, to fix deadlocks, first, get the code so that everything goes in the same order all the time. Next, performance tune that code and your structures. Between the two, you should eliminate most deadlocks. Yes, snapshot isolation helps because the shared locks needed for reads are not taken out in the same way, reducing the chances of deadlocks radically. However, snapshot isolation can add considerable load to your tempdb, so be cautious here.
Search the articles here on SSC. Tons and tons of information on deadlocks, how to get the deadlock graphs (extended events, specifically system_health, will be your friend, don't go old school and use traceflags), how to read the graphs and how to fix the issues.