Hello Filip_Gherman AdrianC and Team ,
I am using ADI product ADRV9008-1W with ZCU102 and 2021_r1 HDL design. According to our need the design is modified in such a way that AXI_ADCFIFO and MIG controller is added so that DMA can have continous RF data from the RF frontend. Now, as the design advances we need to extract the saved data in a repetitive manner from DDR4 through MIG controller and direct to one of our IP core. The custom IP core will control when the frame ends and after that should start again from starting base address.For this purpose modified AXI_DACFIFIO is desgined, where only *_rd.v is used. Smartconnect from xilinx is used to which connects AXI_ADCFIFO and modified AXI_DACFIFO to the MIG Controller. Now the data can be successfully retrieved from AXI_ADCFIFO and sent to axi_dmac. From there the MATLAB can verify the correctness of data. The problem arises where the modified AXI_DACFIFO(AXI_DATAEXTACTOR in fig.) tries to read the data. The IQ samples at the end of the data (seen in ILA) does not verify with MATLAB. MATLAB and ILA shows the same RF data at the time. For this particular problem I want to ask
1. In AXI_ADCFIFO IP core this formula is used AXI_AWINCR = AXI_LENGTH * AXI_BYTE_WIDTH whereas in AXI_DACFIFO this formula is used AXI_AWINCR = (AXI_LENGTH + 1) * AXI_BYTE_WIDTH. I concur that ADCFIFO IP utilizes AXI3 protocol and DACFIFIO AXI4. Does this difference could arise the wrong reading of data from modified AXI_DACFIFIO IP core?
2. AXI_SIZE is the size of data to be transferred. DDR4 in ZCU102 has 128 bits. This translates to 2^n where n in this case is 4. In Axi_ADCFIFO AXI_LENGTH is configured as 4. So that means that in a burst it writes 4*(2^4) bytes in the memory(DDR4). Should modified AXI_DACFIO also have the same axi_length config. or it can also be configured for more , for e.g 32 or 64?
How AXI_Length impacts the buffer memory composed of BRAM in DACFIFO?
How one can calculate ideal AXI_LENGTH?
3. Here is the modified code
`timescale 1ns/100ps module axi_dataextractor #( parameter DAC_DATA_WIDTH = 64, parameter AXI_DATA_WIDTH = 128, parameter AXI_SIZE = 4, parameter AXI_LENGTH = 4, parameter AXI_ADDRESS = 32'h80000000, parameter AXI_ADDRESS_LIMIT = 32'h9fffffff, parameter AXI_LAST_ADDR = 32'h80012C50 ) ( // dac interface input dac_clk, input dac_rst, input dac_valid, input axi_xfer_req_s, output reg [(DAC_DATA_WIDTH-1):0] dac_data, output reg dac_dunf, output reg dac_xfer_out, // axi interface input axi_clk, input axi_resetn, output axi_awvalid, output [ 3:0] axi_awid, output [ 1:0] axi_awburst, output axi_awlock, output [ 3:0] axi_awcache, output [ 2:0] axi_awprot, output [ 3:0] axi_awqos, output [ 7:0] axi_awlen, output [ 2:0] axi_awsize, output [ 31:0] axi_awaddr, input axi_awready, output axi_wvalid, output [(AXI_DATA_WIDTH-1):0] axi_wdata, output [(AXI_DATA_WIDTH/8-1):0] axi_wstrb, output axi_wlast, input axi_wready, input axi_bvalid, input [ 3:0] axi_bid, input [ 1:0] axi_bresp, output axi_bready, output axi_arvalid, output [ 3:0] axi_arid, output [ 1:0] axi_arburst, output axi_arlock, output [ 3:0] axi_arcache, output [ 2:0] axi_arprot, output [ 3:0] axi_arqos, output [ 7:0] axi_arlen, output [ 2:0] axi_arsize, output [ 31:0] axi_araddr, input axi_arready, input axi_rvalid, input [ 3:0] axi_rid, input [ 1:0] axi_rresp, input axi_rlast, input [(AXI_DATA_WIDTH-1):0] axi_rdata, output axi_rready, output axi_rerror, // Debug output output [4:0] fsm_dacfifio_deb, output [31:0] last_raddr_deb, output [31:0] axi_araddr_deb, output [8:0] axi_arincr_deb, output axi_rready_deb, output axi_rrvalid_deb, output axi_rrlast_deb, output reg axi_xfer_req_deb, output axi_fifo_rst_deb ); reg axi_xfer_req_m_s1; reg axi_xfer_req_m; (* dont_touch = "true" *) wire [31:0] axi_last_addr_s ; (* dont_touch = "true" *) wire [ 7:0] axi_last_beats_s; reg [ 3:0] dma_last_beats_s = 4'b0000; wire [(DAC_DATA_WIDTH-1):0] dac_data_fifo_s; wire [(DAC_DATA_WIDTH-1):0] dac_data_bypass_s; wire dac_xfer_fifo_out_s; wire dac_dunf_fifo_s; wire dac_dunf_bypass_s; localparam AXI_BYTE_WIDTH = AXI_DATA_WIDTH/8; localparam AXI_ARINCR = (AXI_LENGTH + 1) * AXI_BYTE_WIDTH; assign axi_last_addr_s = AXI_LAST_ADDR & (~AXI_ARINCR + 1); assign axi_last_beats_s = AXI_LENGTH; // setting deafult values for Write channel. In our case, // the write channel should be disabled. assign axi_awvalid = 1'b0; assign axi_awid = 4'b0000; assign axi_awburst = 2'b01; // INCR (Incrementing address burst) assign axi_awlock = 1'b0; // Normal access assign axi_awcache = 4'b0010; // Cacheable, but not allocate assign axi_awprot = 3'b000; // Normal, secure, data access assign axi_awqos = 4'b0000; // Not used assign axi_awlen = AXI_LENGTH; assign axi_awsize = AXI_SIZE; assign axi_awaddr = AXI_ADDRESS; assign axi_wvalid = 1'b0; assign axi_wdata = {128{1'b0}}; assign axi_wstrb = {AXI_BYTE_WIDTH{1'b1}}; assign axi_wlast = 1'b0; assign axi_bready = 1'b0; axi_dataextractor_rd #( .AXI_DATA_WIDTH (AXI_DATA_WIDTH), .AXI_SIZE (AXI_SIZE), .AXI_LENGTH (AXI_LENGTH), .AXI_ADDRESS (AXI_ADDRESS), .DAC_DATA_WIDTH (DAC_DATA_WIDTH), .DAC_MEM_ADDRESS_WIDTH (12) ) i_rd ( .axi_xfer_req (axi_xfer_req_m_s1), .axi_last_raddr (axi_last_addr_s), .axi_last_beats (axi_last_beats_s), .axi_clk (axi_clk), .axi_resetn (axi_resetn), .axi_arvalid (axi_arvalid), .axi_arid (axi_arid), .axi_arburst (axi_arburst), .axi_arlock (axi_arlock), .axi_arcache (axi_arcache), .axi_arprot (axi_arprot), .axi_arqos (axi_arqos), .axi_arlen (axi_arlen), .axi_arsize (axi_arsize), .axi_araddr (axi_araddr), .axi_arready (axi_arready), .axi_rvalid (axi_rvalid), .axi_rid (axi_rid), .axi_rresp (axi_rresp), .axi_rlast (axi_rlast), .axi_rdata (axi_rdata), .axi_rready (axi_rready), .axi_rerror (axi_rerror), .dma_last_beats (dma_last_beats_s), .dac_clk (dac_clk), .dac_rst (dac_rst), .dac_valid (dac_valid), .dac_data (dac_data_fifo_s), .dac_xfer_out (dac_xfer_fifo_out_s), .dac_dunf (dac_dunf_fifo_s), .fsm_dacfifio_deb(fsm_dacfifio_deb), .last_raddr_deb(last_raddr_deb), .axi_araddr_deb(axi_araddr_deb), .axi_arincr_deb(axi_arincr_deb), .axi_rready_deb(axi_rready_deb), .axi_rrvalid_deb(axi_rrvalid_deb), .axi_rrlast_deb(axi_rrlast_deb), .axi_fifo_rst_deb(axi_fifo_rst_deb) ); /* if (~FIFO_BYPASS) */ always @(posedge dac_clk) begin if (dac_valid) begin dac_data <= dac_data_fifo_s; end dac_xfer_out <= dac_xfer_fifo_out_s; dac_dunf <= dac_dunf_fifo_s; end always @(posedge axi_clk) begin axi_xfer_req_m <= axi_xfer_req_s; axi_xfer_req_m_s1 <= axi_xfer_req_m; axi_xfer_req_deb <= axi_xfer_req_m_s1; end endmodule
In this I have removed DMA and dacfifo_wr.v logic as I am only interested in reading from MM part and then sending the readed Data through a different lower clock. The axi_xfer_req_s signal comes from my custom IP core @122.88 MHz and as a result CDC so that it can register to AXI clock which is connected to MIG UI clk port. Other than that dacfifo_rd.v is untouched and no modification is done there. I am having trouble with three signals namely : axi_last_addr_s, axi_last_beats_s and dma_last_beats_s. With which deafult value should I initialize them? In my custom IP core I control axi_xfer_req_s in such a way that when counter reaches a demanded IQ samples value then the signal is put to LOW for a single clock and then again to HIGH so that I can again read the same value from starting address of the RAM.
4. If AXI_ADCFIFO only operates on AXI3 then how AXI_DMAC gets the right IQ samples and MATLAB decodes it correct whereas modified AXI_DACFIFO is not able to?
Thank you in advance.
With regards,
Added former thread members
[edited by: FPGA@noob at 8:52 AM (GMT -4) on 24 Mar 2023]