UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor hekhanate
Visitor
786 Views
Registered: ‎07-28-2019

Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

I created an RTL as follows, whic was supposed to sum all the values in a connected BRAM, and store the sum in a custom AXI slave peripheral, with four registers (slv_regs).
RTL.jpeg

Having written the verilog file, the test bench, simulated it, it was verified and then packaged into an IP bram_ArraySum.

Thereafter, I created a block design as follows, which connected the bram controller, custom AXI slave register, and the bram_ArraySum, to function according to the RTL diagram, i.e. sum all the values in the BRAM, and store them in the 4th register of the AXI slave peripheral. With the first and second register used to write and read the start and done signal, respective, in accordance with the RTL diagram.

block design.PNG

When considering the memory-mapping of the bram and the axi peripheral, it was set as follows in the address editor:
address editor vivado.PNG

The AXI slave peripheral was edited using IP package editor, to ensure that the 1st register stored the start bit, the 2nd stores the done bit and the 4th stores the sum. I created the hdl wrapping, synthesised, implemented, generated the bitstream and exported the hardware.
After having launched the sdk, I wrote the source file "helloworld.c" as follows:

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xil_io.h"
#include "xparameters.h"
#include "xtime_l.h"


int main()
{
init_platform();

print("Hello World\n\r");
//storing base address of bram in bramPtr
unsigned int* bramPtr = 0x40000000;
xil_printf("bramPtr addr = %d\n\r", bramPtr);

//writing values in first 5 addresses of bram
int value;
for(int i = 0; i < 5; i++)
{
Xil_Out32(bramPtr + i, i);

}
//printing values from bram wrote on bram
int value1;
for(int i = 0; i < 5; i++)
{
value1 = Xil_In32(bramPtr + i);
xil_printf("bram[%d] = %d \n\r", i, value1);
}

//storing base address of bram in bramPtr
unsigned int* axiRegs = 0x40020000;
xil_printf("axiRegs addr = %d\n\r", axiRegs);
XTime time, time1;

//get start time
XTime_GetTime(&time1);

//start = 1
Xil_Out32(axiRegs, 1);

//wait for done
while((Xil_In32(axiRegs + 1)) != 1);

//read sum
int sum = Xil_In32(axiRegs + 3);
//start = 0
Xil_Out32(axiRegs + 0, 0);

//get end time
XTime_GetTime(&time);

// print sum
xil_printf("Sum = %d\n\r", sum);

cleanup_platform();
return 0;
}


This code is able to run successfully in the first two loops, having successfully wrote on the BRAM, and read from the values as well. However, the program gets stuck on the code line, when debugging "Xil_Out32(axiRegs, 1);" , not allowing me to stepo over. Considering the memory contents while debugging, I see no ability to access the axi_regs base address i.e. 0x40020000.

memory content debugging sdk.PNG
I can't seem to find the reason why I am not able to write on the register bit in AXI slave peripheral. Any and all help would be highly appreciated.

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Scholar dgisselq
Scholar
606 Views
Registered: ‎05-21-2015

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

@hekhanate,

Your code has a couple of problems.   The first problem is that it will lock the bus if you issue two read requests back to back in the presence of any back pressure.

readbug.png

What's basically happening is that the core raises ARREADY before the prior transaction clears.  The new transaction then comes in and ... there's no where for it to go.  As a result, you have in the example above two requests (a third one starts at the end) with only a single response.

This bug has been reported some time ago, and is rather common in the code currently created by Vivado's "Create and package IP" example design.  Worse, it's not caught by Xilinx's AXI verification IP.  You can find a description of a working AXI-lite peripheral here.

The ADDR_LSB calculation method is also broken.  While it works in this design for a bus width of 32 (AXI-lite can only have a 32-bit bus), it does not work in general.  The correct expression should be $clog2(C_S_AXI_DATA_WIDTH)-3.

As for your one write modifying 1024 values, that's simply due to the fact that the interconnect together with your code are only doing partial address decoding.  Notice that the case statement setting reg_data_out only checks two bits.  It's nothing to be worried about as long as the *correct* values are properly set.

Notice also that OPT_MEM_ADDR_BITS is set to 1.  This is probably also a mistake, but it isn't currently contributing to your problem.  A better choice for this value might be C_S_AXI_ADDR_WIDTH - ADDR_LSB.  However, if you chose to do that you'd then need to go back into your code and update everything that depended upon it, since it would now be equal to 2 rather than 1.

Dan

readbug.png
8 Replies
Moderator
Moderator
760 Views
Registered: ‎06-30-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

Hi @hekhanate,

 

Is it convenient to post your RTL code here(bram_ArraySum module and AXI_regs_0)?

-------------------------------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------------------------------
如果提供的信息能解决您的问题,请标记为“接受为解决方案”。
如果您认为帖子有帮助,请点击“奖励”。谢谢!
-------------------------------------------------------------------------------------------------
0 Kudos
Visitor hekhanate
Visitor
723 Views
Registered: ‎07-28-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

Sure!
bram_ArraySum.v code:

module bram_ArraySum(
input clk,
input reset,
input start, //Start signal generated by computer/processor
output reg done,
output reg [31:0] sum,
output reg [11:0] addr, //12-bit address
input [31:0] data //Data_out coming from BRAM
);
reg en_addr; //enable signal for address register
reg en_sum; //enable signal for sum register
//reg en_addr_r; //Signal not max, first delay register result
parameter MAX = 1023; // Max address of BRAM
//Not max as enable signal of address register
always@(*)
begin
en_addr = (addr != MAX);
end
//Address register
always@(posedge clk)
begin
if(reset || !start) addr <= #1 0;
else if(en_addr) addr <= addr + 1;
end

//One delay register to be used rather than two, as the sum register is to be enabled one cycle earlier, as when addresss is accessed, data is accessed from BRAM instantaneously
always@(posedge clk)
begin
if(reset || !start)
begin
//en_addr_r <= #1 0;
en_sum <= #1 0;
end
else
begin
//en_addr_r <= (en_addr);
en_sum <= (en_addr);
end
end

//Sum register
always@(posedge clk)
begin
if(reset || !start) sum <= #1 0;
else if(en_sum) sum <= sum + data;

end

//Generate done signal from en_sum
always@(posedge clk)
begin
done <= ~en_sum;
end

endmodule

AXI_regs_v2_0_S00_AXI.v code:


`timescale 1 ns / 1 ps

module AXI_regs_v2_0_S00_AXI #
(
// Users to add parameters here

// User parameters ends
// Do not modify the parameters beyond this line

// Width of S_AXI data bus
parameter integer C_S_AXI_DATA_WIDTH = 32,
// Width of S_AXI address bus
parameter integer C_S_AXI_ADDR_WIDTH = 4
)
(
// Users to add ports here
output start,
input done,
input [C_S_AXI_DATA_WIDTH-1:0] sum,


// User ports ends
// Do not modify the ports beyond this line

// Global Clock Signal
input wire S_AXI_ACLK,
// Global Reset Signal. This Signal is Active LOW
input wire S_AXI_ARESETN,
// Write address (issued by master, acceped by Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
// Write channel Protection type. This signal indicates the
// privilege and security level of the transaction, and whether
// the transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_AWPROT,
// Write address valid. This signal indicates that the master signaling
// valid write address and control information.
input wire S_AXI_AWVALID,
// Write address ready. This signal indicates that the slave is ready
// to accept an address and associated control signals.
output wire S_AXI_AWREADY,
// Write data (issued by master, acceped by Slave)
input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
// Write strobes. This signal indicates which byte lanes hold
// valid data. There is one write strobe bit for each eight
// bits of the write data bus.
input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
// Write valid. This signal indicates that valid write
// data and strobes are available.
input wire S_AXI_WVALID,
// Write ready. This signal indicates that the slave
// can accept the write data.
output wire S_AXI_WREADY,
// Write response. This signal indicates the status
// of the write transaction.
output wire [1 : 0] S_AXI_BRESP,
// Write response valid. This signal indicates that the channel
// is signaling a valid write response.
output wire S_AXI_BVALID,
// Response ready. This signal indicates that the master
// can accept a write response.
input wire S_AXI_BREADY,
// Read address (issued by master, acceped by Slave)
input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
// Protection type. This signal indicates the privilege
// and security level of the transaction, and whether the
// transaction is a data access or an instruction access.
input wire [2 : 0] S_AXI_ARPROT,
// Read address valid. This signal indicates that the channel
// is signaling valid read address and control information.
input wire S_AXI_ARVALID,
// Read address ready. This signal indicates that the slave is
// ready to accept an address and associated control signals.
output wire S_AXI_ARREADY,
// Read data (issued by slave)
output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
// Read response. This signal indicates the status of the
// read transfer.
output wire [1 : 0] S_AXI_RRESP,
// Read valid. This signal indicates that the channel is
// signaling the required read data.
output wire S_AXI_RVALID,
// Read ready. This signal indicates that the master can
// accept the read data and response information.
input wire S_AXI_RREADY
);

// AXI4LITE signals
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
reg axi_awready;
reg axi_wready;
reg [1 : 0] axi_bresp;
reg axi_bvalid;
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
reg axi_arready;
reg [C_S_AXI_DATA_WIDTH-1 : 0] axi_rdata;
reg [1 : 0] axi_rresp;
reg axi_rvalid;

// Example-specific design signals
// local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
// ADDR_LSB is used for addressing 32/64 bit registers/memories
// ADDR_LSB = 2 for 32 bits (n downto 2)
// ADDR_LSB = 3 for 64 bits (n downto 3)
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1;
//----------------------------------------------
//-- Signals for user logic register space example
//------------------------------------------------
//-- Number of Slave Registers 4
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg1;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg2;
reg [C_S_AXI_DATA_WIDTH-1:0] slv_reg3;
wire slv_reg_rden;
wire slv_reg_wren;
reg [C_S_AXI_DATA_WIDTH-1:0] reg_data_out;
integer byte_index;
reg aw_en;

// I/O Connections assignments

assign S_AXI_AWREADY = axi_awready;
assign S_AXI_WREADY = axi_wready;
assign S_AXI_BRESP = axi_bresp;
assign S_AXI_BVALID = axi_bvalid;
assign S_AXI_ARREADY = axi_arready;
assign S_AXI_RDATA = axi_rdata;
assign S_AXI_RRESP = axi_rresp;
assign S_AXI_RVALID = axi_rvalid;
// 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;
end
end
end

// Implement axi_awaddr latching
// This process is used to latch the address when both
// S_AXI_AWVALID and S_AXI_WVALID are valid.

always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_awaddr <= 0;
end
else
begin
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
begin
// Write Address latching
axi_awaddr <= S_AXI_AWADDR;
end
end
end

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

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

// Implement memory mapped register select and write logic generation
// The write data is accepted and written to memory mapped registers when
// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
// select byte enables of slave registers while writing.
// These registers are cleared when reset (active low) is applied.
// Slave register write enable is asserted when valid address and data are available
// and the slave is ready to accept the write address and write data.
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
slv_reg0 <= 0;
slv_reg1 <= 0;
slv_reg2 <= 0;
slv_reg3 <= 0;
end
else begin
if (slv_reg_wren)
begin
case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
2'h0:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 0
slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h1:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 1
slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h2:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 2
slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h3:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 3
slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
default : begin
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end
endcase
end
end
end

// Implement write response logic generation
// The write response and response valid signals are asserted by the slave
// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.
// This marks the acceptance of address and indicates the status of
// write transaction.

always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_bvalid <= 0;
axi_bresp <= 2'b0;
end
else
begin
if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
begin
// indicates a valid write response is available
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0; // 'OKAY' response
end // work error responses in future
else
begin
if (S_AXI_BREADY && axi_bvalid)
//check if bready is asserted while bvalid is high)
//(there is a possibility that bready is always asserted high)
begin
axi_bvalid <= 1'b0;
end
end
end
end

// Implement axi_arready generation
// axi_arready is asserted for one S_AXI_ACLK clock cycle when
// S_AXI_ARVALID is asserted. axi_awready is
// de-asserted when reset (active low) is asserted.
// The read address is also latched when S_AXI_ARVALID is
// asserted. axi_araddr is reset to zero on reset assertion.

always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_arready <= 1'b0;
axi_araddr <= 32'b0;
end
else
begin
if (~axi_arready && S_AXI_ARVALID)
begin
// indicates that the slave has acceped the valid read address
axi_arready <= 1'b1;
// Read address latching
axi_araddr <= S_AXI_ARADDR;
end
else
begin
axi_arready <= 1'b0;
end
end
end

// Implement axi_arvalid generation
// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
// S_AXI_ARVALID and axi_arready are asserted. The slave registers
// data are available on the axi_rdata bus at this instance. The
// assertion of axi_rvalid marks the validity of read data on the
// bus and axi_rresp indicates the status of read transaction.axi_rvalid
// is deasserted on reset (active low). axi_rresp and axi_rdata are
// cleared to zero on reset (active low).
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rvalid <= 0;
axi_rresp <= 0;
end
else
begin
if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
begin
// Valid read data is available at the read data bus
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0; // 'OKAY' response
end
else if (axi_rvalid && S_AXI_RREADY)
begin
// Read data is accepted by the master
axi_rvalid <= 1'b0;
end
end
end
//********************************************************************
//No need of counter anymore. Now we use axi for storing sum, generating start signal and receiving done signal
//reg [31:0] counter;
//always@(posedge S_AXI_ACLK) counter <= counter + 1;
//********************************************************************
// Implement memory mapped register select and read logic generation
// Slave register read enable is asserted when valid address is available
// and the slave is ready to accept the read address.
assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
always @(*)
begin
// Address decoding for reading registers
case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
2'h0 : reg_data_out <= slv_reg0;
2'h1 : reg_data_out <= {slv_reg1[31:1], done};
2'h2 : reg_data_out <= slv_reg2;
//2'h3 : reg_data_out <= slv_reg3;
2'h3 : reg_data_out <= sum;
default : reg_data_out <= 0;
endcase
end

// Output register or memory read data
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
axi_rdata <= 0;
end
else
begin
// When there is a valid read address (S_AXI_ARVALID) with
// acceptance of read address by the slave (axi_arready),
// output the read dada
if (slv_reg_rden)
begin
axi_rdata <= reg_data_out; // register read data
end
end
end

// Add user logic here
assign start = slv_reg0[0];
// User logic ends

endmodule

0 Kudos
Moderator
Moderator
701 Views
Registered: ‎06-30-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

Hi @hekhanate ,

 

I have tried your design. And I can access the slave AXI peripheral register.

I think you should check: All reset signals. AXI peripheral's reset is active-low. Bram's rsta/b is active-high.

Two suggestions:

1.Using ILA to capture signals. Please refer to ug940 Lab1.

2.These two modules can be merged into one AXI peripheral. Please refer to ug1118.

 

-------------------------------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------------------------------
如果提供的信息能解决您的问题,请标记为“接受为解决方案”。
如果您认为帖子有帮助,请点击“奖励”。谢谢!
-------------------------------------------------------------------------------------------------
Block Design.jpg
0 Kudos
Visitor hekhanate
Visitor
688 Views
Registered: ‎07-28-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

So do I change the polary setting of the bram to active low? or change the polarity setting of reset of the axi peripheral as active high?
And please guide me towards documentation that show how to do so. Thanks again!

0 Kudos
Moderator
Moderator
672 Views
Registered: ‎06-30-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

If all reset signals make sense, no change needs to be made. Just check and make sure the module won't stuck in reset cycle.

First try clean the project and rebuild.

If it dosen't work, delete current AXI_regs IP and package a new one. Please follow ug1118 Ch3 and Ch4.

 

 

-------------------------------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------------------------------
如果提供的信息能解决您的问题,请标记为“接受为解决方案”。
如果您认为帖子有帮助,请点击“奖励”。谢谢!
-------------------------------------------------------------------------------------------------
0 Kudos
Visitor hekhanate
Visitor
621 Views
Registered: ‎07-28-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

Apologies for the late reply. 

I was able to successfully write on the axi_regs, using a different base address as follows. Though even with the axi reg having base address 0x43C0_0000, I have a problem. I am able to access (read/write) values from the axi_regs (i.e. axi slave peripheral with no user logic), but when I use the following code:
unsigned int* axiRegs = 0x43C00000;

Xil_Out32(axiRegs, 11);

And debug it in sdk, the memory shows that '11' is written on the first bytes of all 1024 addresses of the axi_regs.

Similarly if the following code is used:

unsigned int* axiRegs = 0x43C00000;

Xil_Out32(axiRegs + 1, 11);
And debug it in sdk, the memory shows that '11' is written on the second bytes of all 1024 addresses of the axi_regs.
However, I just want to write on one memory location. Please help!

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

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

@hekhanate,

Your code has a couple of problems.   The first problem is that it will lock the bus if you issue two read requests back to back in the presence of any back pressure.

readbug.png

What's basically happening is that the core raises ARREADY before the prior transaction clears.  The new transaction then comes in and ... there's no where for it to go.  As a result, you have in the example above two requests (a third one starts at the end) with only a single response.

This bug has been reported some time ago, and is rather common in the code currently created by Vivado's "Create and package IP" example design.  Worse, it's not caught by Xilinx's AXI verification IP.  You can find a description of a working AXI-lite peripheral here.

The ADDR_LSB calculation method is also broken.  While it works in this design for a bus width of 32 (AXI-lite can only have a 32-bit bus), it does not work in general.  The correct expression should be $clog2(C_S_AXI_DATA_WIDTH)-3.

As for your one write modifying 1024 values, that's simply due to the fact that the interconnect together with your code are only doing partial address decoding.  Notice that the case statement setting reg_data_out only checks two bits.  It's nothing to be worried about as long as the *correct* values are properly set.

Notice also that OPT_MEM_ADDR_BITS is set to 1.  This is probably also a mistake, but it isn't currently contributing to your problem.  A better choice for this value might be C_S_AXI_ADDR_WIDTH - ADDR_LSB.  However, if you chose to do that you'd then need to go back into your code and update everything that depended upon it, since it would now be equal to 2 rather than 1.

Dan

readbug.png
Visitor hekhanate
Visitor
271 Views
Registered: ‎07-28-2019

回复: Unable to access (write/read) custom slave AXI peripheral register.

Jump to solution

@shengjie  @dgisselq  Thanks a lot Sir, the both of you. You have been of tremendous help. My block design has started working. 

再次感谢 

0 Kudos