06-18-2015 10:17 AM
Hi,
Hopefully somebody will be able to give me a few pointers to solve my issue, I've been fighting with it for a few days but can't seem to get it working.
I'm trying to write a simple AXI4 Slave (full AXI not lite) which will respond to read requests from the GP Masters of a Zynq Core. I have the following simple state machine which supports read transactions, including incremental bursts. the RDATA output is set in code not included below, triggered by the mem_read signal.
always@(posedge ACLK, negedge ARESETN) begin
if(ARESETN == 1'b0 ) begin ARREADY <= 1'b0; RVALID <= 1'b0; RRESP <= 2'b00; RLAST <= 1'b0; RID <= 3'b000; AXI_RC_BUSY <= 1'b0; axi_fsm_read_state <= Read_Idle_0; w_tr_length <= 4'b0000; mem_raddr <= 31'h00000000; end else begin case (axi_fsm_read_state)
Read_Idle_0: begin RVALID <= 1'b0; RLAST <= 1'b0; r_tr_length <= 4'b0000; if ( (ARVALID == 1'b1) && (ARBURST == 2'b01) && ((ARSIZE == 3'b000) || (ARSIZE == 3'b001) || (ARSIZE == 3'b010) || (ARSIZE == 3'b011))) begin ARREADY <= 1'b1; AXI_RC_BUSY <= 1'b1; ARSIZE_INT <= ARSIZE; ARBURST_INT <= ARBURST; ARLEN_INT <= ARLEN; RID <= ARID; mem_raddr <= ARADDR; mem_read <= 1'b1; axi_fsm_read_state <= Read_0; end else begin axi_fsm_read_state <= Read_Idle_0; end end Read_0: begin mem_read <= 1'b0; RVALID <= 1'b1; if (r_tr_length == ARLEN_INT) begin axi_fsm_read_state <= Read_2; RLAST <= 1'b1; end else begin axi_fsm_read_state <= Read_1; RLAST <= 1'b0; end end
Read_1: begin if (RREADY == 1'b1) begin axi_fsm_read_state <= Read_0; RVALID <= 1'b0; mem_read <= 1'b1; r_tr_length <= r_tr_length+1'b1; case(ARSIZE_INT[1:0]) 2'b00: begin mem_raddr <= mem_raddr + 16'h1; end 2'b01: begin mem_raddr <= mem_raddr + 16'h2; end 2'b10: begin mem_raddr <= mem_raddr + 16'h4; end 2'b11: begin mem_raddr <= mem_raddr + 16'h8; end default : mem_raddr <= mem_raddr; endcase end end
Read_2: begin if (RREADY == 1'b1) begin RVALID <= 1'b0; ARREADY <= 1'b1; RLAST <= 1'b0; RID <= 3'b000; axi_fsm_read_state <= Read_Idle_0; end end endcase end
The code as included seems to work as is. Now I want to be able to temporarily stall the slave and delay the completion of the read transaction for a few cycles introducing a delay. For now I'm looking at just artificially stalling the slave for a few cycles but this will be replaced with implementation logic which may take a couple of cycles to run. Looking at the AXI specs, and timing diagrams it appears that there are at least two points where the master should wait for the slave's signals before continuing:
In the above code there is no stall for 1) as the ARREADY signal is high before the read transaction is initiated and there is no stall for 2) as RVALID is asserted in the cycle immediately following the valid address being provided. When I try to insert a delay in either of these points (asserting ARREADY after an address request, or inserting a additional fsm state between Read_Idle0 and Read_0 the transaction appears not to complete and my control code on the ARM core hangs in the Xil_In32 command which initiates the read transaction, even if I stall for just a single cycle.
My question is, have I interpreted the spec and timing diagrams correctly to allow me to do this? is there a better way to insert a delay in the slave responding to a read request? And can anyone give me any pointers on how to implement it?
Thanks in advance for your comments, if anything needs clarifying, let me know.
Andrew
06-21-2015 09:06 AM
Hi bwiec,
Thanks for your message. I think i've got it working now. After much investigation I realised that the AXI stuff was working but I'd made a mistake in implementing my extra states in the state machine - note too self: when adding additional states to an fsm, always ensure ALL state variables have sufficient bit-widths!...
Thanks again
Andrew
06-19-2015 10:25 AM
06-21-2015 09:06 AM
Hi bwiec,
Thanks for your message. I think i've got it working now. After much investigation I realised that the AXI stuff was working but I'd made a mistake in implementing my extra states in the state machine - note too self: when adding additional states to an fsm, always ensure ALL state variables have sufficient bit-widths!...
Thanks again
Andrew