Trigger selection

This commit is contained in:
2026-03-05 16:24:29 +01:00
parent cfdec1aec7
commit 08c0f6967b
2 changed files with 59 additions and 21 deletions

View File

@@ -30,9 +30,10 @@ module signal_scope_q15 #(
reg scope_armed; reg scope_armed;
reg scope_triggered; reg scope_triggered;
reg capture_done; reg capture_done;
reg [1:0] trigger_channel;
reg [15:0] trig_val; reg [15:0] trig_val;
reg [15:0] signal_a_prev; reg [15:0] trigger_prev;
reg signal_a_prev_valid; reg trigger_prev_valid;
reg [15:0] signal_a; reg [15:0] signal_a;
reg [15:0] signal_b; reg [15:0] signal_b;
@@ -54,6 +55,8 @@ module signal_scope_q15 #(
wire [aw-1:0] wb_mem_idx = wb_adr[aw+2:3]; wire [aw-1:0] wb_mem_idx = wb_adr[aw+2:3];
wire wb_is_reg = (wb_adr[31:28] == reg_base_addr[31:28]); wire wb_is_reg = (wb_adr[31:28] == reg_base_addr[31:28]);
wire [3:0] wb_reg_idx = wb_adr[5:2]; wire [3:0] wb_reg_idx = wb_adr[5:2];
reg [15:0] trigger_sample;
reg trigger_sample_valid;
jtag_wb_bridge #( jtag_wb_bridge #(
.chain(chain), .chain(chain),
@@ -72,6 +75,27 @@ module signal_scope_q15 #(
.o_cmd_reset() .o_cmd_reset()
); );
always @(*) begin
case(trigger_channel)
2'd0: begin
trigger_sample = i_signal_a;
trigger_sample_valid = i_signal_valid_a;
end
2'd1: begin
trigger_sample = i_signal_b;
trigger_sample_valid = i_signal_valid_b;
end
2'd2: begin
trigger_sample = i_signal_c;
trigger_sample_valid = i_signal_valid_c;
end
default: begin
trigger_sample = i_signal_d;
trigger_sample_valid = i_signal_valid_d;
end
endcase
end
always @(posedge i_clk) begin always @(posedge i_clk) begin
if(i_rst) begin if(i_rst) begin
counter <= {aw{1'b0}}; counter <= {aw{1'b0}};
@@ -81,11 +105,12 @@ module signal_scope_q15 #(
scope_armed <= 1'b0; scope_armed <= 1'b0;
scope_triggered <= 1'b0; scope_triggered <= 1'b0;
capture_done <= 1'b0; capture_done <= 1'b0;
trigger_channel <= 2'd0;
wb_ack <= 1'b0; wb_ack <= 1'b0;
wb_rdt <= 32'b0; wb_rdt <= 32'b0;
trig_val <= 16'h0000; trig_val <= 16'h0000;
signal_a_prev <= 16'h0000; trigger_prev <= 16'h0000;
signal_a_prev_valid <= 1'b0; trigger_prev_valid <= 1'b0;
signal_a <= 0; signal_a <= 0;
signal_b <= 0; signal_b <= 0;
signal_c <= 0; signal_c <= 0;
@@ -100,18 +125,6 @@ module signal_scope_q15 #(
if(i_signal_valid_a) begin if(i_signal_valid_a) begin
signal_a <= i_signal_a; signal_a <= i_signal_a;
signal_a_pending <= 1'b1; signal_a_pending <= 1'b1;
// Trigger on signal_a rising across trig_val.
if(scope_armed && trigger_enable && !count_enable) begin
if(signal_a_prev_valid &&
($signed(signal_a_prev) < $signed(trig_val)) &&
($signed(i_signal_a) >= $signed(trig_val))) begin
count_enable <= 1'b1;
scope_triggered <= 1'b1;
end
signal_a_prev <= i_signal_a;
signal_a_prev_valid <= 1'b1;
end
end end
if(i_signal_valid_b) begin if(i_signal_valid_b) begin
signal_b <= i_signal_b; signal_b <= i_signal_b;
@@ -126,6 +139,18 @@ module signal_scope_q15 #(
signal_d_pending <= 1'b1; signal_d_pending <= 1'b1;
end end
// Trigger on selected channel rising across trig_val.
if(scope_armed && trigger_enable && !count_enable && trigger_sample_valid) begin
if(trigger_prev_valid &&
($signed(trigger_prev) < $signed(trig_val)) &&
($signed(trigger_sample) >= $signed(trig_val))) begin
count_enable <= 1'b1;
scope_triggered <= 1'b1;
end
trigger_prev <= trigger_sample;
trigger_prev_valid <= 1'b1;
end
// Arm/rearm capture. If trigger is disabled, start capture immediately. // Arm/rearm capture. If trigger is disabled, start capture immediately.
if(arm_req) begin if(arm_req) begin
counter <= {aw{1'b0}}; counter <= {aw{1'b0}};
@@ -133,7 +158,7 @@ module signal_scope_q15 #(
scope_armed <= 1'b1; scope_armed <= 1'b1;
scope_triggered <= !trigger_enable; scope_triggered <= !trigger_enable;
capture_done <= 1'b0; capture_done <= 1'b0;
signal_a_prev_valid <= 1'b0; trigger_prev_valid <= 1'b0;
signal_a_pending <= 1'b0; signal_a_pending <= 1'b0;
signal_b_pending <= 1'b0; signal_b_pending <= 1'b0;
signal_c_pending <= 1'b0; signal_c_pending <= 1'b0;
@@ -178,6 +203,8 @@ module signal_scope_q15 #(
arm_req <= 1'b1; arm_req <= 1'b1;
// Bit 1: trigger enable. // Bit 1: trigger enable.
trigger_enable <= wb_dat[1]; trigger_enable <= wb_dat[1];
// Bits [3:2]: trigger channel (0=a,1=b,2=c,3=d).
trigger_channel <= wb_dat[3:2];
end end
end end
reg_trig_val: begin reg_trig_val: begin
@@ -191,8 +218,8 @@ module signal_scope_q15 #(
end else begin end else begin
if(wb_is_reg) begin if(wb_is_reg) begin
case(wb_reg_idx) case(wb_reg_idx)
// [1]=trigger_enable, [0]=arm bit is write-pulse only. // [3:2]=trigger_channel, [1]=trigger_enable, [0]=arm(write pulse only/read 0).
reg_control: wb_rdt <= {30'b0, trigger_enable, 1'b0}; reg_control: wb_rdt <= {28'b0, trigger_channel, trigger_enable, 1'b0};
// [0]=triggered, [1]=capturing, [2]=armed, [3]=done // [0]=triggered, [1]=capturing, [2]=armed, [3]=done
reg_status: wb_rdt <= {28'b0, capture_done, scope_armed, count_enable, scope_triggered}; reg_status: wb_rdt <= {28'b0, capture_done, scope_armed, count_enable, scope_triggered};
reg_trig_val: wb_rdt <= {16'b0, trig_val}; reg_trig_val: wb_rdt <= {16'b0, trig_val};

View File

@@ -53,6 +53,12 @@ def parse_args() -> argparse.Namespace:
default=None, default=None,
help="Optional trigger threshold (16-bit, signal_a rising crossing). If omitted, triggering is disabled.", help="Optional trigger threshold (16-bit, signal_a rising crossing). If omitted, triggering is disabled.",
) )
parser.add_argument(
"--trigger-channel",
choices=["a", "b", "c", "d"],
default="a",
help="Trigger source channel when triggering is enabled",
)
parser.add_argument( parser.add_argument(
"--unsigned", "--unsigned",
action="store_true", action="store_true",
@@ -81,15 +87,20 @@ def parse_args() -> argparse.Namespace:
def capture_once(bridge, args: argparse.Namespace) -> list[tuple[int, int, int, int]]: def capture_once(bridge, args: argparse.Namespace) -> list[tuple[int, int, int, int]]:
samples = [] samples = []
frame_count = args.depth frame_count = args.depth
trigger_channel_map = {"a": 0, "b": 1, "c": 2, "d": 3}
trigger_channel = trigger_channel_map[args.trigger_channel]
if args.trigger_value is None: if args.trigger_value is None:
print("[signal_scope] Arming scope with trigger disabled...") print("[signal_scope] Arming scope with trigger disabled...")
bridge.write32(REG_CONTROL, 0x1) # bit0: arm pulse, bit1: trigger enable=0 bridge.write32(REG_CONTROL, 0x1) # bit0: arm pulse, bit1: trigger enable=0
else: else:
trig_val = args.trigger_value & 0xFFFF trig_val = args.trigger_value & 0xFFFF
print(f"[signal_scope] Config trigger: trig_val=0x{trig_val:04x}, source=signal_a rising") print(
f"[signal_scope] Config trigger: trig_val=0x{trig_val:04x}, "
f"source=signal_{args.trigger_channel} rising"
)
bridge.write32(REG_TRIG_VAL, trig_val) bridge.write32(REG_TRIG_VAL, trig_val)
print("[signal_scope] Arming scope with trigger enabled...") print("[signal_scope] Arming scope with trigger enabled...")
bridge.write32(REG_CONTROL, 0x3) # bit0: arm pulse, bit1: trigger enable bridge.write32(REG_CONTROL, 0x3 | (trigger_channel << 2)) # bit0: arm, bit1: trig_en, bits[3:2]: channel
# Wait until the new arm command is active, then wait for its trigger event. # Wait until the new arm command is active, then wait for its trigger event.
while (bridge.read32(REG_STATUS) & 0x4) == 0: while (bridge.read32(REG_STATUS) & 0x4) == 0: