util_adcfifo: Fix data corruption at faster DMA clock rates

When the DMA clock to ADC data rate ratio exceeds a certain threshold it is
possible that an erroneous dma_waddr_rel toggle event is generated. This
causes the last address of the previous DMA transfer to be transferred to
the DMA domain. And the DMA side will start reading from the FIFO even
though data is not available yet.

This results in data corruption with the current transfer containing data
from the previous transfer.

The root cause here is that the toggle signal CDC synchronizer register are
reset in the DMA when a new transfer starts, but not in the ADC domain,
causing a potential mismatch and the incorrect toggle event. To fix this
remove the reset from the DMA side. This is OK since the registers are
self-resetting if the reset signal is asserted for more than 3 clock cycles.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2017-08-17 13:16:10 +02:00
parent c843a16797
commit a46b9cfa5a
1 changed files with 4 additions and 2 deletions

View File

@ -154,14 +154,16 @@ module util_adcfifo #(
assign dma_waddr_rel_t_s = dma_waddr_rel_t_m[2] ^ dma_waddr_rel_t_m[1]; assign dma_waddr_rel_t_s = dma_waddr_rel_t_m[2] ^ dma_waddr_rel_t_m[1];
assign dma_waddr_rel_s = {dma_waddr_rel,{ADDRESS_PADDING_WIDTH{1'b0}}}; assign dma_waddr_rel_s = {dma_waddr_rel,{ADDRESS_PADDING_WIDTH{1'b0}}};
always @(posedge dma_clk) begin
dma_waddr_rel_t_m <= {dma_waddr_rel_t_m[1:0], adc_waddr_rel_t};
end
always @(posedge dma_clk) begin always @(posedge dma_clk) begin
if (dma_xfer_req == 1'b0) begin if (dma_xfer_req == 1'b0) begin
dma_rst <= 1'b1; dma_rst <= 1'b1;
dma_waddr_rel_t_m <= 'd0;
dma_waddr_rel <= 'd0; dma_waddr_rel <= 'd0;
end else begin end else begin
dma_rst <= 1'b0; dma_rst <= 1'b0;
dma_waddr_rel_t_m <= {dma_waddr_rel_t_m[1:0], adc_waddr_rel_t};
if (dma_waddr_rel_t_s == 1'b1) begin if (dma_waddr_rel_t_s == 1'b1) begin
dma_waddr_rel <= adc_waddr_rel; dma_waddr_rel <= adc_waddr_rel;
end end