diff --git a/library/axi_dacfifo/axi_dacfifo.v b/library/axi_dacfifo/axi_dacfifo.v index 01f140e0a..f6b3ccc96 100644 --- a/library/axi_dacfifo/axi_dacfifo.v +++ b/library/axi_dacfifo/axi_dacfifo.v @@ -196,6 +196,7 @@ module axi_dacfifo ( wire axi_rd_valid_s; wire [31:0] axi_rd_lastaddr_s; wire axi_xfer_req_s; + wire [31:0] dma_last_addr_s; wire [(DAC_DATA_WIDTH-1):0] dac_data_s; wire dma_ready_s; @@ -217,6 +218,7 @@ module axi_dacfifo ( .dma_xfer_req (dma_xfer_req), .dma_xfer_last (dma_xfer_last), .axi_last_raddr (axi_rd_lastaddr_s), + .dma_last_addr (dma_last_addr_s), .axi_xfer_out (axi_xfer_req_s), .axi_clk (axi_clk), .axi_resetn (axi_resetn), @@ -289,6 +291,7 @@ module axi_dacfifo ( .axi_ddata (axi_rd_data_s), .axi_dready (axi_rd_ready_s), .axi_xfer_req (axi_xfer_req_s), + .dma_last_addr (dma_last_addr_s), .dac_clk (dac_clk), .dac_rst (dac_rst), .dac_valid (dac_valid), diff --git a/library/axi_dacfifo/axi_dacfifo_dac.v b/library/axi_dacfifo/axi_dacfifo_dac.v index 44a47ea1f..3aeeb3d94 100644 --- a/library/axi_dacfifo/axi_dacfifo_dac.v +++ b/library/axi_dacfifo/axi_dacfifo_dac.v @@ -47,6 +47,8 @@ module axi_dacfifo_dac ( axi_dready, axi_xfer_req, + dma_last_addr, + dac_clk, dac_rst, dac_valid, @@ -67,8 +69,13 @@ module axi_dacfifo_dac ( (MEM_RATIO == 2) ? (DAC_ADDRESS_WIDTH - 1) : (MEM_RATIO == 4) ? (DAC_ADDRESS_WIDTH - 2) : (DAC_ADDRESS_WIDTH - 3); - localparam BUF_THRESHOLD_LO = 8'd32; - localparam BUF_THRESHOLD_HI = 8'd240; + + // BUF_THRESHOLD_LO will make sure that there are always at least two burst in the memmory + localparam AXI_BUF_THRESHOLD_LO = 3 * (AXI_LENGTH+1); + localparam AXI_BUF_THRESHOLD_HI = {(AXI_ADDRESS_WIDTH){1'b1}} - (AXI_LENGTH+1); + localparam DAC_BUF_THRESHOLD_LO = 3 * (AXI_LENGTH+1) * MEM_RATIO; + localparam DAC_BUF_THRESHOLD_HI = {(DAC_ADDRESS_WIDTH){1'b1}} - (AXI_LENGTH+1) * MEM_RATIO; + localparam DAC_ARINCR = (AXI_LENGTH+1) * MEM_RATIO; // dma write @@ -78,6 +85,8 @@ module axi_dacfifo_dac ( output axi_dready; input axi_xfer_req; + input [32:0] dma_last_addr; + // dac read input dac_clk; @@ -89,34 +98,44 @@ module axi_dacfifo_dac ( // internal registers - reg [(AXI_ADDRESS_WIDTH-1):0] axi_waddr = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] axi_waddr_g = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] axi_raddr = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] axi_raddr_m = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] axi_addr_diff = 'd0; + reg [(AXI_ADDRESS_WIDTH-1):0] axi_mem_waddr = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] axi_mem_waddr_g = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] axi_mem_raddr = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] axi_mem_raddr_m = 'd0; + reg [(AXI_ADDRESS_WIDTH-1):0] axi_mem_addr_diff = 'd0; reg axi_dready = 'd0; - reg axi_almost_full = 1'b0; - reg axi_dwunf = 1'b0; - reg axi_almost_empty = 1'b0; - reg dac_rd = 'd0; - reg dac_rd_d = 'd0; - reg [(DAC_DATA_WIDTH-1):0] dac_rdata_d = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] dac_raddr = 'd0; - reg [(DAC_ADDRESS_WIDTH-1):0] dac_raddr_g = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_next = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_g = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_m = 'd0; + reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_addr_diff = 'd0; + reg dac_mem_init = 1'b0; + reg dac_mem_init_d = 1'b0; + reg dac_mem_enable = 1'b0; - reg [ 2:0] dac_dunf_m = 3'b0; reg [ 2:0] dac_xfer_req_m = 3'b0; + reg dac_xfer_init = 1'b0; + + reg [31:0] dac_raddr_cnt = 32'b0; + reg [31:0] dac_last_raddr = 32'b0; + reg [31:0] dac_last_raddr_m = 32'b0; + reg dac_almost_full = 1'b0; + reg dac_almost_empty = 1'b0; + reg dac_dunf = 1'b0; // internal signals - wire [DAC_ADDRESS_WIDTH:0] axi_addr_diff_s; - wire [(DAC_ADDRESS_WIDTH-1):0] axi_waddr_s; - wire dac_wready_s; - wire dac_rd_s; - wire [(DAC_DATA_WIDTH-1):0] dac_rdata_s; + wire [AXI_ADDRESS_WIDTH:0] axi_mem_addr_diff_s; + wire [(AXI_ADDRESS_WIDTH-1):0] axi_mem_raddr_s; + wire [(DAC_ADDRESS_WIDTH-1):0] axi_mem_waddr_s; - wire dac_valid_s; + wire [DAC_ADDRESS_WIDTH:0] dac_mem_addr_diff_s; + wire [DAC_ADDRESS_WIDTH:0] dac_mem_raddr_diff_s; + wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_s; + wire dac_mem_valid_s; + wire dac_xfer_init_s; // binary to grey conversion @@ -158,83 +177,136 @@ module axi_dacfifo_dac ( always @(posedge axi_clk) begin if (axi_xfer_req == 1'b0) begin - axi_waddr <= 'd0; - axi_waddr_g <= 'd0; + axi_mem_waddr <= 'd0; + axi_mem_waddr_g <= 'd0; end else begin if (axi_dvalid == 1'b1) begin - axi_waddr <= axi_waddr + 1'b1; + axi_mem_waddr <= axi_mem_waddr + 1'b1; end - axi_waddr_g <= b2g(axi_waddr_s); + axi_mem_waddr_g <= b2g(axi_mem_waddr_s); end end - // underflow / overflow + // scale the axi_mem_* addresses - assign axi_addr_diff_s = {1'b1, axi_waddr_s} - axi_raddr; - assign axi_waddr_s = (MEM_RATIO == 1) ? axi_waddr : - (MEM_RATIO == 2) ? {axi_waddr, 1'd0} : - (MEM_RATIO == 4) ? {axi_waddr, 2'd0} : - {axi_waddr, 3'd0}; + assign axi_mem_raddr_s = (MEM_RATIO == 1) ? axi_mem_raddr : + (MEM_RATIO == 2) ? axi_mem_raddr[(DAC_ADDRESS_WIDTH-1):1] : + (MEM_RATIO == 4) ? axi_mem_raddr[(DAC_ADDRESS_WIDTH-1):2] : + axi_mem_raddr[(DAC_ADDRESS_WIDTH-1):3]; + assign axi_mem_waddr_s = (MEM_RATIO == 1) ? axi_mem_waddr : + (MEM_RATIO == 2) ? {axi_mem_waddr, 1'b0} : + (MEM_RATIO == 4) ? {axi_mem_waddr, 2'b0} : + {axi_mem_waddr, 3'b0}; + + // incomming data flow control + + assign axi_mem_addr_diff_s = {1'b1, axi_mem_waddr} - axi_mem_raddr_s; always @(posedge axi_clk) begin if (axi_xfer_req == 1'b0) begin - axi_addr_diff <= 'd0; - axi_raddr <= 'd0; - axi_raddr_m <= 'd0; + axi_mem_addr_diff <= 'd0; + axi_mem_raddr <= 'd0; + axi_mem_raddr_m <= 'd0; axi_dready <= 'd0; - axi_almost_full <= 1'b0; - axi_dwunf <= 1'b0; - axi_almost_empty <= 1'b0; end else begin - axi_raddr_m <= g2b(dac_raddr_g); - axi_raddr <= axi_raddr_m; - axi_addr_diff <= axi_addr_diff_s[DAC_ADDRESS_WIDTH-1:0]; - if (axi_addr_diff >= BUF_THRESHOLD_HI) begin + axi_mem_raddr_m <= g2b(dac_mem_raddr_g); + axi_mem_raddr <= axi_mem_raddr_m; + axi_mem_addr_diff <= axi_mem_addr_diff_s[AXI_ADDRESS_WIDTH-1:0]; + if (axi_mem_addr_diff >= AXI_BUF_THRESHOLD_HI) begin axi_dready <= 1'b0; - end else if (axi_addr_diff <= BUF_THRESHOLD_LO) begin + end else if (axi_mem_addr_diff <= AXI_BUF_THRESHOLD_LO) begin axi_dready <= 1'b1; end - if (axi_addr_diff > BUF_THRESHOLD_HI) begin - axi_almost_full <= 1'b1; - end else begin - axi_almost_full <= 1'b0; + end + end + + // CDC for xfer_req signal + + always @(posedge dac_clk) begin + dac_xfer_req_m <= {dac_xfer_req_m[1:0], axi_xfer_req}; + end + + assign dac_xfer_out = dac_xfer_req_m[2]; + assign dac_xfer_init_s = ~dac_xfer_req_m[2] & dac_xfer_req_m[1]; + + // read interface + + always @(posedge dac_clk) begin + if (dac_xfer_out == 1'b0) begin + dac_mem_init <= 1'b0; + dac_mem_init_d <= 1'b0; + dac_mem_enable <= 1'b0; + end else begin + if (dac_xfer_init == 1'b1) begin + dac_mem_init <= 1'b1; end - if (axi_addr_diff < BUF_THRESHOLD_LO) begin - axi_almost_empty <= 1'b1; - end else begin - axi_almost_empty <= 1'b0; + if ((dac_mem_init == 1'b1) && (dac_mem_addr_diff > DAC_BUF_THRESHOLD_LO)) begin + dac_mem_init <= 1'b0; end - axi_dwunf <= (axi_addr_diff == 0) ? 1'b1 : 1'b0; + dac_mem_init_d <= dac_mem_init; + // memory is ready when the initial fill up is done + dac_mem_enable <= (dac_mem_init_d & ~dac_mem_init) ? 1'b1 : dac_mem_enable; + end + dac_xfer_init <= dac_xfer_init_s; + end + + always @(posedge dac_clk) begin + if (dac_xfer_out == 1'b0) begin + dac_mem_waddr <= 'b0; + dac_mem_waddr_m <= 'b0; + end else begin + dac_mem_waddr_m <= g2b(axi_mem_waddr_g); + dac_mem_waddr <= dac_mem_waddr_m; + end + end + + assign dac_mem_addr_diff_s = {1'b1, dac_mem_waddr} - dac_mem_raddr; + assign dac_mem_raddr_diff_s = {1'b1, dac_mem_raddr_next} - dac_mem_raddr; + assign dac_mem_valid_s = (dac_mem_enable) ? dac_valid : 1'b0; + + // CDC for the dma_last_addr + + always @(posedge dac_clk) begin + if (dac_rst == 1'b1) begin + dac_last_raddr <= 32'b0; + dac_last_raddr_m <= 32'b0; + end else begin + dac_last_raddr_m <= dma_last_addr; + dac_last_raddr <= dac_last_raddr_m; end end always @(posedge dac_clk) begin - dac_dunf_m <= {dac_dunf_m[1:0], axi_dwunf}; - dac_xfer_req_m <= {dac_xfer_req_m[1:0], axi_xfer_req}; + if (dac_xfer_out == 1'b0) begin + dac_mem_raddr <= 'd0; + dac_mem_raddr_next <= DAC_ARINCR; + dac_mem_raddr_g <= 'd0; + dac_mem_addr_diff <= 'd0; + end else begin + dac_mem_addr_diff <= dac_mem_addr_diff_s[DAC_ADDRESS_WIDTH-1:0]; + if (dac_mem_valid_s == 1'b1) begin + dac_raddr_cnt <= (dac_raddr_cnt == dac_last_raddr) ? 32'b0 : dac_raddr_cnt + 1; + dac_mem_raddr <= (dac_raddr_cnt == dac_last_raddr) ? dac_mem_raddr_next : dac_mem_raddr + 1'b1; + end + dac_mem_raddr_next <= (dac_mem_raddr_diff_s[DAC_ADDRESS_WIDTH-1:0] <= 1) ? dac_mem_raddr_next + DAC_ARINCR : dac_mem_raddr_next; + dac_mem_raddr_g <= b2g(dac_mem_raddr); + end end - assign dac_dunf = dac_dunf_m[2]; - assign dac_xfer_out = dac_xfer_req_m[2]; - - // read interface - - assign dac_rd_s = dac_xfer_out & dac_valid; + // underflow generation, there is no overflow always @(posedge dac_clk) begin - if (dac_xfer_out == 1'b0) begin - dac_rd <= 'd0; - dac_rd_d <= 'd0; - dac_rdata_d <= 'd0; - dac_raddr <= 'd0; - dac_raddr_g <= 'd0; + if(dac_xfer_out == 1'b0) begin + dac_almost_full <= 1'b0; + dac_almost_empty <= 1'b0; + dac_dunf <= 1'b0; end else begin - dac_rd <= dac_rd_s; - dac_rd_d <= dac_rd; - dac_rdata_d <= dac_rdata_s; - if (dac_rd_s == 1'b1) begin - dac_raddr <= dac_raddr + 1'b1; + if (dac_mem_addr_diff < DAC_BUF_THRESHOLD_LO) begin + dac_almost_empty <= 1'b1; + end else begin + dac_almost_empty <= 1'b0; end - dac_raddr_g <= b2g(dac_raddr); + dac_dunf <= (dac_mem_addr_diff == 0) ? 1'b1 : 1'b0; end end @@ -248,22 +320,11 @@ module axi_dacfifo_dac ( i_mem_asym ( .clka (axi_clk), .wea (axi_dvalid), - .addra (axi_waddr), + .addra (axi_mem_waddr), .dina (axi_ddata), .clkb (dac_clk), - .addrb (dac_raddr), - .doutb (dac_rdata_s)); - - ad_axis_inf_rx #(.DATA_WIDTH(DAC_DATA_WIDTH)) i_axis_inf ( - .clk (dac_clk), - .rst (dac_rst), - .valid (dac_rd_d), - .last (1'd0), - .data (dac_rdata_d), - .inf_valid (dac_valid_s), - .inf_last (), - .inf_data (dac_data), - .inf_ready (dac_valid)); + .addrb (dac_mem_raddr), + .doutb (dac_data)); endmodule diff --git a/library/axi_dacfifo/axi_dacfifo_rd.v b/library/axi_dacfifo/axi_dacfifo_rd.v index b3ec1388f..f4f309fc7 100644 --- a/library/axi_dacfifo/axi_dacfifo_rd.v +++ b/library/axi_dacfifo/axi_dacfifo_rd.v @@ -186,6 +186,7 @@ module axi_dacfifo_rd ( if (axi_resetn == 1'b0) begin axi_arvalid <= 'd0; axi_araddr <= 'd0; + axi_rd_addr_h <= 'd0; end else begin if (axi_arvalid == 1'b1) begin if (axi_arready == 1'b1) begin @@ -202,7 +203,7 @@ module axi_dacfifo_rd ( end else if ((axi_xfer_req == 1'b1) && (axi_arvalid == 1'b1) && (axi_arready == 1'b1)) begin - axi_araddr <= ((axi_araddr + AXI_AWINCR) >= axi_rd_addr_h) ? AXI_ADDRESS : axi_araddr + AXI_AWINCR; + axi_araddr <= (axi_araddr >= axi_rd_addr_h) ? AXI_ADDRESS : axi_araddr + AXI_AWINCR; end end end diff --git a/library/axi_dacfifo/axi_dacfifo_wr.v b/library/axi_dacfifo/axi_dacfifo_wr.v index 073e56d1d..71c4ccd95 100644 --- a/library/axi_dacfifo/axi_dacfifo_wr.v +++ b/library/axi_dacfifo/axi_dacfifo_wr.v @@ -56,6 +56,7 @@ module axi_dacfifo_wr ( // syncronization for the read side axi_last_raddr, + dma_last_addr, axi_xfer_out, // axi write address, write data and write response channels @@ -122,6 +123,7 @@ module axi_dacfifo_wr ( input dma_xfer_last; output [31:0] axi_last_raddr; + output [31:0] dma_last_addr; output axi_xfer_out; // axi interface @@ -165,6 +167,8 @@ module axi_dacfifo_wr ( reg dma_ready = 'd0; reg dma_rst_m1 = 1'b0; reg dma_rst_m2 = 1'b0; + reg [31:0] dma_last_addr = 32'b0; + reg [31:0] dma_addr_cnt = 32'b0; reg [ 2:0] axi_xfer_req_m = 3'b0; reg [ 2:0] axi_xfer_last_m = 3'b0; @@ -248,6 +252,18 @@ module axi_dacfifo_wr ( // write address generation for the asymetric memory + always @(posedge dma_clk) begin + if (dma_rst_s == 1'b1) begin + dma_addr_cnt <= 32'b0; + dma_last_addr <= 32'b0; + end else begin + if((dma_valid == 1'b1) && (dma_xfer_req == 1'b1)) begin + dma_addr_cnt <= (dma_xfer_last == 1'b1) ? 32'b0 : dma_addr_cnt + 1; + dma_last_addr <= (dma_xfer_last == 1'b1) ? dma_addr_cnt : dma_last_addr; + end + end + end + always @(posedge dma_clk) begin if (dma_rst_s == 1'b1) begin dma_mem_waddr <= 8'h0; @@ -371,8 +387,8 @@ module axi_dacfifo_wr ( end else if ((axi_awvalid == 1'b1) && (axi_awready == 1'b1)) begin axi_awaddr <= axi_awaddr + AXI_AWINCR; end - if(axi_xfer_last_m[2] == 1) begin - axi_last_raddr <= axi_awaddr; + if ((axi_xfer_req_m[2] == 1) && (axi_xfer_last_m[2] == 1)) begin + axi_last_raddr <= axi_awaddr - AXI_AWINCR; axi_xfer_out <= 1'b1; end end