axi_logic_analyzer: Auto sync to ADC path
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.main
parent
d2b1164567
commit
2e0ba5bffd
|
@ -35,11 +35,7 @@
|
||||||
|
|
||||||
`timescale 1ns/100ps
|
`timescale 1ns/100ps
|
||||||
|
|
||||||
module axi_logic_analyzer #(
|
module axi_logic_analyzer (
|
||||||
|
|
||||||
// add sample delays on LA to compensate for adc path delay
|
|
||||||
|
|
||||||
parameter ADC_PATH_DELAY = 19) (
|
|
||||||
|
|
||||||
// interface
|
// interface
|
||||||
|
|
||||||
|
@ -58,6 +54,9 @@ module axi_logic_analyzer #(
|
||||||
input dac_valid,
|
input dac_valid,
|
||||||
output reg dac_read,
|
output reg dac_read,
|
||||||
|
|
||||||
|
input [ 2:0] external_rate,
|
||||||
|
input external_valid,
|
||||||
|
input external_decimation_en,
|
||||||
input trigger_in,
|
input trigger_in,
|
||||||
output trigger_out,
|
output trigger_out,
|
||||||
output trigger_out_adc,
|
output trigger_out_adc,
|
||||||
|
@ -128,6 +127,40 @@ module axi_logic_analyzer #(
|
||||||
|
|
||||||
reg [15:0] adc_data_mn = 'd0;
|
reg [15:0] adc_data_mn = 'd0;
|
||||||
reg [31:0] trigger_holdoff_counter = 32'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
|
// internal signals
|
||||||
|
|
||||||
|
@ -181,6 +214,11 @@ module axi_logic_analyzer #(
|
||||||
|
|
||||||
wire streaming;
|
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;
|
genvar i;
|
||||||
|
|
||||||
// signal name changes
|
// signal name changes
|
||||||
|
@ -189,6 +227,7 @@ module axi_logic_analyzer #(
|
||||||
assign up_rstn = s_axi_aresetn;
|
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 = trigger_delay == 32'h0 ? trigger_out_holdoff | streaming_on : trigger_out_delayed | streaming_on;
|
||||||
|
|
||||||
assign trigger_out_delayed = delay_counter == 32'h0 ? 1 : 0;
|
assign trigger_out_delayed = delay_counter == 32'h0 ? 1 : 0;
|
||||||
|
|
||||||
always @(posedge clk_out) begin
|
always @(posedge clk_out) begin
|
||||||
|
@ -254,41 +293,92 @@ module axi_logic_analyzer #(
|
||||||
|
|
||||||
// - synchronization
|
// - synchronization
|
||||||
// - compensate for m2k adc path delay
|
// - 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];
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
always @(posedge clk_out) begin
|
always @(posedge clk_out) begin
|
||||||
if (sample_valid_la == 1'b1) begin
|
if (sample_valid_la == 1'b1) begin
|
||||||
data_m[0] <= data_i;
|
case (in_data_delay)
|
||||||
end
|
5'd0: adc_data_mn <= data_m_16;
|
||||||
end
|
5'd1: adc_data_mn <= data_m_17;
|
||||||
|
5'd2: adc_data_mn <= data_m_18;
|
||||||
for (j = 0; j < ADC_PATH_DELAY - 2; j = j + 1) begin
|
5'd3: adc_data_mn <= data_m_19;
|
||||||
always @(posedge clk_out) begin
|
5'd4: adc_data_mn <= data_m_20;
|
||||||
if (sample_valid_la == 1'b1) begin
|
5'd5: adc_data_mn <= data_m_21;
|
||||||
data_m[j+1] <= data_m[j];
|
5'd6: adc_data_mn <= data_m_22;
|
||||||
end
|
5'd7: adc_data_mn <= data_m_23;
|
||||||
end
|
5'd8: adc_data_mn <= data_m_24;
|
||||||
end
|
5'd9: adc_data_mn <= data_m_25;
|
||||||
|
5'd10: adc_data_mn <= data_m_26;
|
||||||
always @(posedge clk_out) begin
|
5'd11: adc_data_mn <= data_m_27;
|
||||||
if (sample_valid_la == 1'b1) begin
|
5'd12: adc_data_mn <= data_m_28;
|
||||||
adc_data_mn <= data_m[ADC_PATH_DELAY-2];
|
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;
|
adc_data <= adc_data_mn;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
|
||||||
|
|
||||||
assign adc_valid = sample_valid_la;
|
assign adc_valid = sample_valid_la;
|
||||||
|
|
||||||
always @(posedge clk_out) begin
|
always @(posedge clk_out) begin
|
||||||
trigger_m1 <= trigger_i;
|
trigger_m1 <= trigger_i;
|
||||||
end
|
end
|
||||||
|
|
||||||
// downsampler logic analyzer
|
// downsampler logic analyzer
|
||||||
|
|
||||||
always @(posedge clk_out) begin
|
always @(posedge clk_out) begin
|
||||||
|
@ -296,7 +386,10 @@ module axi_logic_analyzer #(
|
||||||
sample_valid_la <= 1'b0;
|
sample_valid_la <= 1'b0;
|
||||||
downsampler_counter_la <= 32'h0;
|
downsampler_counter_la <= 32'h0;
|
||||||
end else begin
|
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;
|
downsampler_counter_la <= downsampler_counter_la + 1;
|
||||||
sample_valid_la <= 1'b0;
|
sample_valid_la <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -404,7 +497,6 @@ module axi_logic_analyzer #(
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
axi_logic_analyzer_trigger i_trigger (
|
axi_logic_analyzer_trigger i_trigger (
|
||||||
.clk (clk_out),
|
.clk (clk_out),
|
||||||
.reset (reset),
|
.reset (reset),
|
||||||
|
@ -446,11 +538,10 @@ module axi_logic_analyzer #(
|
||||||
.overwrite_data (overwrite_data),
|
.overwrite_data (overwrite_data),
|
||||||
.input_data (adc_data_mn),
|
.input_data (adc_data_mn),
|
||||||
.od_pp_n (od_pp_n),
|
.od_pp_n (od_pp_n),
|
||||||
|
|
||||||
.triggered (up_triggered),
|
.triggered (up_triggered),
|
||||||
.pg_trigger_config (pg_trigger_config),
|
.pg_trigger_config (pg_trigger_config),
|
||||||
|
|
||||||
.streaming(streaming),
|
.streaming(streaming),
|
||||||
|
.data_delay_control (data_delay_control),
|
||||||
|
|
||||||
// bus interface
|
// bus interface
|
||||||
|
|
||||||
|
|
|
@ -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_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 =~ *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_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_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 =~ *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}]
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ module axi_logic_analyzer_reg (
|
||||||
output [19:0] pg_trigger_config,
|
output [19:0] pg_trigger_config,
|
||||||
|
|
||||||
input triggered,
|
input triggered,
|
||||||
|
|
||||||
output streaming,
|
output streaming,
|
||||||
|
output [ 9:0] data_delay_control,
|
||||||
|
|
||||||
// bus interface
|
// bus interface
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@ module axi_logic_analyzer_reg (
|
||||||
reg [19:0] up_pg_trigger_config = 20'h0;
|
reg [19:0] up_pg_trigger_config = 20'h0;
|
||||||
reg up_triggered = 0;
|
reg up_triggered = 0;
|
||||||
reg up_streaming = 0;
|
reg up_streaming = 0;
|
||||||
|
reg [ 9:0] up_data_delay_control = 10'd0;
|
||||||
|
|
||||||
wire [15:0] up_input_data;
|
wire [15:0] up_input_data;
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ module axi_logic_analyzer_reg (
|
||||||
up_streaming <= 1'd0;
|
up_streaming <= 1'd0;
|
||||||
up_trigger_holdoff <= 32'h0;
|
up_trigger_holdoff <= 32'h0;
|
||||||
up_pg_trigger_config <= 20'd0;
|
up_pg_trigger_config <= 20'd0;
|
||||||
|
up_data_delay_control <= 10'h0;
|
||||||
end else begin
|
end else begin
|
||||||
up_wack <= up_wreq;
|
up_wack <= up_wreq;
|
||||||
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h1)) begin
|
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h1)) begin
|
||||||
|
@ -192,6 +194,9 @@ module axi_logic_analyzer_reg (
|
||||||
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h15)) begin
|
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h15)) begin
|
||||||
up_pg_trigger_config <= up_wdata[19:0];
|
up_pg_trigger_config <= up_wdata[19:0];
|
||||||
end
|
end
|
||||||
|
if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h16)) begin
|
||||||
|
up_data_delay_control <= up_wdata[9:0];
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -227,6 +232,7 @@ module axi_logic_analyzer_reg (
|
||||||
5'h13: up_rdata <= {31'h0,up_streaming};
|
5'h13: up_rdata <= {31'h0,up_streaming};
|
||||||
5'h14: up_rdata <= up_trigger_holdoff;
|
5'h14: up_rdata <= up_trigger_holdoff;
|
||||||
5'h15: up_rdata <= {12'h0,up_pg_trigger_config};
|
5'h15: up_rdata <= {12'h0,up_pg_trigger_config};
|
||||||
|
5'h16: up_rdata <= {22'h0,up_data_delay_control};
|
||||||
default: up_rdata <= 0;
|
default: up_rdata <= 0;
|
||||||
endcase
|
endcase
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -237,7 +243,7 @@ module axi_logic_analyzer_reg (
|
||||||
|
|
||||||
ad_rst i_core_rst_reg (.rst_async(~up_rstn), .clk(clk), .rstn(), .rst(reset));
|
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_rstn (up_rstn),
|
||||||
.up_clk (up_clk),
|
.up_clk (up_clk),
|
||||||
.up_data_cntrl ({ up_streaming, // 1
|
.up_data_cntrl ({ up_streaming, // 1
|
||||||
|
@ -257,7 +263,8 @@ module axi_logic_analyzer_reg (
|
||||||
up_io_selection, // 16
|
up_io_selection, // 16
|
||||||
up_pg_trigger_config, // 20
|
up_pg_trigger_config, // 20
|
||||||
up_divider_counter_pg, // 32
|
up_divider_counter_pg, // 32
|
||||||
up_divider_counter_la}), // 32
|
up_divider_counter_la, // 32
|
||||||
|
up_data_delay_control}), // 10
|
||||||
|
|
||||||
.up_xfer_done (),
|
.up_xfer_done (),
|
||||||
.d_rst (1'b0),
|
.d_rst (1'b0),
|
||||||
|
@ -279,7 +286,8 @@ module axi_logic_analyzer_reg (
|
||||||
io_selection, // 16
|
io_selection, // 16
|
||||||
pg_trigger_config, // 20
|
pg_trigger_config, // 20
|
||||||
divider_counter_pg, // 32
|
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 (
|
up_xfer_status #(.DATA_WIDTH(16)) i_xfer_status (
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue