1111
1212import cocotb
1313from cocotb_helpers import reset_n
14- from cocotb .triggers import ClockCycles , RisingEdge , Timer
14+ from cocotb .triggers import ClockCycles , RisingEdge , Combine
1515from cocotbext .axi import AxiLockType , AxiBurstType , AxiResp
1616from common import timeout_task , log_seed
1717
@@ -657,11 +657,11 @@ async def test_read_stall(dut):
657657@cocotb .test ()
658658async def test_write_b_channel_skid_full (dut ):
659659 """
660- Verify that when the B-channel is stalled and two write responses are pending
660+ Verify that when the B-channel is stalled and three write responses are pending
661661 (output stage + hold register of the response skidbuffer), rp_ready drops to 0,
662- req_ready follows, and AWREADY deasserts to prevent a third response from
663- overflowing the skidbuffer. Releasing the stall drains all responses and all
664- three writes complete with correct data.
662+ req_ready follows, and AWREADY deasserts to prevent a third and fourth responses
663+ from overflowing the skidbuffer. Releasing the stall drains all responses and all
664+ four writes complete with correct data.
665665 """
666666 tb = await initialize (dut )
667667
@@ -673,10 +673,11 @@ async def test_write_b_channel_skid_full(dut):
673673 b_channel = tb .busIf .axi_m .write_if .b_channel
674674
675675 test_data = csr_access_test_data (tb .reg_map .I3CBASE , skip_regs = ["RESET_CONTROL" ])
676- assert len (test_data ) >= 3 , "Need at least 3 writable registers in I3CBASE"
676+ assert len (test_data ) >= 4 , "Need at least 4 writable registers in I3CBASE"
677677 (reg1_name , addr1 , wdata1 , exp_rd1 ) = test_data [0 ]
678678 (reg2_name , addr2 , wdata2 , exp_rd2 ) = test_data [1 ]
679679 (reg3_name , addr3 , wdata3 , exp_rd3 ) = test_data [2 ]
680+ (reg4_name , addr4 , wdata4 , exp_rd4 ) = test_data [3 ]
680681
681682 # Stall all write responses — no B-channel handshake until we release
682683 b_channel .pause = True
@@ -687,15 +688,20 @@ async def test_write_b_channel_skid_full(dut):
687688 await RisingEdge (dut .aclk )
688689
689690 # Write 2: when its final beat completes with bvalid=1 already asserted,
690- # the skidbuffer hold register fills (r_valid=1) and rp_ready drops to 0.
691+ # the skidbuffer hold register fills (r_valid=1) and rp_ready
692+ # drops to 0.
691693 task2 = cocotb .start_soon (tb .write_csr (addr2 , int2dword (wdata2 ), 4 ))
692694 # Allow enough cycles for write 2 to complete its AW+W phases
693695 await ClockCycles (dut .aclk , 20 )
694696
695697 # Write 3: AW arrives when req_ready=0 (rp_ready=0), so the request skidbuffer
696- # fills and AWREADY must deassert to apply backpressure
698+ # fills and AWREADY must deassert to apply backpressure
697699 task3 = cocotb .start_soon (tb .write_csr (addr3 , int2dword (wdata3 ), 4 ))
698700
701+ # Write 4: Request skidbuffer is already full, AWVALID is asserted while
702+ # AWREADY is deasserted
703+ task4 = cocotb .start_soon (tb .write_csr (addr4 , int2dword (wdata4 ), 4 ))
704+
699705 awready_went_low = False
700706 for _ in range (30 ):
701707 await RisingEdge (dut .aclk )
@@ -707,14 +713,13 @@ async def test_write_b_channel_skid_full(dut):
707713
708714 # Release the stall — all three responses drain, all three tasks complete
709715 b_channel .pause = False
710- await task1
711- await task2
712- await task3
716+ await Combine (task1 , task2 , task3 , task4 )
713717
714718 for reg_name , addr , exp_rd in [
715719 (reg1_name , addr1 , exp_rd1 ),
716720 (reg2_name , addr2 , exp_rd2 ),
717721 (reg3_name , addr3 , exp_rd3 ),
722+ (reg4_name , addr4 , exp_rd4 ),
718723 ]:
719724 rd = bytes2int (await tb .read_csr (addr , 4 ))
720725 assert rd == exp_rd , (
0 commit comments