Skip to content

Commit

Permalink
axi_logic_analyzer: Auto sync to ADC path
Browse files Browse the repository at this point in the history
The number of delay taps in the LA data path can be controlled manually, from
the regmap or automatically, according to the axi_adc_decimate's rate.

Moreover, because the rate is configure by software, and the time of
initialization, is different for the ADC path and LA path. There is an
uncertainty of plus/minus one sample between the two. Because ADC and LA
paths share the same clock we can easily synchronize the two paths. We
can't use reset, because the rate generation mechanism is different
between the two. So the ADC path is used as master valid generator and we
can use it to drive the LA path.
The synchronization is done by setting the rate source bit. This
mechanism can only be used if the desired rate for both path is equal,
including oversampling fom ADC decimation.
  • Loading branch information
AndreiGrozav committed Aug 13, 2020
1 parent d2b1164 commit 2e0ba5b
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 38 deletions.
159 changes: 125 additions & 34 deletions library/axi_logic_analyzer/axi_logic_analyzer.v
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@

`timescale 1ns/100ps

module axi_logic_analyzer #(

// add sample delays on LA to compensate for adc path delay

parameter ADC_PATH_DELAY = 19) (
module axi_logic_analyzer (

// interface

Expand All @@ -58,6 +54,9 @@ module axi_logic_analyzer #(
input dac_valid,
output reg dac_read,

input [ 2:0] external_rate,
input external_valid,
input external_decimation_en,
input trigger_in,
output trigger_out,
output trigger_out_adc,
Expand Down Expand Up @@ -128,6 +127,40 @@ module axi_logic_analyzer #(

reg [15:0] adc_data_mn = 'd0;
reg [31:0] trigger_holdoff_counter = 32'd0;
reg [ 4:0] adc_data_delay = 5'd0;

reg [15:0] data_m_0;
reg [15:0] data_m_1;
reg [15:0] data_m_2;
reg [15:0] data_m_3;
reg [15:0] data_m_4;
reg [15:0] data_m_5;
reg [15:0] data_m_6;
reg [15:0] data_m_7;
reg [15:0] data_m_8;
reg [15:0] data_m_9;
reg [15:0] data_m_10;
reg [15:0] data_m_11;
reg [15:0] data_m_12;
reg [15:0] data_m_13;
reg [15:0] data_m_14;
reg [15:0] data_m_15;
reg [15:0] data_m_16;
reg [15:0] data_m_17;
reg [15:0] data_m_18;
reg [15:0] data_m_19;
reg [15:0] data_m_20;
reg [15:0] data_m_21;
reg [15:0] data_m_22;
reg [15:0] data_m_23;
reg [15:0] data_m_24;
reg [15:0] data_m_25;
reg [15:0] data_m_26;
reg [15:0] data_m_27;
reg [15:0] data_m_28;
reg [15:0] data_m_29;
reg [15:0] data_m_30;
reg [15:0] data_m_31;

// internal signals

Expand Down Expand Up @@ -181,6 +214,11 @@ module axi_logic_analyzer #(

wire streaming;

wire [ 4:0] in_data_delay;
wire [ 4:0] up_data_delay;
wire master_delay_ctrl;
wire [ 9:0] data_delay_control;

genvar i;

// signal name changes
Expand All @@ -189,9 +227,10 @@ module axi_logic_analyzer #(
assign up_rstn = s_axi_aresetn;

assign trigger_out = trigger_delay == 32'h0 ? trigger_out_holdoff | streaming_on : trigger_out_delayed | streaming_on;

assign trigger_out_delayed = delay_counter == 32'h0 ? 1 : 0;

always @(posedge clk_out) begin
always @(posedge clk_out) begin
if (trigger_delay == 0) begin
if (streaming == 1'b1 && sample_valid_la == 1'b1 && trigger_out_holdoff == 1'b1) begin
streaming_on <= 1'b1;
Expand All @@ -208,7 +247,7 @@ module axi_logic_analyzer #(
end


always @(posedge clk_out) begin
always @(posedge clk_out) begin
if (sample_valid_la == 1'b1 && trigger_out_holdoff == 1'b1) begin
up_triggered_set <= 1'b1;
end else if (up_triggered_reset == 1'b1) begin
Expand Down Expand Up @@ -254,49 +293,103 @@ module axi_logic_analyzer #(

// - synchronization
// - compensate for m2k adc path delay
// - transfer data at clock frequency if capture is enabled

genvar j;
always @(posedge clk_out) begin
data_m_0 <= data_i;
data_m_1 <= data_m_0;
data_m_2 <= data_m_1;
data_m_3 <= data_m_2;
data_m_4 <= data_m_3;
data_m_5 <= data_m_4;
data_m_6 <= data_m_5;
data_m_7 <= data_m_6;
data_m_8 <= data_m_7;
data_m_9 <= data_m_8;
data_m_10 <= data_m_9;
data_m_11 <= data_m_10;
data_m_12 <= data_m_11;
data_m_13 <= data_m_12;
data_m_14 <= data_m_13;
data_m_15 <= data_m_14;
data_m_16 <= data_m_15;
if (sample_valid_la == 1'b1) begin
data_m_17 <= data_m_16;
data_m_18 <= data_m_17;
data_m_19 <= data_m_18;
data_m_20 <= data_m_19;
data_m_21 <= data_m_20;
data_m_22 <= data_m_21;
data_m_23 <= data_m_22;
data_m_24 <= data_m_23;
data_m_25 <= data_m_24;
data_m_26 <= data_m_25;
data_m_27 <= data_m_26;
data_m_28 <= data_m_27;
data_m_29 <= data_m_28;
data_m_30 <= data_m_29;
data_m_31 <= data_m_30;
end
end

generate
// adc path 'rate delay' given by axi_adc_decimate
always @(posedge clk_out) begin
case (external_rate)
3'd0: adc_data_delay <= 5'd1; // 100MSPS
3'd1: adc_data_delay <= 5'd3; // 10MSPS
default: adc_data_delay <= 5'd1; // <= 1MSPS
endcase
end

reg [15:0] data_m[ADC_PATH_DELAY-2:0];
assign up_data_delay = data_delay_control[4:0];
assign rate_gen_select = data_delay_control[8];

always @(posedge clk_out) begin
if (sample_valid_la == 1'b1) begin
data_m[0] <= data_i;
end
end
// select if the delay taps number is chosen by the user or automatically
assign master_delay_ctrl = data_delay_control[9];
assign in_data_delay = master_delay_ctrl ? up_data_delay :
external_decimation_en ? 5'd0 : adc_data_delay;

for (j = 0; j < ADC_PATH_DELAY - 2; j = j + 1) begin
always @(posedge clk_out) begin
if (sample_valid_la == 1'b1) begin
data_m[j+1] <= data_m[j];
end
end
end

always @(posedge clk_out) begin
if (sample_valid_la == 1'b1) begin
adc_data_mn <= data_m[ADC_PATH_DELAY-2];
adc_data <= adc_data_mn;
end
always @(posedge clk_out) begin
if (sample_valid_la == 1'b1) begin
case (in_data_delay)
5'd0: adc_data_mn <= data_m_16;
5'd1: adc_data_mn <= data_m_17;
5'd2: adc_data_mn <= data_m_18;
5'd3: adc_data_mn <= data_m_19;
5'd4: adc_data_mn <= data_m_20;
5'd5: adc_data_mn <= data_m_21;
5'd6: adc_data_mn <= data_m_22;
5'd7: adc_data_mn <= data_m_23;
5'd8: adc_data_mn <= data_m_24;
5'd9: adc_data_mn <= data_m_25;
5'd10: adc_data_mn <= data_m_26;
5'd11: adc_data_mn <= data_m_27;
5'd12: adc_data_mn <= data_m_28;
5'd13: adc_data_mn <= data_m_29;
5'd14: adc_data_mn <= data_m_30;
5'd15: adc_data_mn <= data_m_31;
default: adc_data_mn <= data_m_16;
endcase
adc_data <= adc_data_mn;
end
endgenerate
end

assign adc_valid = sample_valid_la;

always @(posedge clk_out) begin
trigger_m1 <= trigger_i;
end

// downsampler logic analyzer

always @(posedge clk_out) begin
if (reset == 1'b1) begin
sample_valid_la <= 1'b0;
downsampler_counter_la <= 32'h0;
end else begin
if (downsampler_counter_la < divider_counter_la ) begin
if (rate_gen_select) begin
downsampler_counter_la <= 32'h0;
sample_valid_la <= external_valid;
end else if (downsampler_counter_la < divider_counter_la ) begin
downsampler_counter_la <= downsampler_counter_la + 1;
sample_valid_la <= 1'b0;
end else begin
Expand Down Expand Up @@ -404,7 +497,6 @@ module axi_logic_analyzer #(
end
end


axi_logic_analyzer_trigger i_trigger (
.clk (clk_out),
.reset (reset),
Expand Down Expand Up @@ -446,11 +538,10 @@ module axi_logic_analyzer #(
.overwrite_data (overwrite_data),
.input_data (adc_data_mn),
.od_pp_n (od_pp_n),

.triggered (up_triggered),
.pg_trigger_config (pg_trigger_config),

.streaming(streaming),
.data_delay_control (data_delay_control),

// bus interface

Expand Down
5 changes: 5 additions & 0 deletions library/axi_logic_analyzer/axi_logic_analyzer_constr.xdc
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *up_triggered_d*}]
set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *up_triggered_reset_d*}]
set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *data_m*}]
set_property ASYNC_REG TRUE [get_cells -hier -filter {name =~ *up_sync_ack_m*}]

set_false_path -to [get_pins BUFGMUX_CTRL_inst/S*]

set_false_path -to [get_cells -hier -filter {name =~ *up_triggered_d1* && IS_SEQUENTIAL}]
set_false_path -to [get_cells -hier -filter {name =~ *up_triggered_reset_d1* && IS_SEQUENTIAL}]
set_false_path -to [get_cells -hier -filter {name =~ *data_m* && IS_SEQUENTIAL}]
set_false_path -to [get_cells -hier -filter {name =~ *up_sync_ack_m* && IS_SEQUENTIAL}]

16 changes: 12 additions & 4 deletions library/axi_logic_analyzer/axi_logic_analyzer_reg.v
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ module axi_logic_analyzer_reg (
output [19:0] pg_trigger_config,

input triggered,

output streaming,
output [ 9:0] data_delay_control,

// bus interface

Expand Down Expand Up @@ -102,6 +102,7 @@ module axi_logic_analyzer_reg (
reg [19:0] up_pg_trigger_config = 20'h0;
reg up_triggered = 0;
reg up_streaming = 0;
reg [ 9:0] up_data_delay_control = 10'd0;

wire [15:0] up_input_data;

Expand All @@ -128,6 +129,7 @@ module axi_logic_analyzer_reg (
up_streaming <= 1'd0;
up_trigger_holdoff <= 32'h0;
up_pg_trigger_config <= 20'd0;
up_data_delay_control <= 10'h0;
end else begin
up_wack <= up_wreq;
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h1)) begin
Expand Down Expand Up @@ -192,6 +194,9 @@ module axi_logic_analyzer_reg (
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h15)) begin
up_pg_trigger_config <= up_wdata[19:0];
end
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h16)) begin
up_data_delay_control <= up_wdata[9:0];
end
end
end

Expand Down Expand Up @@ -227,6 +232,7 @@ module axi_logic_analyzer_reg (
5'h13: up_rdata <= {31'h0,up_streaming};
5'h14: up_rdata <= up_trigger_holdoff;
5'h15: up_rdata <= {12'h0,up_pg_trigger_config};
5'h16: up_rdata <= {22'h0,up_data_delay_control};
default: up_rdata <= 0;
endcase
end else begin
Expand All @@ -237,7 +243,7 @@ module axi_logic_analyzer_reg (

ad_rst i_core_rst_reg (.rst_async(~up_rstn), .clk(clk), .rstn(), .rst(reset));

up_xfer_cntrl #(.DATA_WIDTH(343)) i_xfer_cntrl (
up_xfer_cntrl #(.DATA_WIDTH(353)) i_xfer_cntrl (
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_data_cntrl ({ up_streaming, // 1
Expand All @@ -257,7 +263,8 @@ module axi_logic_analyzer_reg (
up_io_selection, // 16
up_pg_trigger_config, // 20
up_divider_counter_pg, // 32
up_divider_counter_la}), // 32
up_divider_counter_la, // 32
up_data_delay_control}), // 10

.up_xfer_done (),
.d_rst (1'b0),
Expand All @@ -279,7 +286,8 @@ module axi_logic_analyzer_reg (
io_selection, // 16
pg_trigger_config, // 20
divider_counter_pg, // 32
divider_counter_la})); // 32
divider_counter_la, // 32
data_delay_control})); // 10

up_xfer_status #(.DATA_WIDTH(16)) i_xfer_status (

Expand Down

0 comments on commit 2e0ba5b

Please sign in to comment.