Basically I want to provide delay of 15 clock cycles for writing and reading through axi4 bus .Is it possible?
Hi preet729,
As "yasuhikokoumoto" says, we would need to know what is driving this requirement before anyone could suggest how to achieve this.
The interconnect logic between your master and your slave should be trying to pass information as quickly as possible, so it would be rare to see anything intentionally adding 15 cycles of delay.
Instead my first thought would be that if a master or a slave needs to delay any transfer completing on any channel, both the transfer source and the transfer destination have full control over the transfer timings using the AXI VALID and READY handshake signals.
So if for example your slave required at least 15 cycles between an AW channel transfer and the first W channel transfer, the slave can simply hold WREADY low for that amount of cycles.
Register Slices are there to break timing long paths, so adding up to a couple of clock cycles of latency depending on the design, but not 15.
You can add buffers in some ARM interconnects to data channels, but these will still try to pass the data from source to destination as soon as possible, so just adding one cycle of registering before making the data available to the destination device. Write data channel buffers can have something called "tidemark" levels which will stall the buffered write data until sufficient write data is buffered, or until the WLAST data transfer, but again not really guaranteeing any 15 cycle requirement.
So I would suggest that the component needing the 15 cycle delay should use the available READY and VALID handshake signals to implement the delay, unless you can explain why that isn't possible in your system, and what is driving this requirement.
JD
Thank you so much for your replies.
I am using memory controller block(Xilinx) and I need to delay the read and writes for 15 clock cycles so that I can modify the data being written to memory. Xilinx uses AXI bus . So I was thinking to delay the data when present in AXI bus. I have tried to delay the reading and writing but it has corrupted the data. I need to know where can I delay the data in AXI bus. And I have not made register slice myself . I was using the inbuilt AXI register slice to do so.
Also as said by you if i try to delay the data between aw and w channel. Then how will my system behave under burst mode. Because according to me in burst mode aw channel will be utilised once. As consecutive addresses will be calculated by the axi itself.and therefore i wont be able provide delay to each data in burst mode.
All suggestions are welcome
Regards
Preet
Sir
I am new to the AXI.
"You should make the timer trigger from the first read response."
Does this mean that I have to start the counter when the done signal is high for the first read?
or
I should start the counter when,
count = arvalid & arready goes high..
then i should mask the rvalid and rready.
I am not able to understand the timing adjustments I have to make between these four signals.
And the difference between delaying procedure in read and write. I have been able to delay in write as per told by you. It worked
Hi Preet,I mean the timing will be like below.
Also, both RVALID and RREADY should be masked by the mask signal.Best regards,Yasuhiko Koumoto.
i have tried it but not been able to make it.
I have done the following changes to delay my every read by 15 clock cycles.
assign count=arready&arvalid
if(count)
addr_done<=1
else if(rvalid & rready_new & rlast)
addr_done <=0
always@(posedge clk)
begin
assign valid =((~rd_empty_d1 & ~rhandshake_d1) | rd_count_gt_2) & ~mask;
assign rready_new = rready & ~mask
if (addr_done & rvalid & rready_new)
case(state_delay)
0: begin
mask <=1;
state_delay<=1;
end
1: begin
state_delay<=2;
2: begin
state_delay<=3;
3: begin
state_delay<=4;
4: begin
state_delay<=5;
5:begin
state_delay<=6;
6: begin
state_delay<=7;
7: begin
state_delay<=8;
8: begin
state_delay<=9;
9: begin
state_delay<=10;
10: begin
state_delay<=11;
11: begin
state_delay<=12;
12: begin
state_delay<=13;
13: begin
state_delay<=14;
14: begin
state_delay<=15;
15: begin
rdata_changed<=rd_data + 1'b1; //for debugging
state_delay<=16;
16:begin
state_delay <= 0;
mask <= 0;
endcase
I dont know where am I going wrong.
kindly help.
regards
Preet Kaur Walia
Hello Preet Kaur Walia,
I think if (addr_done & rvalid & rready_new)would be wrong.The count start trigger should be the rising edge of "rvalid & rready".Therefore, the if statement should be replaced withif (addr_done & ~delayed_rvalid_rready & (rvalid_pre_mask & rready_pre_mask)).Here,awalways@(posedge clk) delayed_rvalid_rready <= rvalid_pre_mask & rready_pre_mask;
Best regards,Yasuhiko Koumoto.
the statement
if (addr_done & ~delayed_rvalid_rready & (rvalid_pre_mask & rready_pre_mask))
How will this statement be responsible for checking the rising edge of the ready and valid signals.
Instead can i do this:
dealyed_rvalid_rready<=rvalid & rready;
always@(posedge clk or posedge count_in)
case(state)
if (count_in)
addr_done<=1;
state <= 1;
else
addr_done<=0;
state<=0;
if (rvalid_i & rready & rlast)
state <= 0;
always@(posedge clk or dealyed_rvalid_rready)
if ( addr_done & dealyed_rvalid_rready)
mask <=1;//provide delay as required by masking
state_delay<=0;
mask <=0;//stop the masking
Hi Preet Kaur Walia,
I think your HDL description would generate the latch instead of the flip-flop. Is it OK?
Honestry speaking, I cannot understnd your HDL.
Is it working well?
Best regards,
Yasuhiko Koumoto.
No sir
Even after using the code below I am able to read the value written to previous address .
For example if i try to read 0x11111111 of my memory I read the value written to 0x11111110.I am using AXI bus to read.
assign count_in = arvalid and arready;
always@(posedge clk) //as suggested by you
delayed_rvalid_rready<=rvalid_i & rready;
always@(posedge clk )
if ( addr_done & ~dealyed_rvalid_rready & (rvalid_i & rready))
mask <=0;
1:begin
mask <=1;///so on for 15 cycle
15:
rdata_delayed<=rd_data ;
mask<=0;
first of all,
"For example if i try to read 0x11111111 of my memory I read the value written to 0x11111110.I am using AXI bus to read. "
would be impossible.
There is possibility to read the data before being written at 0x11111111.
This time, there is no consideration of such the read-after-write problem.
I think that there seems be some misunderstandings.
My proposal is to insert 15 cycle delay one time for one read or write transaction. It seems that you want to insert 15 cycle delay for each data cycle.
Please show us your timing diagram instead of HDL descriptions.
By the way, what is the number of outstandings by your master?
I only consider the number of outstandings is one.
Yes for each data cycle I want to add the delay for read and write transaction. For example in burst mode if I read 64 data words from memory. I want each of the read to be delayed by 15 clock cycles. As of the timing diagrams is considered I was following the timing provided by you to achieve the situation for read and write.
For write, the circuit diagram provided by you works for delaying each write(each datapath write and not one complete write transaction containing several data words written but delay to each dataword) by 15 clock cycles but the same is not happening for read(I am following your timing diagram.)
As I have understandood the outstandings by master(heer Mmeory controller block) are the number of transactions to and from the AXI bus can be any number. But maximum number can be 64 data words can be written in single burst. Each dataword width is 64 bits. First of all I want to know the timing diagram you have provided for read will not delay each read dataword? As of now I am assuming my HDL is wrong.
Preet Kaur
As you can see from timing diagram. I am trying to delay my read transaction(every data word in one read transaction) .As rvald and rready posedge arrives I began to mask the rvalid and rready for 15 cycles. For example in diagram below for burst read containing 3 dataword reads I mask the signals thrice and finsh off when rlast arrives. Kindly let me know if this is the correct way to delay each read dataword. My prime motive is to modify each dataword being written to memory.(in the dealy I am providing).
thank you for the confirmation.My previous idea is wrong because a master will accept the first data response without delay.I think the desired timing would be as following.
To realize the timing I would like to the Verilog descriptions like below.
always@(posedge CLK) begin if(~ARESETN) ADDR_DONE <= 0; else if(ARVALID&masked_ARREADY) ADDR_DONE <= 1; else if(RLAST&RVALID&RREADY) ADDR_DONE <= 0; end akways@(posedge CLK) begin if(~ARESETN) FIRST_DATA_MASK <= 0; else if(ARVALID&masked_ARREADY) FIRST_DATA_MASK <= 1; else if(ADDR_DONE&RVALID&RREADY) FIRST_DATA_MASK <= 0; end akways@(posedge CLK) begin if(~ARESETN) counter <= 4'h0; else if(ADDR_DONE&masked_RVALID&masked_RREADY) counter <= 4'hf; else if(counter!=4'h0) coubter <= counter -1 ; end assign mask_pre = (couner != 4'h0); assign RVALID_mask = FIRST_DATA_MASK | mask_pre; assign RREADY_mask = mask_pre; assign masked_RVALID = RVALID & ~RVALID_mask; // RVALID for master assign masked_RREADY = READY & ~RREADY_mask; // RREADY for slave assign masked_ARREADY = ~ADDR_DONE & ARREADY; // this make outstanding 1
HTH,Yasuhiko Koumoto.
hankyou sir .
I have a few doubts
Firstly,the write circuit you sent to me..will be applicable for delaying each dataword in a write transaction(same situation as read).
Also I am not able to understand the cpncepr of arready.
from what I have understood
assign masked_ARREADY = ~ADDR_DONE & ARREADY; // this make outstanding 1
This masked_arready will be used by used to mask arready or just in the always block you have described in your code?
I am not able to understand this statement. further I have understood the working.
No, it were not. The write logics insert 15 cycle delay one time.However, my new logics which were shown by HDL in the read case will be applicable to the write channel. I think by replacing 'R' for 'W', it will be OK.
This masked_arready will be used by used to mask arready or just in the always block you have described in your code? I am not able to understand this statement.
The aim of the code is to limit the number of read outstandings to one.If the master would issue more than one read addresses before responding the first data, the basic assumption of my logics would be destroyed.
As you can see from the diagram I have taken from the manual of AMBAaxi it states that overlapping read bursts can occur(second address can be sent) without the first data being read back. I have thought of an alternative to this option:
shall i stop the handshaking
axhandshake=arvalid & arready;
instaed
axhandshake=arvalid & mask_arready;
I shall mask arready such that handshaking is not possible.
Also by making outstanding one you mean that the master cannot send second address before first data from first read transaction is read back?
Yes, you shall.
Also by making outstanding one you mean that the master cannot send second address before first data from first
read transaction is read back?
Yes, it does.
I am working on the read and write as per your suggestions.
The read is working fine but write is not.
As you mentioned the write will work similarly but it does not.
If I do a single write it is getting written on memory without delay(I am assuming the first data mask is not working for it)
Burst is not working.
in the write case, you should swap the meaning of data READY and VALID.That is, RREADY to WVALID and RVALID to WREADY conversions will be needed.
always@(posedge CLK) begin if(~ARESETN) WADDR_DONE <= 0; else if(AWVALID&masked_AWREADY) WADDR_DONE <= 1; else if(BVALID&BREADY) WADDR_DONE <= 0; end always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 0; else if(AWVALID&masked_AWREADY) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE&WVALID&WREADY) FIRST_WDATA_MASK <= 0; end always@(posedge CLK) begin if(~ARESETN) wcounter <= 4'h0; else if(WADDR_DONE&masked_WVALID&masked_WREADY) wcounter <= 4'hf; else if(wcounter!=4'h0) wcoubter <= wcounter -1 ; end assign mask_pre = (wcouner != 4'h0); assign WREADY_mask = FIRST_WDATA_MASK | mask_pre; // CHANGE! assign WVALID_mask = mask_pre; // CHANGE! assign masked_WVALID = WVALID & ~WVALID_mask; // RVALID for master assign masked_WREADY = WREADY & ~WREADY_mask; // RREADY for slave assign masked_AWREADY = ~WADDR_DONE & AWREADY; // this make outstanding 1
The write is still not working.
i have a doubt. According to the timing you have assumed it states that during a write transaction the wvalid will be asserted after awready.
But in the manual ambaaxi it has been quoted that "
It is important that during a write transaction, a master must not wait for AWREADY
to be asserted before driving WVALID. This could cause a deadlock condition if the
slave is conversely waiting for WVALID before asserting AWREADY.
"
Then the logic would fade.
Hello Preet Kaur Walia.
I am sorry. I forget the current First_WDATA_Mask would be too late to stop the first data cycle.
I think that if the reset value of First_WDATA_Mask was '1' and it would become '1' at every writing done (BVALID&BREADY), it might go well.
always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; else if(BREADY&BVALID) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE&WVALID&WREADY) FIRST_WDATA_MASK <= 0; end
I have done the following change to the code and it seems to work.
As we donot know that awready will be high before or after wvalid. Therefore there is possibility that first data mask will remain 1 as this condirion may not get true
the changed code
I doubt your suspicion (or maybe experiment result?) "if(WADDR_DONE&WVALID&WREADY)" might not become true because WVALID and WREADY should independent according to "A3.3.1 Dependencies between channel handshake signals" of AXI specs.
Actually, there would be some wrong scenarios with your implementation of "else if(WADDR_DONE & WREADY)" and the reset value was '0'.
If First_WDATA_Mask reset value was '0', it cannot handle the following scenario.
I think almost all case would be the <2> timing.
And "else if(WADDR_DONE & WREADY)" would not handle the following scenario.
This would be the same situation with "else if(WADDR_DONE & WVALID)".
So, I would like to propose the following description.
always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; // new change else if(AWVALID & masked_AWREADY) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE & WREADY & WVALID) // should not change FIRST_WDATA_MASK <= 0; end
How about this?
Otherwize.
always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; // new change else if(AWVALID & masked_AWREADY) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE & (wcount==4'hf)) // new change FIRST_WDATA_MASK <= 0; end
None of the solutions seem to work and I am not able to figure out the reason.
it's sad news.By the way, you said that if the following logic was used, it went well.
always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 0; else if(AWVALID & masked_AWREADY) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE & WREADY) //change FIRST_WDATA_MASK <= 0; end
If it is correct, I guess that your master would not assert WVALID until getting WREADY from the slave. But it would violate the AXI specs.Can you confirm it?If you can confirm it, I should compromise the description above.To the contrary, if your slave would not assert WREADY until getting WVALID from the master, "else if(WADDR_DONE & WREADY)" would be replaced for "else if(WADDR_DONE & WVALID)".
By the way, I have found something was wrong."else if(AWVALID&masked_AWREADY)" would be strange (also in the read case).I'm sorry but I think masked_AWREADY should be AWREADY.
I am afraind WADDR_DONE would not become "1" with the previous description.Therefore, the logics would be the following.
always@(posedge CLK) begin if(~ARESETN) WADDR_DONE <= 0; else if(AWVALID&AWREADY) WADDR_DONE <= 1; else if(BVALID&BREADY) WADDR_DONE <= 0; end always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; else if(AWVALID&AWREADY) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE&(wcounter==4'hf)) FIRST_WDATA_MASK <= 0; end always@(posedge CLK) begin if(~ARESETN) wcounter <= 4'h0; else if(WADDR_DONE&masked_WVALID&masked_WREADY) wcounter <= 4'hf; else if(wcounter!=4'h0) wcoubter <= wcounter -1 ; end assign mask_pre = (wcouner != 4'h0); assign WREADY_mask = FIRST_WDATA_MASK | mask_pre; // CHANGE! assign WVALID_mask = mask_pre; // CHANGE! assign masked_WVALID = WVALID & ~WVALID_mask; // RVALID for master assign masked_WREADY = WREADY & ~WREADY_mask; // RREADY for slave assign masked_AWREADY = ~WADDR_DONE & AWREADY; // this make outstanding 1
How about them?I'm sorry for you inconvenience.
The condition
always@(posedge CLK) begin
if(~ARESETN)
FIRST_WDATA_MASK <= 1; // new change
else if(AWVALID & masked_AWREADY)
FIRST_WDATA_MASK <= 1;
else if(WADDR_DONE & WREADY)
FIRST_WDATA_MASK <= 0;
should work fine considering that wvalid and wready need not be high together. Therefore, it might be possible that wvalid has gone high for a clock cycle and aftersometime wready goes high. Data mask should go low after that. Therefore it would not deviate from the AXI specification.
Hello,
if the releasing the FIRST_WDATA_MASK only by WREADY made your system working fine, it's a good news.I think the characteristic of "wvalid has gone high for a clock cycle and aftersometime wready goes high" would be strange because the assertions (i.e. go to High) WVALID and WREADY should be independent.If the master makes WVALID high before the slave makes WREADY high, the FIRST_WDATA_MASK logic cannot stop the data cycle.The logic will only go well if the WVAID of the master will go high after the slave would make WREADY high.Anyway, there would be the timing WVALID and WREADY will be High at the same and I wonder why "WADDR_DONE & WVALID & WREADY" would be wrong for de-asserting FIRST_WDATA_MASK.The only possibility would be WADDR_DONE was '0' at the timing when "WVALID & WREADY" was '1'. These are the cases <1> and <2> of my previous post.I will propose the new condition for releasing FIRST_WDATA_MASK.Could you please try it?
always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; // new change else if(AWVALID & AWREADY) FIRST_WDATA_MASK <= ~(WVALID & WREADY); else if(WADDR_DONE & WVALID & WREADY) FIRST_WDATA_MASK <= 0; end
Best regards,Yauhiko Koumoto.
I am working on it. Also I had a query that in the write case ,
According to me the following scenario should be followed:
We should mask wvalid as we need to stop the wvalid from the CPU from going to the slave otherwise, it will do the write transaction as and when wvalid is high.Slave will then send wready (telling the CPU it is ready to accept more data).
Whereas we are working on the contrary. As it can be seen from the first data mask situation, wready is being masked and wvalid is being sent to the slave. Therefore, there is a possibilty that slave has already written the data to memory before we are providing the delay. (in the first data mask situation we are only masking the wready)
Slave will then send wready (telling the CPU it is ready to accept more data).
This is not right. It has possibility of deadlock. The wvalid and wready should be independent.
Whereas we are working on the contrary.
No, we consider two cases which wvalid is faster than wready and wready is faster than wvalid.
wready is being masked and wvalid is being sent to the slave.
I'm sorry. You are right.assign WVALID_mask = mask_pre;would be alsoassign WVALID_mask = FIRST_WDATA_MASK | mask_pre;
It does not work .
I am very sorry for your inconvenience.
I have debugged and verified the codes on a real simulation environment.
I have observed that they had went very well,
I hope this will help you.
module AXI_W_DELAY15( CLK, ARESETN, AWVALID, // from a master AWREADY, // from a slave WVALID, // from a master WREADY, // from a slave BVALID, // from a slave BREADY, // from a master WLAST, // from a master masked_WVALID, // to a slave masked_WREADY, // to a master masked_AWREADY // to a master ); input CLK; input ARESETN; input AWVALID; input AWREADY; input WVALID; input WREADY; input BVALID; input BREADY; input WLAST; output masked_WVALID; output masked_WREADY; output masked_AWREADY; reg WADDR_DONE; reg FIRST_WDATA_MASK; reg [3:0] wcounter; wire mask_pre; wire WREADY_mask; wire WVALID_mask; always@(posedge CLK) begin if(~ARESETN) WADDR_DONE <= 0; else if(~WADDR_DONE & AWVALID & AWREADY) WADDR_DONE <= 1; else if(BVALID & BREADY) WADDR_DONE <= 0; end always@(posedge CLK) begin if(~ARESETN) FIRST_WDATA_MASK <= 1; else if(WADDR_DONE & (wcounter==4'hf)) FIRST_WDATA_MASK <= 0; else if(wcounter==4'h0) FIRST_WDATA_MASK <= 1; end always@(posedge CLK) begin if(~ARESETN) wcounter <= 4'h0; else if(wcounter!=4'h0) wcounter <= wcounter -1 ; else if(WADDR_DONE & WVALID & WREADY & ~(WLAST & masked_WREADY)) //!! wcounter <= 4'hf; end assign mask_pre = (wcounter != 4'h0); assign WREADY_mask = FIRST_WDATA_MASK | mask_pre; assign WVALID_mask = FIRST_WDATA_MASK | mask_pre; assign masked_WVALID = WVALID & ~WVALID_mask; // WVALID for master assign masked_WREADY = WREADY & ~WREADY_mask; // WREADY for slave assign masked_AWREADY = ~WADDR_DONE & AWREADY; // this make outstanding 1 endmodule module AXI_R_DELAY15( CLK, ARESETN, ARVALID, // from a master ARREADY, // from a slave RVALID, // from a slave RREADY, // from a master RLAST, // from a master masked_RVALID, // to a master masked_RREADY, // to a slave masked_ARVALID,// to a slave masked_ARREADY // to a master ); input CLK; input ARESETN; input ARVALID; input ARREADY; input RVALID; input RREADY; input RLAST; output masked_RVALID; output masked_RREADY; output masked_ARVALID; output masked_ARREADY; reg RADDR_DONE; reg FIRST_RDATA_MASK; reg [3:0] rcounter; reg next_rlast; reg next2_rlast; reg RVALID_delay; reg done_raddr; wire rmask_pre; wire RREADY_mask; wire RVALID_mask; always@(posedge CLK) begin if(~ARESETN) begin next_rlast <= 0; next2_rlast <= 0; done_raddr <= 0; end else begin next_rlast <= (rcounter == 4'h1); next2_rlast <= next_rlast; done_raddr <= RLAST & masked_RREADY; end end always@(posedge CLK) begin if(~ARESETN) RADDR_DONE <= 0; else if(~RADDR_DONE & ARVALID & masked_ARREADY) RADDR_DONE <= 1; else if(done_raddr & (next2_rlast & ~(RVALID & ARVALID & ARREADY))) //!!! RADDR_DONE <= 0; end always@(posedge CLK) begin if(~ARESETN) FIRST_RDATA_MASK <= 0; else if(ARVALID & masked_ARREADY) FIRST_RDATA_MASK <= 1; else if(rcounter==4'hf) FIRST_RDATA_MASK <= 0; end always@(posedge CLK) begin if(~ARESETN) rcounter <= 4'h0; else if(rcounter!=4'h0) rcounter <= rcounter -1 ; else if(RADDR_DONE & RVALID & RREADY & ~next_rlast) //!! rcounter <= 4'hf; end assign rmask_pre = (rcounter != 4'h0); assign RREADY_mask = FIRST_RDATA_MASK | rmask_pre | next2_rlast; assign RVALID_mask = FIRST_RDATA_MASK | rmask_pre | next2_rlast; assign masked_RVALID = RVALID & ~RVALID_mask; // WVALID for master assign masked_RREADY = RREADY & ~RREADY_mask; // WREADY for slave assign masked_ARREADY = ~RADDR_DONE & ARREADY; // this make outstanding 1 assign masked_ARVALID = ~RADDR_DONE & ARVALID; // this make outstanding 1 endmodule
View all questions in Cortex-A / A-Profile forum