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

axi_araddr <={16'h0,IN_ADDR[31:24]+1,IN_ADDR[15:8]+1}; is ok?

Jump to solution

I design a master axi ip,the code is attached.

The aim is to get 4 data from 4 ddr reg:addr => {a,b};{a+1,b}; {a,b+1}; {a+1,b+1} 

the addr change code is follow:

//Read Addresses
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0)
begin
axi_araddr <= 0;
end
// Signals a new write address/ write data is
// available by user logic
else
begin
if(read_index ==2'd0)
axi_araddr <={16'h0,IN_ADDR[31:24],IN_ADDR[15:8]};
else if(read_index ==2'd1)
axi_araddr <={16'h0,IN_ADDR[31:24],IN_ADDR[15:8]+1};
else if(read_index ==2'd2)
axi_araddr <={16'h0,IN_ADDR[31:24]+1,IN_ADDR[15:8]};
else if(read_index ==2'd3)
axi_araddr <={16'h0,IN_ADDR[31:24]+1,IN_ADDR[15:8]+1};
end
end

 

assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;

but the result is not as I hope. It shows as follow:the base is 0002, the result are:0002,0003,0102,0003. The reg3 should be 0103

why not?

2020-04-10 23_32_40-hw_ila_1.png

0 Kudos
1 Solution

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

@liwenz,

Your design isn't AXI compliant.  You are issuing ARVALID and then (possibly while ARVALID && !ARREADY) you are changing ARADDR.  You probably want to gate your changes on (start_single_read), since that's how everything else is gated within the design.  A better gate might be (!ARVALID || ARREADY)--but that's not quite how this design was built.

The second problem you have is that AXI addresses are *byte* addresses, not *word* addresses.  As a result, IN_ADDR[15:8]+1 requests the same word address rather than the next address.

A better choice might be something like:

// Make sure the additions don't overflow 8-bits
wire [7:0] next_last = IN_ADDR[15:8] + 1;
wire [7:0] next_first = IN_ADDR{31:24] + 1;

always @(posedge M_AXI_ACLK)
if (!M_AXI_ARESETN)
begin
  read_index <= 2'b00;
  axi_araddr <= { 14'h0, IN_ADDR[31:24], IN_ADDR[15:8], 2'b00 };
end else if (M_AXI_ARVALID && M_AXI_ARREADY)
begin
  // Adjust addresses only when we've finished working with the
  // last address.
  case(read_index) // This is the last read index
  2'd3: axi_araddr <= { 14'h0, IN_ADDR[31:24], IN_ADDR[15:8], 2'b00 };
  2'd0: axi_araddr <= { 14'h0, IN_ADDR[31:24], next_last, 2'b00 };
  2'd1: axi_araddr <= { 14'h0, next_first, IN_ADDR[15:8], 2'b00 };
  2'd2: axi_araddr <= { 14'h0, next_first, next_last, 2'b00 };
  endcase
  // Advance to the next address
  read_index <= read_index + 1;
end

Dan

 

View solution in original post

8 Replies
dgisselq
Scholar
Scholar
878 Views
Registered: ‎05-21-2015

@liwenz,

Your design isn't AXI compliant.  You are issuing ARVALID and then (possibly while ARVALID && !ARREADY) you are changing ARADDR.  You probably want to gate your changes on (start_single_read), since that's how everything else is gated within the design.  A better gate might be (!ARVALID || ARREADY)--but that's not quite how this design was built.

The second problem you have is that AXI addresses are *byte* addresses, not *word* addresses.  As a result, IN_ADDR[15:8]+1 requests the same word address rather than the next address.

A better choice might be something like:

// Make sure the additions don't overflow 8-bits
wire [7:0] next_last = IN_ADDR[15:8] + 1;
wire [7:0] next_first = IN_ADDR{31:24] + 1;

always @(posedge M_AXI_ACLK)
if (!M_AXI_ARESETN)
begin
  read_index <= 2'b00;
  axi_araddr <= { 14'h0, IN_ADDR[31:24], IN_ADDR[15:8], 2'b00 };
end else if (M_AXI_ARVALID && M_AXI_ARREADY)
begin
  // Adjust addresses only when we've finished working with the
  // last address.
  case(read_index) // This is the last read index
  2'd3: axi_araddr <= { 14'h0, IN_ADDR[31:24], IN_ADDR[15:8], 2'b00 };
  2'd0: axi_araddr <= { 14'h0, IN_ADDR[31:24], next_last, 2'b00 };
  2'd1: axi_araddr <= { 14'h0, next_first, IN_ADDR[15:8], 2'b00 };
  2'd2: axi_araddr <= { 14'h0, next_first, next_last, 2'b00 };
  endcase
  // Advance to the next address
  read_index <= read_index + 1;
end

Dan

 

View solution in original post

dgisselq
Scholar
Scholar
869 Views
Registered: ‎05-21-2015

@liwenz,

Upon closer inspection, you made a lot of changes to the IP packagers core.  (That's a good thing.)  The problem is ... you have several bugs remaining in your core.

I'm attaching your code (again), but with a reference to a set of formal properties at the bottom.  Using these formal properties and the SymbiYosys script that (I would've attached, but that got removed by the forum software), you can run SymbiYosys on your core to see if it's AXI protocol compliant or not using "sby -f formalcheck.sby prf".  (You'll need to install SymbiYosys and it's dependencies.)  Using SymbiYosys, I generated the following example trace illustrating how you only partially removed the INIT_AXI_TXN dependencies, allowing the core to generate an ARVALID that drops too early.

init-pulse-bug.png

If you assume INIT_AXI_TXN never goes high, then your design doesn't fail (anymore), but neither will it ever issue any writes, nor will it ever issue any more than 5 reads.  I'm not sure if that is by design or not, but the following trace (generated by sby -f formalcheck.sby cvr) shows in general what the read I/O's might look like coming from your core:

five-reads.png

Here's what the formalcheck.sby file looked like--in case you want to try running the check yourself.

[tasks]
prf
cvr

[options]
prf: mode prove
cvr: mode cover
prf: depth 20
cvr: depth 80

[engines]
smtbmc

[script]
read -formal correctTable_v1_0_M00_AXI.v
read -formal faxil_master.v
prep -top correctTable_v1_0_M00_AXI

[files]
correctTable_v1_0_M00_AXI.v
faxil_master.v

Dan

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

Thanks for your reply and code.  

I  try it and work well.

.

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

My ip is only read 4 data every INIT_AXI_TXN go high.

1st step: I change the IP packagers core to a searchTable ip. I check it work well.

2nd step: is this correctTable . It read 4 u32 to x0,x1,x2,x3. I check it something wrong.

3rd step: something calculate with x0-3,y0-3. for correct

With your help, I think the address is right. I am checking the four data( I only watch their last byte)

Also thanks for your information about SymbiYosys. I will learn it later.

 

0 Kudos
avrumw
Expert
Expert
712 Views
Registered: ‎01-23-2009

axi_araddr <={16'h0,IN_ADDR[31:24]+1,IN_ADDR[15:8]+1}; is ok?

 

I just want to go back to the original question to explain why this statement doesn't work.

In many Verilog operations you need to pay attention to the size of the operation. Verilog has very specific rules for the size of an operation. In this expression we have two types of operations, the concatenation operation, and addition.

For the concatenation operation, the size of the result is the sum of the sizes of the things that are concatenated (unless influenced by the left hand side).

For the addition operation, the size of the operation is the size of the larger of the two operands (unless influenced by the left hand side).

Lets take IN_ADDR[31:24]+1. This operation is inside a concatenation operation, so is not influenced by the left hand side. The size of the left operand (IN_ADDR[31:24]) is 8 bits. The right operand is "1" - since it has no specific size designation, it is 32 bits. Thus, you add the 8 bit value on the left with the equivalent of 32'sd1, and you get a 32 bit result. The same for IN_ADDR[15:8]+1. Thus the result is the concatenation of

  • 16 bits of 0
  • 32 bits for the first sum
  • 32 bits for the second sum

This is then truncated to 32 bits when assigned to axi_araddr; thus resulting in the loss of the upper 48 bits. This effectively results in the value

  • IN_ADDR[15:8]+1

(Since this is the entire 32 bottom bits of the expression).

To fix this, you just need to pay attention to the size of the "1" - in fact it is a good idea to never use unsized constants as a value in an expression. So simply changing this to

axi_araddr <={16'h0,IN_ADDR[31:24]+1'b1,IN_ADDR[15:8]+1'b1};

 

 

would work.

 

 

Avrum

 

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

I don't know why the 2nd read at 561 (yellow line) does not happen, and delay one read cycle.

Every read is same.

I change the index++ time after read done. After read, change the index and address.

2020-04-13 13_53_54-hw_ila_1.png

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

@liwenz,

broken-addr-v2.png

Two minutes with SymbiYosys suggests you aren't insulating your incoming address properly from the bus.  As long as ARVALID && !ARREADY, ARADDR isn't allowed to change.  This would be a protocol violation.

Dan

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

Thanks, then if(ARVALID && !ARREADY) addr<=..

I' ll try it.

0 Kudos