From e0a276cd184c22930e20333ab7cff4b7868a4a8c Mon Sep 17 00:00:00 2001 From: Joppe Blondel Date: Thu, 5 Mar 2026 15:21:41 +0100 Subject: [PATCH] control register instead of reset output --- .../signal_scope/rtl/signal_scope_q15.v | 53 ++++++++++++++----- .../signal/signal_scope/tool/capture_plot.py | 14 +++-- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/cores/signal/signal_scope/rtl/signal_scope_q15.v b/cores/signal/signal_scope/rtl/signal_scope_q15.v index b14c255..3caf4ff 100644 --- a/cores/signal/signal_scope/rtl/signal_scope_q15.v +++ b/cores/signal/signal_scope/rtl/signal_scope_q15.v @@ -17,11 +17,14 @@ module signal_scope_q15 #( ); localparam aw = `CLOG2(depth); localparam [aw-1:0] depth_last = depth-1; + localparam [31:0] reg_base_addr = 32'h8000_0000; + localparam [3:0] reg_control = 4'h0; + localparam [3:0] reg_status = 4'h1; (* ram_style = "block" *) reg [16*4-1:0] mem[depth-1:0]; reg [aw-1:0] counter; reg count_enable; - reg rearm_prev; + reg arm_req; reg [15:0] signal_a; reg [15:0] signal_b; @@ -40,8 +43,9 @@ module signal_scope_q15 #( wire wb_stb; reg [31:0] wb_rdt; reg wb_ack; - wire rearm_cmd; 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 [3:0] wb_reg_idx = wb_adr[5:2]; jtag_wb_bridge #( .chain(chain), @@ -57,14 +61,14 @@ module signal_scope_q15 #( .o_wb_stb(wb_stb), .i_wb_rdt(wb_rdt), .i_wb_ack(wb_ack), - .o_cmd_reset(rearm_cmd) + .o_cmd_reset() ); always @(posedge i_clk) begin if(i_rst) begin counter <= {aw{1'b0}}; count_enable <= 1'b0; - rearm_prev <= 1'b0; + arm_req <= 1'b0; wb_ack <= 1'b0; wb_rdt <= 32'b0; signal_a <= 0; @@ -95,9 +99,8 @@ module signal_scope_q15 #( signal_d_pending <= 1'b1; end - // Rearm on rising edge of reset command from JTAG bridge. - rearm_prev <= rearm_cmd; - if(rearm_cmd && !rearm_prev) begin + // Arm/rearm capture on control-register command pulse. + if(arm_req) begin counter <= {aw{1'b0}}; count_enable <= 1'b1; signal_a_pending <= 1'b0; @@ -110,7 +113,7 @@ module signal_scope_q15 #( if(count_enable && signal_a_pending && signal_b_pending && signal_c_pending && signal_d_pending) begin if(counter <= depth_last) begin mem[counter] <= {signal_a, signal_b, signal_c, signal_d}; - counter <= counter + 3'd1; + counter <= counter + {{(aw-1){1'b0}}, 1'b1}; if(counter == depth_last) count_enable <= 1'b0; end else begin @@ -122,16 +125,40 @@ module signal_scope_q15 #( signal_d_pending <= 1'b0; end - // Simple WB slave response for JTAG reads (32-bit = 2x16-bit samples). + // WB slave response: register window + capture memory window. + arm_req <= 1'b0; wb_ack <= wb_cyc & wb_stb & !wb_ack; if(wb_cyc & wb_stb & !wb_ack) begin if(wb_we) begin wb_rdt <= 32'b0; - end else if(wb_mem_idx <= depth_last) begin - // A single frame is 64-bit: {a, b, c, d}. WB reads low/high 32-bit halves. - wb_rdt <= wb_adr[2] ? mem[wb_mem_idx][63:32] : mem[wb_mem_idx][31:0]; + if(wb_is_reg) begin + // Keep register write decode in one case so new writable registers + // can be added without touching memory-path logic. + case(wb_reg_idx) + reg_control: begin + // Bit 0: write-1 to arm/rearm scope (pulse). + if(wb_sel[0] && wb_dat[0]) + arm_req <= 1'b1; + end + default: begin + end + endcase + end end else begin - wb_rdt <= 32'b0; + if(wb_is_reg) begin + case(wb_reg_idx) + // Write-pulse register: reads as zero. + reg_control: wb_rdt <= 32'b0; + // Basic status for polling/debug. + reg_status: wb_rdt <= {30'b0, count_enable, (counter == depth_last)}; + default: wb_rdt <= 32'b0; + endcase + end else if(wb_mem_idx <= depth_last) begin + // A single frame is 64-bit: {a, b, c, d}. WB reads low/high 32-bit halves. + wb_rdt <= wb_adr[2] ? mem[wb_mem_idx][63:32] : mem[wb_mem_idx][31:0]; + end else begin + wb_rdt <= 32'b0; + end end end diff --git a/cores/signal/signal_scope/tool/capture_plot.py b/cores/signal/signal_scope/tool/capture_plot.py index 9bf2825..2e6f835 100755 --- a/cores/signal/signal_scope/tool/capture_plot.py +++ b/cores/signal/signal_scope/tool/capture_plot.py @@ -6,6 +6,11 @@ from pathlib import Path import matplotlib.pyplot as plt +MEM_BASE = 0x00000000 +REG_BASE = 0x80000000 +REG_CONTROL = REG_BASE + 0x00 +REG_STATUS = REG_BASE + 0x04 + def _add_bridge_module_path() -> None: here = Path(__file__).resolve() @@ -64,16 +69,15 @@ def parse_args() -> argparse.Namespace: def capture_once(bridge, args: argparse.Namespace) -> list[tuple[int, int, int, int]]: samples = [] frame_count = args.depth - print("[signal_scope] Arming scope (set_reset=1 -> 0)...") - bridge.set_reset(True) - bridge.set_reset(False) + print("[signal_scope] Arming scope (write REG_CONTROL bit0=1)...") + bridge.write32(REG_CONTROL, 0x1) if args.wait_s > 0: print(f"[signal_scope] Waiting {args.wait_s:.3f}s for capture to complete...") time.sleep(args.wait_s) print(f"[signal_scope] Reading back {frame_count} frames...") for idx in range(frame_count): - base = idx * 8 + base = MEM_BASE + idx * 8 low = bridge.read32(base) high = bridge.read32(base + 4) @@ -151,6 +155,8 @@ def main() -> int: bridge.clear_flags() bridge.ping() print("[signal_scope] Bridge ready") + status = bridge.read32(REG_STATUS) + print(f"[signal_scope] Status: 0x{status:08x}") fig, ax = plt.subplots(figsize=(12, 4)) capture_idx = 1