Sorry, you need to enable JavaScript to visit this website.

MicroZed Vivado Design Issue

Solved
10 posts / 0 new
raymadigan's picture
raymadigan
Junior(0)
MicroZed Vivado Design Issue

I am not sure what to do at this point. I have tried everything I can think of except a new MicroZed board.

I have a design that uses a custom AXI Lite IP. Basically I want to allocate N registers and have N/2 be read/write and the other N/2 be read only. The read only registers will be written to by my application.

I have build the design and none of my changes have any effect when I run the application on my uZed. I have commented out the entire process that writes the register to the AXI output pins. This change has no effect on the application, it still runs as the original AXI Lite IP.

I have asked countless times in the Vivado, Design Entry, Zynq forums and nobody has an idea of how to overcome this problem.

I have a very very early uZed. Is there any suggestions to overcome this issue.

Is there a test I can run to determine where the issue might be.

I have a very similar problem with an AXI Stream Master IP I am trying to build.

fletch's picture
fletch
Moderator(16)
Have you looked at this in

Have you looked at this in simulation?
You might try reading/writing a dual-port blockRAM in the fabric first before getting the custom IP to work.
Also, after you make changes in Vivado, how do you ensure the new hardware platform is being updated in SDK?
 
BryanA

raymadigan's picture
raymadigan
Junior(0)
I have run many examples with

I have run many examples with stock IP, I have an example of using DMA to write to and read from an AXI Stream FIFO. I will do a dual port block ram to be sure I cam make that work.

I have tried several alternatives. When I change the VHDL in the project in vivado, I run synthesis, ..., and generate Bitstream. I then export the Hardware and the SDK automatically recognizes the bitstream has changed rebuild the board support for the project.

Alternatively, I have built a project with the VHDL that has the commented out process and it still acts like the Base IP.

The first customization I did was really simple, I forced the read of a register to output zero by replacing the write to the output signal to be (others => '0').

I don't know how to tell what is actually written to the fabric. Are there SDK calls to ask versioning information?

fletch's picture
fletch
Moderator(16)
I would recommend that you

I would recommend that you not let SDK automatically update the hardware. With each new hardware platform, I would export to a different , versioned directory. Once in SDK with that hardware platform, then generate the BSP, then import your previous code projects from the prior directory.
Bryan

raymadigan's picture
raymadigan
Junior(0)
I will give that a try, I

I will give that a try, I really hope I can find something I am doing wrong that will let me get past this. One thing I don't understand is that I created a fresh project with the already modified VHDL, I exported the hardware and created a brand new SDK project with the new hardware definition. This had the same issue as all of the others did.

I will try some variations of this process this morning and see if the results are different.

I do appreciate your help.

raymadigan's picture
raymadigan
Junior(0)
Maybe my design is wrong

I looked closely at the vhdl to try to get a better understanding and saw this:

process (S_AXI_ACLK)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
if rising_edge(S_AXI_ACLK) then
if S_AXI_ARESETN = '0' then
slv_reg0 <= (others => '0');
slv_reg1 <= (others => '0');
slv_reg2 <= (others => '0');
slv_reg3 <= (others => '0');

so all registers should be reset to zero when AXI_ARESETN goes to zero.

int main()
{
init_platform();
print("Hello World\n\r");

volatile int BaseAddress = 0x43C00000;

// Check the initial state of the 0'th register
int foo = CCMDEMO_mReadReg(&BaseAddress, 0);
printf("Reg 0: %d\n\r", foo);

// Set the 0'th register to a value and read it
CCMLITEDEMO_mWriteReg(&BaseAddress, 0, 54321);
int bar = CCMLITEDEMO_mReadReg(&BaseAddress, 0);
printf("Reg 0: %d\n\r", bar);

cleanup_platform();
return 0;
}

shows output:

Hello World
Reg 0: 1136656384
Reg 0: 54321

It seems like it works, but maybe the reset is wrong.

raymadigan's picture
raymadigan
Junior(0)
I made the following change

I made the following change to the vhdl

-- 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.
slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;

process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, axi_araddr, S_AXI_ARESETN, slv_reg_rden)
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- Address decoding for reading registers
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
case loc_addr is
when b"00" =>
reg_data_out <= (others => '0'); --slv_reg0;
//and at the end of the same process
when others =>
reg_data_out <= (others => '0');
end case;
end process;

The 0'th register and all registers greater then register 3 should be zero

If I change my main to this:
int foo = CCMLITEDEMO_mReadReg(&BaseAddress, 0);
printf("Reg 0: %d\n\r", foo);

CCMLITEDEMO_mWriteReg(&BaseAddress, 0, 54321);
int bar = CCMLITEDEMO_mReadReg(&BaseAddress, 0);
printf("Reg 0: %d\n\r", bar);

CCMLITEDEMO_mWriteReg(&BaseAddress, 24 , 98765);
bar = CCMLITEDEMO_mReadReg(&BaseAddress, 24);
printf("Reg 6: %d\n\r", bar);

the output is:

Hello World
Reg 0: 1136656384
Reg 0: 54321
Reg 6: 98765

Register 6 should be zero, there is no register 6 defined in the vhdl.

All I can assume is a different VHDL is running on the board that implements all registers.

raymadigan's picture
raymadigan
Junior(0)
I did another test this

I did another test this morning to be sure that what I was reporting here was accurate. I built a brand new hardware project that included the following:

Zynq Processor
Processor Reset
AXI Interconnect with 1 master and one slave
AXI Lite with 6 registers.

I made no edits of any of the VHDL Exported the hardware and launched the SDK.

I created the following program in the SDK:

// Six Register attempt at 0x4300000
int main()
{
init_platform();
print("Hello World\n\r");
int BaseAddress = 0x4300000;
int i = 0;
int offset = 0;
int foo = 0;
int regCount = 6;
// Set each register to its index.
for (i = 0; i < regCount; i++)
{
HWTESTONE_mWriteReg(&BaseAddress, offset, i);
offset += 4;
}
offset = 0;
// Write the value of each index
for (i = 0; i < regCount; i++)
{
foo = HWTESTONE_mReadReg(&BaseAddress, offset);
offset += 4;
printf("Write Register %d: %d\n\r", i, foo);
}
// Write to the register one past the number generated
offset = regCount * 4;
HWTESTONE_mWriteReg(&BaseAddress, offset, offset);
// Read the register one past the number generated
foo = HWTESTONE_mReadReg(&BaseAddress, offset);
printf("Read Register %d: %d\n\r", regCount, foo);
offset = 0;
// Read all the registers including the one past
for (i = 0; i < regCount +1; i++)
{
foo = HWTESTONE_mReadReg(&BaseAddress, offset);
offset += 4;
printf("Read Register %d: %d\n\r", i, foo);
}

cleanup_platform();
return 0;
}

The output from the program was:
Hello World
Write Register 0: 0
Write Register 1: 1
Write Register 2: 2
Write Register 3: 3
Write Register 4: 4
Write Register 5: 5
Read Register 6: 24
Read Register 0: 0
Read Register 1: 1
Read Register 2: 2
Read Register 3: 3
Read Register 4: 4
Read Register 5: 5
Read Register 6: 24

What we see here is that writing and reading past the last register works as any of the registers in the requested range. Also, the writing of the register is not a wrap around into the original register range. It is actually writing to where register 6 would be. In the VHDL that was generated by the AXI Lite wizard the reading process is such that if a number past the end of the register bank is read from the result should be zero, and it isn't.

The VHDL is

constant OPT_MEM_ADDR_BITS : integer := 2;

-- 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.
slv_reg_rden <= axi_arready and S_AXI_ARVALID and (not axi_rvalid) ;

process (slv_reg0, slv_reg1, slv_reg2, slv_reg3, slv_reg4, slv_reg5, axi_araddr, S_AXI_ARESETN, slv_reg_rden)

-- loc_addr is a 3 bit vector [2 down to 0]
variable loc_addr :std_logic_vector(OPT_MEM_ADDR_BITS downto 0);
begin
-- Address decoding for reading registers
-- loc_addr := axi_araddr(2 + 2 downto 2);
-- Not sure of the specifics, assume it returns 3 bits in the address
loc_addr := axi_araddr(ADDR_LSB + OPT_MEM_ADDR_BITS downto ADDR_LSB);
case loc_addr is
when b"000" =>
reg_data_out <= slv_reg0;
when b"001" =>
reg_data_out <= slv_reg1;
when b"010" =>
reg_data_out <= slv_reg2;
when b"011" =>
reg_data_out <= slv_reg3;
when b"100" =>
reg_data_out <= slv_reg4;
when b"101" =>
reg_data_out <= slv_reg5;

-- for case b"110" and b"111"
when others =>
reg_data_out <= (others => '0');
end case;
end process;

Registers 6 and 7 should be in the others clause of the case statement.
The same is true for the write process. I can only conjecture that the bitstream that is running on the MicroZed is not the same as that shown it the vhdl for the project.

Also, I cn change the base address in the main program to
BaseAddress to 0x42000000 or to 0x60000000 I still get the same result.

raymadigan's picture
raymadigan
Junior(0)
Why am I so persistent about

Why am I so persistent about this issue. The company I work for wants to use this board for a production product. The issue is, The vhdl generated by the AXI Lite wizard and the AXI Stream wizard need to be modified to fit the needs of the project.

Is it possible for someone to run this example and show the results so I can know if the problem is in the specific board instance I am using, I have one of the very first boards produced. or if I am doing something that could cause the problem. If I am doing something wrong, I will be more then willing to change to make this project work.

TroutChaser's picture
TroutChaser
Moderator(18)
I understand that you worked

I understand that you worked with your local Avnet FAE and tracked down the issue to a software  error in a driver calling Xil_Out32(), which takes an unsigned int rather than a pointer.
 
So HWTESTONE_mWriteReg(&BaseAddress, offset, i); should be HWTESTONE_mWriteReg(BaseAddress, offset, i); (removing & from the BaseAddress parameter)
 
-Gary