From b5dfdcfb8447fbae72aefe04d389fef38d941847 Mon Sep 17 00:00:00 2001 From: AndreiGrozav Date: Fri, 8 Mar 2019 14:21:38 +0000 Subject: [PATCH] axi_adc_trigger: Add cascade support. - Add embedded trigger as an option. The use of the embedded trigger as an option in the data stream is done for further processing, keeping the data synchronized with the trigger. When instrument (module) trigger is desired (logic_analyzer - adc_trigger), a small propagation time is required, hence the need to remove the util_extract(trigger extract) module from the data path. - Add more options for the IO triggering. This will open the door for multiple M2k synchronization(triggering). trigger_o mux: 1 - trigger flag (from regmap) 2 - external pin trigger (Ti) 3 - external pin trigger (To) 4 - internal adc trigger 5 - logic analyzer trigger The signal passed to trigger_o must not be delayed, but the new value has to be kept for a short period, 1ms (100000 clock cycles), to reduce switch noises in the system. The axi_adc_trigger handles 3 output triggers: - trigger_o - external trigger (1 clock cycle delay) - trigger_out - signals on dmac/fifo_wr_sync the start of a new transfer. A variable fifo depth is present in the data path, which delays the data arriving at the DMA with 3 clock cycles. By coincidence, the external trigger is synchronized and detected on 3 clock cycles. To get a maximum optimization the trigger_out will be delayed with 3 clock cycles for internal triggers and directly forwarded in the case of an external trigger. - trigger_out_la (cascade trigger for logic_analyzer - m2k example) Because the trigger_out_la must have a small delay, to get a realible instrument triggering mechanism, a 1 delay clock cycle must be added on the trigger paths, to avoid creating a closed combinatorial loop. Increase pcore version. The major version 3 is used to describe the instrument trigger updates. --- library/axi_adc_trigger/axi_adc_trigger.v | 139 ++++++++++++++---- library/axi_adc_trigger/axi_adc_trigger_reg.v | 91 ++++++------ 2 files changed, 156 insertions(+), 74 deletions(-) diff --git a/library/axi_adc_trigger/axi_adc_trigger.v b/library/axi_adc_trigger/axi_adc_trigger.v index fa4b11ca3..f07aac4ab 100644 --- a/library/axi_adc_trigger/axi_adc_trigger.v +++ b/library/axi_adc_trigger/axi_adc_trigger.v @@ -45,8 +45,10 @@ module axi_adc_trigger #( input clk, + input trigger_in, + input [ 1:0] trigger_i, - output [ 1:0] trigger_o, + output reg [ 1:0] trigger_o, output [ 1:0] trigger_t, input [15:0] data_a, @@ -58,6 +60,8 @@ module axi_adc_trigger #( output [15:0] data_b_trig, output data_valid_a_trig, output data_valid_b_trig, + output reg trigger_out, + output reg trigger_out_la, output [31:0] fifo_depth, @@ -101,7 +105,7 @@ module axi_adc_trigger #( wire up_rreq; wire [ 4:0] up_raddr; - wire [ 1:0] io_selection; + wire [ 7:0] io_selection; wire [ 1:0] low_level; wire [ 1:0] high_level; @@ -119,7 +123,7 @@ module axi_adc_trigger #( wire [31:0] hysteresis_b; wire [ 3:0] trigger_l_mix_b; - wire [ 2:0] trigger_out_mix; + wire [16:0] trigger_out_control; wire [31:0] trigger_delay; wire signed [DW:0] data_a_cmp; @@ -140,7 +144,11 @@ module axi_adc_trigger #( wire trigger_a_any_edge; wire trigger_b_any_edge; wire trigger_out_delayed; + wire [ 1:0] trigger_up_o_s; wire streaming; + wire trigger_out_s; + wire embedded_trigger; + wire external_trigger; reg trigger_a_d1; // synchronization flip flop reg trigger_a_d2; // synchronization flip flop @@ -163,6 +171,13 @@ module axi_adc_trigger #( reg trigger_pin_a; reg trigger_pin_b; + reg [ 1:0] trigger_o_m; + reg [ 1:0] trigger_o_m_1; + + reg trig_o_hold_0; + reg trig_o_hold_1; + reg [16:0] trig_o_hold_cnt_0; + reg [16:0] trig_o_hold_cnt_1; reg trigger_adc_a; reg trigger_adc_b; @@ -180,13 +195,9 @@ module axi_adc_trigger #( reg up_triggered_reset_d1; reg up_triggered_reset_d2; - reg [14:0] data_a_r; - reg [14:0] data_b_r; - reg data_valid_a_r; - reg data_valid_b_r; - reg [31:0] trigger_delay_counter; reg triggered; + reg trigger_out_m1; reg streaming_on; @@ -195,7 +206,7 @@ module axi_adc_trigger #( assign up_clk = s_axi_aclk; assign up_rstn = s_axi_aresetn; - assign trigger_t = io_selection; + assign trigger_t = io_selection[1:0]; assign trigger_a_fall_edge = (trigger_a_d2 == 1'b0 && trigger_a_d3 == 1'b1) ? 1'b1: 1'b0; assign trigger_a_rise_edge = (trigger_a_d2 == 1'b1 && trigger_a_d3 == 1'b0) ? 1'b1: 1'b0; @@ -209,10 +220,76 @@ module axi_adc_trigger #( assign limit_a_cmp = limit_a[DW:0]; assign limit_b_cmp = limit_b[DW:0]; - assign data_a_trig = trigger_delay == 32'h0 ? {trigger_out_mixed | streaming_on, data_a_r} : {trigger_out_delayed |streaming_on, data_a_r}; - assign data_b_trig = trigger_delay == 32'h0 ? {trigger_out_mixed | streaming_on, data_b_r} : {trigger_out_delayed |streaming_on, data_b_r}; - assign data_valid_a_trig = data_valid_a_r; - assign data_valid_b_trig = data_valid_b_r; + always @(*) begin + case(io_selection[4:2]) + 3'h0: trigger_o_m[0] = trigger_up_o_s[0]; + 3'h1: trigger_o_m[0] = trigger_i[0]; + 3'h2: trigger_o_m[0] = trigger_i[1]; + 3'h3: trigger_o_m[0] = trigger_out_mixed; + 3'h4: trigger_o_m[0] = trigger_in; + default: trigger_o_m[0] = trigger_up_o_s[0]; + endcase + case(io_selection[7:5]) + 3'h0: trigger_o_m[1] = trigger_up_o_s[1]; + 3'h1: trigger_o_m[1] = trigger_i[1]; + 3'h2: trigger_o_m[1] = trigger_i[0]; + 3'h3: trigger_o_m[1] = trigger_out_mixed; + 3'h4: trigger_o_m[1] = trigger_in; + default: trigger_o_m[1] = trigger_up_o_s[1]; + endcase + end + + // External trigger output hold 100000 clock cycles(1ms) on polarity change. + // All trigger signals that are to be outputted on the external trigger after a + // trigger out is acknowledged by the hold counter will be disregarded for 1ms. + // This was done to avoid noise created by high frequency switches on long + // wires. + always @(posedge clk) begin + // trigger_o[0] hold start + if ((trigger_o_m[0] != trigger_o_m_1[0]) & (trig_o_hold_cnt_0 == 17'd0)) begin + trig_o_hold_cnt_0 <= 17'd100000; + trig_o_hold_0 <= trigger_o_m[0]; + end + if (trig_o_hold_cnt_0 != 17'd0) begin + trig_o_hold_cnt_0 <= trig_o_hold_cnt_0 - 17'd1; + end + trigger_o_m_1[0] <= trigger_o_m[0]; + + // trigger_o[1] hold start + if ((trigger_o_m[1] != trigger_o_m_1[1]) & (trig_o_hold_cnt_1 == 17'd0)) begin + trig_o_hold_cnt_1 <= 17'd100000; + trig_o_hold_1 <= trigger_o_m[1]; + end + if (trig_o_hold_cnt_1 != 17'd0) begin + trig_o_hold_cnt_1 <= trig_o_hold_cnt_1 - 17'd1; + end + trigger_o_m_1[1] <= trigger_o_m[1]; + + // hold + trigger_o[0] <= (trig_o_hold_cnt_0 == 'd0) ? trigger_o_m[0] : trig_o_hold_0; + trigger_o[1] <= (trig_o_hold_cnt_1 == 'd0) ? trigger_o_m[1] : trig_o_hold_1; + end + + // - keep data in sync with the trigger. The trigger bypasses the variable fifo. + // The data goes through and it is delayed with 4 clock cycles) + always @(posedge clk) begin + trigger_out_m1 <= trigger_out_s; + trigger_out <= trigger_out_m1; + + // triggers logic analyzer + trigger_out_la <= trigger_out_mixed; + end + + // the embedded trigger does not require any extra delay, since the util_extract + // present in this case, delays the trigger with 2 clock cycles + assign data_a_trig = (embedded_trigger == 1'h0) ? {data_a[14],data_a[14:0]} : {trigger_out_s,data_a[14:0]}; + assign data_b_trig = (embedded_trigger == 1'h0) ? {data_b[14],data_b[14:0]} : {trigger_out_s,data_b[14:0]}; + + assign embedded_trigger = trigger_out_control[16]; + assign trigger_out_s = (trigger_delay == 32'h0) ? (trigger_out_mixed | streaming_on) : + (trigger_out_delayed | streaming_on); + assign data_valid_a_trig = data_valid_a; + assign data_valid_b_trig = data_valid_b; assign trigger_out_delayed = (trigger_delay_counter == 32'h0) ? 1 : 0; @@ -220,7 +297,7 @@ module axi_adc_trigger #( if (trigger_delay == 0) begin trigger_delay_counter <= 32'h0; end else begin - if (data_valid_a_r == 1'b1) begin + if (data_valid_a == 1'b1) begin triggered <= trigger_out_mixed | triggered; if (trigger_delay_counter == 0) begin trigger_delay_counter <= trigger_delay; @@ -236,13 +313,13 @@ module axi_adc_trigger #( always @(posedge clk) begin if (trigger_delay == 0) begin - if (streaming == 1'b1 && data_valid_a_r == 1'b1 && trigger_out_mixed == 1'b1) begin + if (streaming == 1'b1 && data_valid_a == 1'b1 && trigger_out_mixed == 1'b1) begin streaming_on <= 1'b1; end else if (streaming == 1'b0) begin streaming_on <= 1'b0; end end else begin - if (streaming == 1'b1 && data_valid_a_r == 1'b1 && trigger_out_delayed == 1'b1) begin + if (streaming == 1'b1 && data_valid_a == 1'b1 && trigger_out_delayed == 1'b1) begin streaming_on <= 1'b1; end else if (streaming == 1'b0) begin streaming_on <= 1'b0; @@ -251,7 +328,7 @@ module axi_adc_trigger #( end always @(posedge clk) begin - if (data_valid_a_r == 1'b1 && trigger_out_mixed == 1'b1) begin + if (data_valid_a == 1'b1 && trigger_out_mixed == 1'b1) begin up_triggered_set <= 1'b1; end else if (up_triggered_reset == 1'b1) begin up_triggered_set <= 1'b0; @@ -267,13 +344,6 @@ module axi_adc_trigger #( up_triggered <= up_triggered_d2; end - always @(posedge clk) begin - data_a_r <= data_a[14:0]; - data_valid_a_r <= data_valid_a; - data_b_r <= data_b[14:0]; - data_valid_b_r <= data_valid_b; - end - always @(*) begin case(trigger_l_mix_a) 4'h0: trigger_a = 1'b1; @@ -350,12 +420,16 @@ module axi_adc_trigger #( end always @(*) begin - case(trigger_out_mix) - 3'h0: trigger_out_mixed = trigger_a; - 3'h1: trigger_out_mixed = trigger_b; - 3'h2: trigger_out_mixed = trigger_a | trigger_b; - 3'h3: trigger_out_mixed = trigger_a & trigger_b; - 3'h4: trigger_out_mixed = trigger_a ^ trigger_b; + case(trigger_out_control[3:0]) + 4'h0: trigger_out_mixed = trigger_a; + 4'h1: trigger_out_mixed = trigger_b; + 4'h2: trigger_out_mixed = trigger_a | trigger_b; + 4'h3: trigger_out_mixed = trigger_a & trigger_b; + 4'h4: trigger_out_mixed = trigger_a ^ trigger_b; + 4'h5: trigger_out_mixed = trigger_in; + 4'h6: trigger_out_mixed = trigger_a | trigger_in; + 4'h7: trigger_out_mixed = trigger_b | trigger_in; + 4'h8: trigger_out_mixed = trigger_a | trigger_b | trigger_in; default: trigger_out_mixed = trigger_a; endcase end @@ -417,7 +491,7 @@ module axi_adc_trigger #( .clk(clk), .io_selection(io_selection), - .trigger_o(trigger_o), + .trigger_o(trigger_up_o_s), .triggered(up_triggered), .low_level(low_level), @@ -436,8 +510,9 @@ module axi_adc_trigger #( .hysteresis_b(hysteresis_b), .trigger_l_mix_b(trigger_l_mix_b), - .trigger_out_mix(trigger_out_mix), + .trigger_out_control(trigger_out_control), .trigger_delay(trigger_delay), + .fifo_depth(fifo_depth), .streaming(streaming), diff --git a/library/axi_adc_trigger/axi_adc_trigger_reg.v b/library/axi_adc_trigger/axi_adc_trigger_reg.v index 21432a760..4c97d45fc 100644 --- a/library/axi_adc_trigger/axi_adc_trigger_reg.v +++ b/library/axi_adc_trigger/axi_adc_trigger_reg.v @@ -39,8 +39,8 @@ module axi_adc_trigger_reg ( input clk, - output reg [ 1:0] io_selection, - output reg [ 1:0] trigger_o, + output [ 7:0] io_selection, + output [ 1:0] trigger_o, input triggered, output [ 1:0] low_level, @@ -59,9 +59,10 @@ module axi_adc_trigger_reg ( output [31:0] hysteresis_b, output [ 3:0] trigger_l_mix_b, - output [ 2:0] trigger_out_mix, + output [16:0] trigger_out_control, output [31:0] fifo_depth, output [31:0] trigger_delay, + output streaming, // bus interface @@ -79,40 +80,42 @@ module axi_adc_trigger_reg ( // internal signals - wire [ 9:0] config_trigger; + wire [ 9:0] config_trigger_i; // internal registers - reg [31:0] up_version = 32'h00010000; + reg [31:0] up_version = 32'h00030000; reg [31:0] up_scratch = 32'h0; - reg [ 9:0] up_config_trigger = 10'h0; + reg [ 7:0] up_io_selection = 8'h0; + reg [ 1:0] up_trigger_o = 2'h0; + reg [ 9:0] up_config_trigger_i = 10'h0; reg [15:0] up_limit_a = 16'h0; reg [ 1:0] up_function_a = 2'h0; reg [31:0] up_hysteresis_a = 32'h0; - reg [ 3:0] up_trigger_l_mix_a = 32'h0; + reg [ 3:0] up_trigger_l_mix_a = 4'h0; reg [15:0] up_limit_b = 16'h0; reg [ 1:0] up_function_b = 2'h0; reg [31:0] up_hysteresis_b = 32'h0; - reg [ 3:0] up_trigger_l_mix_b = 32'h0; - reg [ 2:0] up_trigger_out_mix = 32'h0; + reg [ 3:0] up_trigger_l_mix_b = 4'h0; + reg [16:0] up_trigger_out_control = 17'h0; reg [31:0] up_fifo_depth = 32'h0; reg [31:0] up_trigger_delay = 32'h0; reg up_triggered = 1'h0; reg up_streaming = 1'h0; - assign low_level = config_trigger[1:0]; - assign high_level = config_trigger[3:2]; - assign any_edge = config_trigger[5:4]; - assign rise_edge = config_trigger[7:6]; - assign fall_edge = config_trigger[9:8]; + assign low_level = config_trigger_i[1:0]; + assign high_level = config_trigger_i[3:2]; + assign any_edge = config_trigger_i[5:4]; + assign rise_edge = config_trigger_i[7:6]; + assign fall_edge = config_trigger_i[9:8]; always @(negedge up_rstn or posedge up_clk) begin if (up_rstn == 0) begin up_wack <= 'd0; up_scratch <= 'd0; - io_selection <= 'd3; - trigger_o <= 'd0; - up_config_trigger <= 'd0; + up_trigger_o <= 'd0; + up_io_selection <= 'd1; + up_config_trigger_i <= 'd0; up_limit_a <= 'd0; up_function_a <= 'd0; up_hysteresis_a <= 'd0; @@ -123,7 +126,7 @@ module axi_adc_trigger_reg ( up_trigger_delay <= 'd0; up_trigger_l_mix_a <= 'd0; up_trigger_l_mix_b <= 'd0; - up_trigger_out_mix <= 'd0; + up_trigger_out_control <= 'd0; up_triggered <= 1'd0; up_streaming <= 1'd0; end else begin @@ -132,13 +135,13 @@ module axi_adc_trigger_reg ( up_scratch <= up_wdata; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h2)) begin - trigger_o <= up_wdata[1:0]; + up_trigger_o <= up_wdata[1:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h3)) begin - io_selection <= up_wdata[1:0]; + up_io_selection <= up_wdata[7:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h4)) begin - up_config_trigger <= up_wdata[9:0]; + up_config_trigger_i <= up_wdata[9:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'h5)) begin up_limit_a <= up_wdata[15:0]; @@ -165,7 +168,7 @@ module axi_adc_trigger_reg ( up_trigger_l_mix_b <= up_wdata[3:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'hd)) begin - up_trigger_out_mix <= up_wdata[2:0]; + up_trigger_out_control <= up_wdata[16:0]; end if ((up_wreq == 1'b1) && (up_waddr[4:0] == 5'he)) begin up_fifo_depth <= up_wdata; @@ -196,9 +199,9 @@ module axi_adc_trigger_reg ( case (up_raddr[4:0]) 5'h0: up_rdata <= up_version; 5'h1: up_rdata <= up_scratch; - 5'h2: up_rdata <= {30'h0,trigger_o}; - 5'h3: up_rdata <= {30'h0,io_selection}; - 5'h4: up_rdata <= {22'h0,up_config_trigger}; + 5'h2: up_rdata <= {30'h0,up_trigger_o}; + 5'h3: up_rdata <= {24'h0,up_io_selection}; + 5'h4: up_rdata <= {22'h0,up_config_trigger_i}; 5'h5: up_rdata <= {16'h0,up_limit_a}; 5'h6: up_rdata <= {30'h0,up_function_a}; 5'h7: up_rdata <= up_hysteresis_a; @@ -207,7 +210,7 @@ module axi_adc_trigger_reg ( 5'ha: up_rdata <= {30'h0,up_function_b}; 5'hb: up_rdata <= up_hysteresis_b; 5'hc: up_rdata <= {28'h0,up_trigger_l_mix_b}; - 5'hd: up_rdata <= {29'h0,up_trigger_out_mix}; + 5'hd: up_rdata <= {15'h0,up_trigger_out_control}; 5'he: up_rdata <= up_fifo_depth; 5'hf: up_rdata <= {31'h0,up_triggered}; 5'h10: up_rdata <= up_trigger_delay; @@ -220,28 +223,32 @@ module axi_adc_trigger_reg ( end end - up_xfer_cntrl #(.DATA_WIDTH(186)) i_xfer_cntrl ( + up_xfer_cntrl #(.DATA_WIDTH(210)) i_xfer_cntrl ( .up_rstn (up_rstn), .up_clk (up_clk), - .up_data_cntrl ({ up_streaming, // 1 - up_config_trigger, // 10 - up_limit_a, // 16 - up_function_a, // 2 - up_hysteresis_a, // 32 - up_trigger_l_mix_a, // 4 - up_limit_b, // 16 - up_function_b, // 2 - up_hysteresis_b, // 32 - up_trigger_l_mix_b, // 4 - up_trigger_out_mix, // 3 - up_fifo_depth, // 32 - up_trigger_delay}), // 32 + .up_data_cntrl ({ up_streaming, // 1 + up_trigger_o, // 2 + up_io_selection, // 8 + up_config_trigger_i, // 10 + up_limit_a, // 16 + up_function_a, // 2 + up_hysteresis_a, // 32 + up_trigger_l_mix_a, // 4 + up_limit_b, // 16 + up_function_b, // 2 + up_hysteresis_b, // 32 + up_trigger_l_mix_b, // 4 + up_trigger_out_control, // 17 + up_fifo_depth, // 32 + up_trigger_delay}), // 32 .up_xfer_done (), .d_rst (1'b0), .d_clk (clk), .d_data_cntrl ({ streaming, // 1 - config_trigger, // 10 + trigger_o, // 2 + io_selection, // 8 + config_trigger_i, // 10 limit_a, // 16 function_a, // 2 hysteresis_a, // 32 @@ -250,7 +257,7 @@ module axi_adc_trigger_reg ( function_b, // 2 hysteresis_b, // 32 trigger_l_mix_b, // 4 - trigger_out_mix, // 3 + trigger_out_control,// 17 fifo_depth, // 32 trigger_delay})); // 32