cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
liwenz
Explorer
Explorer
560 Views
Registered: ‎10-09-2017

why does custom axi4 ip fail at 2nd write in simulation?

I design a simple axi4 ip but fail at 2nd write in simulation.

It's in Vvivado 2018.3 and windows 10.

To simple, the user logic only
assign LED[3:0]=slv_reg0[3:0];

In my old axi4 ip, the simulation is normal.

2020-12-31 05_04_01-Greenshot.png

The bench test are:

Write 1,2,3,4 at addr 0, then 24 at 4, 48 at 8, 58 at 12, each write follows a read.

It works well, maybe in 2015.4 or 2018.2. number of registers is 4

 

In  2018.3 , the custom axi4 ip's number of registers is 16, I use almost same bench test program, but the simulation block at 2nd write. It wait awready and wready to be 1.

2020-12-31 13_53_14-simwave.png

I find it has a aw_en signal more, I also add a flag for indicate write begin and end.

I attach ipa,zip ( the normal one which made in 2018.2 or 2015.4 version; 

ip2.zip which made in  2018.3 and block at 2nd write.

Any advice is appreciate. I also hope to know the aw_en meaning.

0 Kudos
5 Replies
liwenz
Explorer
Explorer
544 Views
Registered: ‎10-09-2017

I find that it is blocked  by aw_en.

if aw_en =1, it will be ok.

 

	// Implement axi_awready generation
	// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
	// de-asserted when reset is low.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awready <= 1'b0;
	      aw_en <= 1'b1;
	    end 
	  else
	    begin    
	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
	        begin
	          // slave is ready to accept write address when 
	          // there is a valid write address and write data
	          // on the write address and data bus. This design 
	          // expects no outstanding transactions. 
	          axi_awready <= 1'b1;
	          aw_en <= 1'b0;
	        end
	        else if (S_AXI_BREADY && axi_bvalid)
	            begin
	              aw_en <= 1'b1;
	              axi_awready <= 1'b0;
	            end
	      else           
	        begin
	          axi_awready <= 1'b0;
	          aw_en <= 1'b1;  //code  added in 2020/12/31
	        end
	    end 
	end  

 

 aw_en =1 should be else if (S_AXI_BREADY && axi_bvalid)

but axi_bvalid is 0, aw_en can't be 1,

I add a line code in else (aw_en=1)

Now I could all the write as follows:

2020-12-31 15_58_12-wave.png

Maybe the else if should be:

else if (S_AXI_BREADY && ~axi_bvalid)

I'm not sure the change as I change the official code. Maybe I should ask xilinx.

Then I chek the ila wave, axi_bvalid should be 1. I made something wrong.

Where is the wrong?

0 Kudos
dgisselq
Scholar
Scholar
493 Views
Registered: ‎05-21-2015

@liwenz ,

The problem you are having is due to a race condition (or two or three) in your test bench.  The AXI signals generated by your master should be synchronous with the clock.  In the test bench design you've shared, they are not.  The resulting race condition(s) don't how up in your trace.

The attached test bench makes the AXI master inputs synchronous, resets the AXI master signals with the reset, fixes the other race condition between AWREADY and WREADY, and as a result has no problems.  (The race condition on AWREADY and WREADY wasn't the problem, but in general you can't rely upon these two signals being valid at the same time.  A slave might accept AWVALID before WVALID, or vice versa, or accept both on the same clock as the case is with this slave.)

The test bench I'm returning still has in the read side--I just updated the write half.  The read half should also be made synchronous.

You should also be aware that Xilinx's AXI demo's are horribly broken.  Since the revealing the bugs in their AXI-lite slave demo they fixed the write side (and dropped it's throughput from 50% to 33%), but the read half of the design remains broken.  Your simulation, as written, will not reveal the bugs although certain configurations of MicroBlaze and the interconnect have been known to trigger them.

axi-read-fault.png

I think you'll find this slave example easier to work with.  Even better, it doesn't violate protocol.

Yours,

Dan

0 Kudos
dgisselq
Scholar
Scholar
488 Views
Registered: ‎05-21-2015

@liwenz ,

Just as another note, you can see problems in your first trace long before the second write where you noticed the failure.

  1. The *VALID signals from the master are listed as 'x.  They should either be '0 or '1 or the reset should be active.
  2. The same is true of BREADY and RREADY.
  3. There is no BVALID from your first write.  Your design, however, never checks for it so you miss this bug.  Incidentally, this is where aw_en gets lowered and never raised.

Dan

0 Kudos
liwenz
Explorer
Explorer
449 Views
Registered: ‎10-09-2017

Thanks for your response!

I think that i need got axi_bvalid been 1.

I check the condition:

if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)

and think that I maybe need to last more time for awready, wready.

So I change the axi_awready and axi_wready cycle:

from 

 else  

...

to 

else if(axi_bvalid)
begin
axi_wready <= 1'b0;
end

(axi_awready similar)

Then the simulation seems right.

2021-01-02 00_13_01-Greenshot.png   

I also change the bench.v file ,let write finish wait axi_bvalid signal.

Is my change acceptable?

I also don't understand that aw_en changes before bvalid.

0 Kudos
dgisselq
Scholar
Scholar
396 Views
Registered: ‎05-21-2015

@liwenz ,

Looks like you broke things worse in that last screen shot.

  • AWVALID, WVALID, BREADY, AW* signals, W* signals, B* signals, etc. must change *ONLY* on a clock.  That means your test script should be using non-blocking assignments (<=) that then wait on a clock tick before changing, rather than using delays (#20) followed by blocking assignments (=).
  • For every clock cycle where AWVALID && AWREADY, there should be one and only one corresponding clock cycle where BVALID && BREADY.
  • For every clock cycle where WVALID && WREADY, there should be one and only one corresponding clock cycle where BVALID && BREADY.
  • The screen shot above, therefore, shows missing BVALIDs.  This is a *severe* protocol violation.
  • The Xilinx demo design, as Xilinx wrote it, will never allow (AWREADY || WREADY) && BVALID.  Your modified design, as shown in your screen shot above permits this.

If you want to share this updated design, I'll take a peek at it to check for protocol compliance.

Dan

0 Kudos