[axi|avl]_dacfifo: Fix the util_dacfifo_module
Fix the read side of the CDC data FIFO. The read address generation did not function correctly. Redesign the read side of the FIFO, and make sure that it becomes empty after the DMA transfer ends; and never get stock in a cyclic mode.main
parent
b338b30964
commit
5d3b2b1550
|
@ -77,24 +77,22 @@ module util_dacfifo_bypass #(
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_g = 'd0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_g = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_g = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_g = 'd0;
|
||||||
|
reg dac_mem_rea = 1'b0;
|
||||||
|
reg dac_mem_rea_d = 1'b0;
|
||||||
reg dma_rst_m1 = 1'b0;
|
reg dma_rst_m1 = 1'b0;
|
||||||
reg dma_rst = 1'b0;
|
reg dma_rst = 1'b0;
|
||||||
reg [DMA_ADDRESS_WIDTH-1:0] dma_mem_addr_diff = 1'b0;
|
reg [DMA_ADDRESS_WIDTH-1:0] dma_mem_addr_diff = 1'b0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m1 = 1'b0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m1 = 1'b0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m2 = 1'b0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m2 = 1'b0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr = 1'b0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr = 1'b0;
|
||||||
reg [DAC_ADDRESS_WIDTH-1:0] dac_mem_addr_diff = 1'b0;
|
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m1 = 1'b0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m1 = 1'b0;
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m2 = 1'b0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m2 = 1'b0;
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr = 1'b0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr = 1'b0;
|
||||||
reg dac_mem_ready = 1'b0;
|
|
||||||
reg dac_xfer_out = 1'b0;
|
reg dac_xfer_out = 1'b0;
|
||||||
reg dac_xfer_out_m1 = 1'b0;
|
reg dac_xfer_out_m1 = 1'b0;
|
||||||
|
|
||||||
// internal signals
|
// internal signals
|
||||||
|
|
||||||
wire dma_mem_last_read_s;
|
|
||||||
wire [(DMA_ADDRESS_WIDTH):0] dma_mem_addr_diff_s;
|
|
||||||
wire [(DAC_ADDRESS_WIDTH):0] dac_mem_addr_diff_s;
|
wire [(DAC_ADDRESS_WIDTH):0] dac_mem_addr_diff_s;
|
||||||
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_raddr_s;
|
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_raddr_s;
|
||||||
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_s;
|
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_s;
|
||||||
|
@ -102,7 +100,7 @@ module util_dacfifo_bypass #(
|
||||||
wire dac_mem_rea_s;
|
wire dac_mem_rea_s;
|
||||||
wire [(DAC_DATA_WIDTH-1):0] dac_mem_rdata_s;
|
wire [(DAC_DATA_WIDTH-1):0] dac_mem_rdata_s;
|
||||||
wire [DMA_ADDRESS_WIDTH:0] dma_address_diff_s;
|
wire [DMA_ADDRESS_WIDTH:0] dma_address_diff_s;
|
||||||
wire [DAC_ADDRESS_WIDTH:0] dac_address_diff_s;
|
wire dac_mem_empty_s;
|
||||||
|
|
||||||
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_b2g_s;
|
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_b2g_s;
|
||||||
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_b2g_s;
|
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_b2g_s;
|
||||||
|
@ -189,7 +187,7 @@ module util_dacfifo_bypass #(
|
||||||
|
|
||||||
|
|
||||||
// relative address offset on dac domain
|
// relative address offset on dac domain
|
||||||
assign dac_address_diff_s = {1'b1, dac_mem_raddr} - dac_mem_waddr_s;
|
assign dac_address_diff_s = {1'b1, dac_mem_waddr_s} - dac_mem_raddr;
|
||||||
assign dac_mem_waddr_s = (DAC_DATA_WIDTH>DMA_DATA_WIDTH) ?
|
assign dac_mem_waddr_s = (DAC_DATA_WIDTH>DMA_DATA_WIDTH) ?
|
||||||
((MEM_RATIO == 1) ? (dac_mem_waddr) :
|
((MEM_RATIO == 1) ? (dac_mem_waddr) :
|
||||||
(MEM_RATIO == 2) ? (dac_mem_waddr[(DMA_ADDRESS_WIDTH-1):1]) :
|
(MEM_RATIO == 2) ? (dac_mem_waddr[(DMA_ADDRESS_WIDTH-1):1]) :
|
||||||
|
@ -200,7 +198,8 @@ module util_dacfifo_bypass #(
|
||||||
|
|
||||||
// Read address generation for the asymmetric memory
|
// Read address generation for the asymmetric memory
|
||||||
|
|
||||||
assign dac_mem_rea_s = dac_valid & dac_mem_ready;
|
assign dac_mem_empty_s = (dac_mem_waddr_s == dac_mem_raddr) ? 1'b1 : 1'b0;
|
||||||
|
assign dac_mem_rea_s = dac_valid & !dac_mem_empty_s;
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_rst == 1'b1) begin
|
||||||
|
@ -214,6 +213,12 @@ module util_dacfifo_bypass #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// compensate the read latency of the memory
|
||||||
|
always @(posedge dac_clk) begin
|
||||||
|
dac_mem_rea_d <= dac_mem_rea_s;
|
||||||
|
dac_mem_rea <= dac_mem_rea_d;
|
||||||
|
end
|
||||||
|
|
||||||
ad_b2g #(
|
ad_b2g #(
|
||||||
.DATA_WIDTH (DAC_ADDRESS_WIDTH))
|
.DATA_WIDTH (DAC_ADDRESS_WIDTH))
|
||||||
i_dac_mem_raddr_b2g (
|
i_dac_mem_raddr_b2g (
|
||||||
|
@ -224,21 +229,13 @@ module util_dacfifo_bypass #(
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_rst == 1'b1) begin
|
||||||
dac_mem_addr_diff <= 'b0;
|
|
||||||
dac_mem_waddr_m1 <= 'b0;
|
dac_mem_waddr_m1 <= 'b0;
|
||||||
dac_mem_waddr_m2 <= 'b0;
|
dac_mem_waddr_m2 <= 'b0;
|
||||||
dac_mem_waddr <= 'b0;
|
dac_mem_waddr <= 'b0;
|
||||||
dac_mem_ready <= 1'b0;
|
|
||||||
end else begin
|
end else begin
|
||||||
dac_mem_waddr_m1 <= dma_mem_waddr_g;
|
dac_mem_waddr_m1 <= dma_mem_waddr_g;
|
||||||
dac_mem_waddr_m2 <= dac_mem_waddr_m1;
|
dac_mem_waddr_m2 <= dac_mem_waddr_m1;
|
||||||
dac_mem_waddr <= dac_mem_waddr_m2_g2b_s;
|
dac_mem_waddr <= dac_mem_waddr_m2_g2b_s;
|
||||||
dac_mem_addr_diff <= dac_address_diff_s[DAC_ADDRESS_WIDTH-1:0];
|
|
||||||
if (dac_mem_addr_diff > 0) begin
|
|
||||||
dac_mem_ready <= 1'b1;
|
|
||||||
end else begin
|
|
||||||
dac_mem_ready <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -258,14 +255,16 @@ module util_dacfifo_bypass #(
|
||||||
end else begin
|
end else begin
|
||||||
dac_xfer_out_m1 <= dma_xfer_req;
|
dac_xfer_out_m1 <= dma_xfer_req;
|
||||||
dac_xfer_out <= dac_xfer_out_m1;
|
dac_xfer_out <= dac_xfer_out_m1;
|
||||||
dac_dunf <= (dac_valid == 1'b1) ? (dac_xfer_out & ~dac_mem_ready) : dac_dunf;
|
if (dac_valid == 1'b1) begin
|
||||||
|
dac_dunf <= dac_mem_empty_s;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// DAC data output logic
|
// DAC data output logic
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_dunf == 1'b1) begin
|
||||||
dac_data <= 0;
|
dac_data <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
dac_data <= dac_mem_rdata_s;
|
dac_data <= dac_mem_rdata_s;
|
||||||
|
|
|
@ -77,32 +77,28 @@ module util_dacfifo_bypass #(
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_g = 'd0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_g = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_g = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_g = 'd0;
|
||||||
|
reg dac_mem_rea = 1'b0;
|
||||||
reg dma_rst_m1 = 1'b0;
|
reg dma_rst_m1 = 1'b0;
|
||||||
reg dma_rst = 1'b0;
|
reg dma_rst = 1'b0;
|
||||||
reg [DMA_ADDRESS_WIDTH-1:0] dma_mem_addr_diff = 'd0;
|
reg [DMA_ADDRESS_WIDTH-1:0] dma_mem_addr_diff = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m1 = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m1 = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m2 = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr_m2 = 'd0;
|
||||||
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr = 'd0;
|
reg [(DAC_ADDRESS_WIDTH-1):0] dma_mem_raddr = 'd0;
|
||||||
reg [DAC_ADDRESS_WIDTH-1:0] dac_mem_addr_diff = 'd0;
|
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m1 = 'd0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m1 = 'd0;
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m2 = 'd0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr_m2 = 'd0;
|
||||||
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr = 'd0;
|
reg [(DMA_ADDRESS_WIDTH-1):0] dac_mem_waddr = 'd0;
|
||||||
reg dac_mem_ready = 1'b0;
|
|
||||||
reg dac_xfer_out = 1'b0;
|
reg dac_xfer_out = 1'b0;
|
||||||
reg dac_xfer_out_m1 = 1'b0;
|
reg dac_xfer_out_m1 = 1'b0;
|
||||||
|
|
||||||
// internal signals
|
// internal signals
|
||||||
|
|
||||||
wire dma_mem_last_read_s;
|
|
||||||
wire [(DMA_ADDRESS_WIDTH):0] dma_mem_addr_diff_s;
|
|
||||||
wire [(DAC_ADDRESS_WIDTH):0] dac_mem_addr_diff_s;
|
|
||||||
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_raddr_s;
|
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_raddr_s;
|
||||||
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_s;
|
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_waddr_s;
|
||||||
wire dma_mem_wea_s;
|
wire dma_mem_wea_s;
|
||||||
wire dac_mem_rea_s;
|
wire dac_mem_rea_s;
|
||||||
wire [(DAC_DATA_WIDTH-1):0] dac_mem_rdata_s;
|
wire [(DAC_DATA_WIDTH-1):0] dac_mem_rdata_s;
|
||||||
wire [DMA_ADDRESS_WIDTH:0] dma_address_diff_s;
|
wire [DMA_ADDRESS_WIDTH:0] dma_address_diff_s;
|
||||||
wire [DAC_ADDRESS_WIDTH:0] dac_address_diff_s;
|
wire dac_mem_empty_s;
|
||||||
|
|
||||||
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_b2g_s;
|
wire [(DMA_ADDRESS_WIDTH-1):0] dma_mem_waddr_b2g_s;
|
||||||
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_b2g_s;
|
wire [(DAC_ADDRESS_WIDTH-1):0] dac_mem_raddr_b2g_s;
|
||||||
|
@ -193,8 +189,7 @@ module util_dacfifo_bypass #(
|
||||||
(MEM_RATIO == 4) ? ({dma_mem_raddr, 2'b0}) : ({dma_mem_raddr, 3'b0}));
|
(MEM_RATIO == 4) ? ({dma_mem_raddr, 2'b0}) : ({dma_mem_raddr, 3'b0}));
|
||||||
|
|
||||||
|
|
||||||
// relative address offset on dac domain
|
// relative address offset on DAC domain
|
||||||
assign dac_address_diff_s = {1'b1, dac_mem_raddr} - dac_mem_waddr_s;
|
|
||||||
assign dac_mem_waddr_s = (DAC_DATA_WIDTH>DMA_DATA_WIDTH) ?
|
assign dac_mem_waddr_s = (DAC_DATA_WIDTH>DMA_DATA_WIDTH) ?
|
||||||
((MEM_RATIO == 1) ? (dac_mem_waddr) :
|
((MEM_RATIO == 1) ? (dac_mem_waddr) :
|
||||||
(MEM_RATIO == 2) ? (dac_mem_waddr[(DMA_ADDRESS_WIDTH-1):1]) :
|
(MEM_RATIO == 2) ? (dac_mem_waddr[(DMA_ADDRESS_WIDTH-1):1]) :
|
||||||
|
@ -203,9 +198,8 @@ module util_dacfifo_bypass #(
|
||||||
(MEM_RATIO == 2) ? ({dac_mem_waddr, 1'b0}) :
|
(MEM_RATIO == 2) ? ({dac_mem_waddr, 1'b0}) :
|
||||||
(MEM_RATIO == 4) ? ({dac_mem_waddr, 2'b0}) : ({dac_mem_waddr, 3'b0}));
|
(MEM_RATIO == 4) ? ({dac_mem_waddr, 2'b0}) : ({dac_mem_waddr, 3'b0}));
|
||||||
|
|
||||||
// Read address generation for the asymmetric memory
|
assign dac_mem_empty_s = (dac_mem_waddr_s == dac_mem_raddr) ? 1'b1 : 1'b0;
|
||||||
|
assign dac_mem_rea_s = dac_valid & !dac_mem_empty_s;
|
||||||
assign dac_mem_rea_s = dac_valid & dac_mem_ready;
|
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_rst == 1'b1) begin
|
||||||
|
@ -213,12 +207,17 @@ module util_dacfifo_bypass #(
|
||||||
dac_mem_raddr_g <= 'h0;
|
dac_mem_raddr_g <= 'h0;
|
||||||
end else begin
|
end else begin
|
||||||
if (dac_mem_rea_s == 1'b1) begin
|
if (dac_mem_rea_s == 1'b1) begin
|
||||||
dac_mem_raddr <= dac_mem_raddr + 1;
|
dac_mem_raddr <= dac_mem_raddr + 1'b1;
|
||||||
end
|
end
|
||||||
dac_mem_raddr_g <= dac_mem_raddr_b2g_s;
|
dac_mem_raddr_g <= dac_mem_raddr_b2g_s;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// compensate the read latency of the memory
|
||||||
|
always @(posedge dac_clk) begin
|
||||||
|
dac_mem_rea <= dac_mem_rea_s;
|
||||||
|
end
|
||||||
|
|
||||||
ad_b2g #(
|
ad_b2g #(
|
||||||
.DATA_WIDTH (DAC_ADDRESS_WIDTH))
|
.DATA_WIDTH (DAC_ADDRESS_WIDTH))
|
||||||
i_dac_mem_raddr_b2g (
|
i_dac_mem_raddr_b2g (
|
||||||
|
@ -229,21 +228,13 @@ module util_dacfifo_bypass #(
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_rst == 1'b1) begin
|
||||||
dac_mem_addr_diff <= 'b0;
|
|
||||||
dac_mem_waddr_m1 <= 'b0;
|
dac_mem_waddr_m1 <= 'b0;
|
||||||
dac_mem_waddr_m2 <= 'b0;
|
dac_mem_waddr_m2 <= 'b0;
|
||||||
dac_mem_waddr <= 'b0;
|
dac_mem_waddr <= 'b0;
|
||||||
dac_mem_ready <= 1'b0;
|
|
||||||
end else begin
|
end else begin
|
||||||
dac_mem_waddr_m1 <= dma_mem_waddr_g;
|
dac_mem_waddr_m1 <= dma_mem_waddr_g;
|
||||||
dac_mem_waddr_m2 <= dac_mem_waddr_m1;
|
dac_mem_waddr_m2 <= dac_mem_waddr_m1;
|
||||||
dac_mem_waddr <= dac_mem_waddr_m2_g2b_s;
|
dac_mem_waddr <= dac_mem_waddr_m2_g2b_s;
|
||||||
dac_mem_addr_diff <= dac_address_diff_s[DAC_ADDRESS_WIDTH-1:0];
|
|
||||||
if (dac_mem_addr_diff > 0) begin
|
|
||||||
dac_mem_ready <= 1'b1;
|
|
||||||
end else begin
|
|
||||||
dac_mem_ready <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -263,14 +254,17 @@ module util_dacfifo_bypass #(
|
||||||
end else begin
|
end else begin
|
||||||
dac_xfer_out_m1 <= dma_xfer_req;
|
dac_xfer_out_m1 <= dma_xfer_req;
|
||||||
dac_xfer_out <= dac_xfer_out_m1;
|
dac_xfer_out <= dac_xfer_out_m1;
|
||||||
dac_dunf <= (dac_valid == 1'b1) ? (dac_xfer_out & ~dac_mem_ready) : dac_dunf;
|
if (dac_valid == 1'b1) begin
|
||||||
|
dac_dunf <= dac_mem_empty_s;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// DAC data output logic
|
// DAC data output logic - make sure that the data output is zero between
|
||||||
|
// transfers
|
||||||
|
|
||||||
always @(posedge dac_clk) begin
|
always @(posedge dac_clk) begin
|
||||||
if (dac_rst == 1'b1) begin
|
if (dac_dunf == 1'b1) begin
|
||||||
dac_data <= 0;
|
dac_data <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
dac_data <= dac_mem_rdata_s;
|
dac_data <= dac_mem_rdata_s;
|
||||||
|
|
Loading…
Reference in New Issue