vGoodtimes
Advanced Member level 4
bram_axi_controller -- arready is always high after reset.
Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
The read data must always follow the address that it relates to.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 always @(posedge clk) begin if(reset) o_axi_rdata <= 0; // the following assumes that (i_axi_arlen = 0) && (i_axi_arsize = C_AXI_DATA_WIDTH/NUM_OF_BITS_PER_BYTES) // If (i_axi_arlen = 0), then value of i_axi_arburst does not matter at all // memory data is read out correctly one clock cycle after data request // memory data is valid only when requested with valid read address else if(!(o_axi_rvalid && !i_axi_rready)) o_axi_rdata <= mem[i_axi_araddr]; end
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 always @(posedge clk) begin if(reset) o_axi_araddr <= 0; // continues the next reading only when DDR memory is ready && // destination cache has space && // not exceeding designated DDR memory address else if(i_axi_arready && o_axi_rready) o_axi_araddr <= o_axi_araddr + 1; // increments DDR address to read instructions from end
Code Verilog - [expand] 1 2 else if(i_axi_arready && o_axi_arvalid) o_axi_araddr <= o_axi_araddr + 1;
Code Verilog - [expand] 1 2 else if(i_axi_arready && o_axi_arvalid) o_axi_araddr <= o_axi_araddr + 1;
However, if I modify the logic for ARADDR as above with o_axi_arvalid being a reg , then o_axi_araddr will be off by 1 clock cycle compared to o_axi_arvalid
ARVALID + ARREADY = produce RDATA + Assert RVALID
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 always @(posedge clk) begin if(reset) o_axi_rdata <= 0; // the following assumes that (i_axi_arlen = 0) && (i_axi_arsize = C_AXI_DATA_WIDTH/NUM_OF_BITS_PER_BYTES) // If (i_axi_arlen = 0), then value of i_axi_arburst does not matter at all // memory data is read out correctly one clock cycle after data request // memory data is valid only when requested with valid read address else if(!(o_axi_rvalid && !i_axi_rready)) o_axi_rdata <= mem[i_axi_araddr]; end always @(posedge clk) begin if(reset) o_axi_rvalid <= 0; // AXI specification: A3.3.1 Dependencies between channel handshake signal // the VALID signal of the AXI interface sending information must not be dependent on // the READY signal of the AXI interface receiving that information // this is to prevent deadlock // since AXI slave could wait for i_axi_arvalid to be true before setting o_axi_arready true. // Note: For same interface, VALID cannot depend upon READY, but READY can depends upon VALID // Note: Once VALID is asserted, it MUST be kept asserted until READY is asserted. // VALID signal needs to be set (initially) independent of READY signal, // and then only ever adjusted if !(VALID && !READY) // Note: the slave must not wait for the master to assert RREADY before asserting RVALID // Note: (!(o_axi_rvalid && !i_axi_rready)) == (!rvalid || rready) // == (!rvalid || (rvalid && rready)). // it means "no transaction in progress or transaction accepted" // Note: the slave must wait for both ARVALID and ARREADY to be asserted before // it asserts RVALID to indicate that valid data is available else if(!(o_axi_rvalid && !i_axi_rready)) o_axi_rvalid <= i_axi_arvalid && o_axi_arready; end
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 always @(posedge clk) begin if(reset) o_axi_araddr <= 0; // When ARVALID & ARREADY are both high the next ARADDR can be generated // because the current address for the current transfer is now complete (ARVALID & ARREADY). else if(i_axi_arready && o_axi_arvalid) o_axi_araddr <= o_axi_araddr + 1; // increments DDR address to read instructions from end
// simplified logic with interpretation and commentary. resets omitted. Code
// is from two files.
always @(posedge clk)
begin
// this part is fine. (bram controller)
// if (no current r transaction or current r transaction accepted)
// rvalid <= ar transaction accepted.
// rdata <= mem selected with araddr
if(!(rvalid && !rready)) begin
rvalid <= arvalid && arready;
rdata <= mem[araddr];
end
// this part is not. (bram controller)
// always accept ar transactions.
// lets say rready is 0 and stays 0 for many cycles.
// i_axi_arvalid becomes high. this is fine -- the above logic works
// correct. but one cycle later, what happens if arvalid is high again?
// the ar transaction will be accepted, but the r channel is not affected.
// and the above logic doesn't have any way to handle this.
arready <= 1;
// this part is weird (read instruction)
// from the above commentary, any time rready is high, arvalid must stop
// immediately because the transaction would be accepted and dropped.
// making part/all of this combinatorial probably fixes the issue, but isn't
// axi. It might work fine for this specific case.
arvalid <= (ddr_address_range_is_valid) && rready;
end
// this part is weird (read instruction)
// it is not registered and comes from another module.
// perhaps this is ok?
rready <= !cache_is_full; // from another module
@TrickyDicky
What do you exactly mean by the above ?
You accept the read address, then some time later, you produce the read data.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 always @(posedge clk) begin if(reset) o_axi_rdata <= 0; // the following assumes that (i_axi_arlen = 0) && (i_axi_arsize = C_AXI_DATA_WIDTH/NUM_OF_BITS_PER_BYTES) // If (i_axi_arlen = 0), then value of i_axi_arburst does not matter at all // memory data is read out correctly one clock cycle after data request // memory data is valid only when requested with valid read address else if(!(o_axi_rvalid && !i_axi_rready)) o_axi_rdata <= mem[i_axi_araddr]; end always @(posedge clk) begin if(reset) o_axi_rvalid <= 0; // AXI specification: A3.3.1 Dependencies between channel handshake signal // the VALID signal of the AXI interface sending information must not be dependent on // the READY signal of the AXI interface receiving that information // this is to prevent deadlock // since AXI slave could wait for i_axi_arvalid to be true before setting o_axi_arready true. // Note: For same interface, VALID cannot depend upon READY, but READY can depends upon VALID // Note: Once VALID is asserted, it MUST be kept asserted until READY is asserted. // VALID signal needs to be set (initially) independent of READY signal, // and then only ever adjusted if !(VALID && !READY) // Note: the slave must not wait for the master to assert RREADY before asserting RVALID // Note: (!(o_axi_rvalid && !i_axi_rready)) == (!rvalid || rready) // == (!rvalid || (rvalid && rready)). // it means "no transaction in progress or transaction accepted" // Note: the slave must wait for both ARVALID and ARREADY to be asserted before // it asserts RVALID to indicate that valid data is available else if(!(o_axi_rvalid && !i_axi_rready)) o_axi_rvalid <= i_axi_arvalid && o_axi_arready; end
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 always @(posedge clk) begin if(reset) o_axi_araddr <= 0; // When ARVALID & ARREADY are both high the next ARADDR can be generated // because the current address for the current transfer is now complete (ARVALID & ARREADY). else if(i_axi_arready && o_axi_arvalid && o_axi_rready) o_axi_araddr <= o_axi_araddr + 1; // increments DDR address to read instructions from end
Code Verilog - [expand] 1 else if(i_axi_arready && o_axi_arvalid && o_axi_rready)
Then arready can correctly apply backpressure.
Code Verilog - [expand] 1 o_axi_arvalid <= o_axi_rready;
3) slave can now start a read operation using the address captured during 2 (ignoring the RADDR), while doing the read,the slave would not respond (with an ARREADY) to another ARVALID unless it can support pending transactions.
As you seem to want to do an auto-increment address (for bursts?).
a) latch the AXI bus RADDR with ARREADY && ARVALID
b) increment the address using RREADY && RVALID, this updates the auto-increment burst address with a new read address.
if you use arready for backpressure, you know a valid axi master won't send transactions you can't handle.
@vGoodtimes : but ARVALID cannot depend on ARREADY .....
Code VHDL - [expand] 1 2 3 4 5 6 7 if start_of_burst then arvalid <= '1'; elsif end_of_burst and arready = '1' then arvalid <= '0'; end if;
AXI is really an unregistered control system, so its usually best to create READY signal unregistered internally and connect them to a AXI reg stage or skid buffer.
As you seem to want to do an auto-increment address (for bursts?).
a) latch the AXI bus RADDR with ARREADY && ARVALID
b) increment the address using RREADY && RVALID, this updates the auto-increment burst address with a new read address.
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 wire transaction_is_accepted = (i_axi_rvalid) && (o_axi_rready); always @(posedge clk) begin if(reset) o_axi_araddr <= 0; // When RVALID & RREADY are both high the next ARADDR can be generated // because the current address for the current transfer is now complete (RVALID & RREADY). else if(transaction_is_accepted) o_axi_araddr <= o_axi_araddr + 1; // increments DDR address to read instructions from end
Code Verilog - [expand] 1 2 3 4 5 6 7 8 9 10 11 wire transaction_is_accepted = (o_axi_arvalid) && (i_axi_arready); always @(posedge clk) begin if(reset) o_axi_araddr <= 0; // When ARVALID & ARREADY are both high the next ARADDR can be generated // because the current address for the current transfer is now complete (ARVALID & ARREADY). else if(transaction_is_accepted) o_axi_araddr <= o_axi_araddr + 1; // increments DDR address to read instructions from end
Code VHDL - [expand] 1 2 3 4 5 6 7 if start_of_burst then arvalid <= '1'; elsif end_of_burst and arready = '0' then arvalid <= '0'; end if;