I have 2+ concurrent processes. Inside them there is an iteration that perform repetitive validate (select) + save (insert) operations. Here is the sql-server-profiler info on the deadlock:
<deadlock-list>
<deadlock victim="process8e09048">
<process-list>
<process id="process8e09048" taskpriority="0" logused="1088" waitresource="PAGE: 29:1:376823" waittime="920" ownerId="1276429306" transactionname="user_transaction" lasttranstarted="2012-09-26T20:59:44.367" XDES="0x3077833c0" lockMode="S" schedulerid="1" kpid="4872" status="suspended" spid="79" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-09-26T20:59:44.427" lastbatchcompleted="2012-09-26T20:59:44.427" clientapp=".Net SqlClient Data Provider" hostname="PORTAL" hostpid="5348" loginname="IIS APPPOOL\ASP.NET v4.0 Classic" isolationlevel="read committed (2)" xactid="1276429306" currentdb="29" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="282" sqlhandle="0x02000000b79df8046665e3984d6dc129fec20a3029fce9bc">
SELECT id FROM [WP_CashCenter_StockTransactionLine] WHERE StockTransaction_id=@StockTransaction_id and Direction=@Direction and IsVerified=@IsVerified and QualificationType=@QualificationType and id <> @id and Product_id is null and Material_id=@Material_id and StockContainer_id is null and StockLocation_id=@StockLocation_id </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@id bigint,@StockTransaction_id bigint,@Direction int,@IsVerified bit,@QualificationType int,@Material_id nvarchar(3),@StockLocation_id int)SELECT id FROM [WP_CashCenter_StockTransactionLine] WHERE StockTransaction_id=@StockTransaction_id and Direction=@Direction and IsVerified=@IsVerified and QualificationType=@QualificationType and id <> @id and Product_id is null and Material_id=@Material_id and StockContainer_id is null and StockLocation_id=@StockLocation_id </inputbuf>
</process>
<process id="process5c13948" taskpriority="0" logused="2636" waitresource="PAGE: 29:1:376823" waittime="920" ownerId="1276429252" transactionname="user_transaction" lasttranstarted="2012-09-26T20:59:44.337" XDES="0x222e64e80" lockMode="S" schedulerid="6" kpid="2956" status="suspended" spid="70" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-09-26T20:59:44.427" lastbatchcompleted="2012-09-26T20:59:44.427" clientapp=".Net SqlClient Data Provider" hostname="PORTAL" hostpid="5348" loginname="IIS APPPOOL\ASP.NET v4.0 Classic" isolationlevel="read committed (2)" xactid="1276429252" currentdb="29" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="238" sqlhandle="0x02000000d77dd1038a9b7f6d7158436117c042e42767242d">
SELECT id FROM [WP_CashCenter_StockTransactionLine] WHERE StockTransaction_id=@StockTransaction_id and Direction=@Direction and IsVerified=@IsVerified and QualificationType=@QualificationType and id <> @id and Product_id is null and Material_id=@Material_id and StockContainer_id is null and StockLocation_id is null </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@id bigint,@StockTransaction_id bigint,@Direction int,@IsVerified bit,@QualificationType int,@Material_id nvarchar(3))SELECT id FROM [WP_CashCenter_StockTransactionLine] WHERE StockTransaction_id=@StockTransaction_id and Direction=@Direction and IsVerified=@IsVerified and QualificationType=@QualificationType and id <> @id and Product_id is null and Material_id=@Material_id and StockContainer_id is null and StockLocation_id is null </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="376823" dbid="29" objectname="Edsson_WebPortal_v5.01.dbo.WP_CashCenter_StockTransactionLine" id="lock9302c80" mode="IX" associatedObjectId="72057594148028416">
<owner-list>
<owner id="process5c13948" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process8e09048" mode="S" requestType="convert"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="376823" dbid="29" objectname="Edsson_WebPortal_v5.01.dbo.WP_CashCenter_StockTransactionLine" id="lock9302c80" mode="IX" associatedObjectId="72057594148028416">
<owner-list>
<owner id="process8e09048" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process5c13948" mode="S" requestType="convert"/>
</waiter-list>
</pagelock>
</resource-list>
</deadlock>
</deadlock-list>

The statements are selects with conditions. The where clause of these selects only uses columns that are included to non-clustered index. Execution plan:

In this deadlock graph, both the processes were succeeded performing the INSERT and is holding the IX lock on the same page. They must be holding an X lock also on a two separate rows in the same page.
Since the SELECT is covered by the NC index, the page involved in the deadlock must be belonging the NC Index.
Your SELECT statement is trying to acquire a page level lock which is already having an IX lock by the INSERT statements.
So if your INSERTs are not belonging to the same StockTransaction_id, just adding the ROWLOCK hint to the SELECT will resolve the deadlock condition.
RCSI guarantees that readers are not blocked by writers and vice versa. But if your application design is relying on any blocking behavior, this can be an issue.
You can read more about Deadlock due to different lock granularity here