Просмотр исходного кода

Remove obsolete FPGA demo sources

botao 1 неделя назад
Родитель
Сommit
bb9e0e68f5

+ 8 - 10
Dockerfile

@@ -1,18 +1,16 @@
 FROM docker.m.daocloud.io/library/debian:trixie-slim
 
 RUN apt-get update && \
-    apt-get install -y --no-install-recommends iverilog && \
-    rm -rf /var/lib/apt/lists/*
+    apt-get install -y --no-install-recommends \
+      iverilog \
+      python3 \
+    && rm -rf /var/lib/apt/lists/*
 
 WORKDIR /app
 
-COPY rtl/ rtl/
-COPY sim/ sim/
+COPY fpga/fpga_pwm_trace_project/ ./
 
-RUN mkdir -p build && \
-    iverilog -g2012 \
-      -o build/pwm_control_demo.vvp \
-      rtl/pwm_control_demo.v \
-      sim/pwm_control_demo_tb.v
+RUN chmod +x scripts/run_test.sh && \
+    ./scripts/run_test.sh
 
-CMD ["sh", "-c", "vvp build/pwm_control_demo.vvp && tail -f /dev/null"]
+CMD ["sh", "-c", "./scripts/run_test.sh && tail -f /dev/null"]

+ 0 - 330
rtl/axis_travel_monitor.v

@@ -1,330 +0,0 @@
-`timescale 1ns/1ps
-
-module axis_travel_monitor #(
-    // How far beyond the target is considered a serious overrun.
-    parameter integer OVERRUN_LIMIT = 20
-)(
-    input  wire                    clk,
-    input  wire                    reset_n,
-
-    // Start a new travel segment.
-    input  wire                    start,
-
-    // Current measured position.
-    input  wire signed [31:0]      current_position,
-
-    // Relative requested travel.
-    // +500 = positive travel
-    // -500 = negative travel
-    input  wire signed [31:0]      target_travel,
-
-    // Allowed target error.
-    input  wire [31:0]             tolerance,
-
-    // Physical limits.
-    input  wire                    limit_pos,
-    input  wire                    limit_neg,
-
-    // Position captured when START occurs.
-    output reg  signed [31:0]      start_position,
-
-    // start_position + target_travel
-    output reg  signed [31:0]      target_position,
-
-    // current_position - start_position
-    output wire signed [31:0]      travel,
-
-    // Travel state.
-    output reg                     busy,
-
-    // Current position is inside target tolerance.
-    output wire                    in_position,
-
-    // Normal completion.
-    output reg                     done,
-
-    // Limit status.
-    output reg                     limit_hit,
-    output reg                     limit_pos_hit,
-    output reg                     limit_neg_hit,
-
-    // Target was crossed without entering tolerance window.
-    output reg                     overshoot,
-
-    // Position went too far beyond target.
-    output reg                     travel_overrun
-);
-
-    reg signed [31:0] latched_target_travel;
-
-    // ------------------------------------------------------------
-    // Travel calculation
-    // ------------------------------------------------------------
-
-    assign travel =
-        current_position - start_position;
-
-    // ------------------------------------------------------------
-    // Extend positions to 33 bits before subtraction/comparison.
-    // ------------------------------------------------------------
-
-    wire signed [32:0] current_ext;
-    wire signed [32:0] target_ext;
-    wire signed [32:0] tolerance_ext;
-    wire signed [32:0] overrun_limit_ext;
-
-    wire signed [32:0] position_error;
-    wire        [32:0] abs_position_error;
-
-    assign current_ext =
-        {current_position[31], current_position};
-
-    assign target_ext =
-        {target_position[31], target_position};
-
-    assign tolerance_ext =
-        {1'b0, tolerance};
-
-    assign overrun_limit_ext =
-        OVERRUN_LIMIT;
-
-    assign position_error =
-        current_ext - target_ext;
-
-    assign abs_position_error =
-        position_error[32]
-        ? -position_error
-        : position_error;
-
-    // ------------------------------------------------------------
-    // Current position is inside allowed target window.
-    // ------------------------------------------------------------
-
-    assign in_position =
-        (busy || done) &&
-        (abs_position_error <= tolerance_ext);
-
-    // ------------------------------------------------------------
-    // Overshoot detection
-    //
-    // Positive movement:
-    //
-    // target = 1500
-    // tolerance = 5
-    //
-    // >1505 means target window was passed.
-    //
-    // Negative movement is the opposite.
-    // ------------------------------------------------------------
-
-    wire positive_overshoot_now;
-    wire negative_overshoot_now;
-
-    assign positive_overshoot_now =
-        (latched_target_travel > 0) &&
-        (current_ext > (target_ext + tolerance_ext));
-
-    assign negative_overshoot_now =
-        (latched_target_travel < 0) &&
-        (current_ext < (target_ext - tolerance_ext));
-
-    // ------------------------------------------------------------
-    // Serious travel-overrun detection.
-    //
-    // Default OVERRUN_LIMIT = 20.
-    //
-    // target=1500:
-    // positive overrun at >=1520
-    //
-    // target=2500:
-    // negative overrun at <=2480
-    // ------------------------------------------------------------
-
-    wire positive_overrun_now;
-    wire negative_overrun_now;
-
-    assign positive_overrun_now =
-        (latched_target_travel > 0) &&
-        (current_ext >=
-            (target_ext + overrun_limit_ext));
-
-    assign negative_overrun_now =
-        (latched_target_travel < 0) &&
-        (current_ext <=
-            (target_ext - overrun_limit_ext));
-
-    // ------------------------------------------------------------
-    // Main state logic
-    // ------------------------------------------------------------
-
-    always @(posedge clk or negedge reset_n) begin
-
-        if (!reset_n) begin
-
-            start_position        <= 32'sd0;
-            target_position       <= 32'sd0;
-            latched_target_travel <= 32'sd0;
-
-            busy                  <= 1'b0;
-            done                  <= 1'b0;
-
-            limit_hit             <= 1'b0;
-            limit_pos_hit         <= 1'b0;
-            limit_neg_hit         <= 1'b0;
-
-            overshoot             <= 1'b0;
-            travel_overrun        <= 1'b0;
-
-        end else begin
-
-            // ====================================================
-            // New travel segment
-            // ====================================================
-
-            if (start) begin
-
-                start_position <=
-                    current_position;
-
-                target_position <=
-                    current_position + target_travel;
-
-                latched_target_travel <=
-                    target_travel;
-
-                done           <= 1'b0;
-
-                limit_hit      <= 1'b0;
-                limit_pos_hit  <= 1'b0;
-                limit_neg_hit  <= 1'b0;
-
-                overshoot      <= 1'b0;
-                travel_overrun <= 1'b0;
-
-                // Zero-distance command is complete immediately.
-                if (target_travel == 0) begin
-
-                    busy <= 1'b0;
-                    done <= 1'b1;
-
-                end else begin
-
-                    busy <= 1'b1;
-
-                end
-
-            end else begin
-
-                // =================================================
-                // Continue monitoring overrun even after the normal
-                // travel state has stopped.
-                //
-                // This allows:
-                //
-                // reach target normally
-                //      ↓
-                // external mechanics keep moving
-                //      ↓
-                // travel_overrun becomes 1
-                // =================================================
-
-                if (
-                    (
-                        busy       ||
-                        done       ||
-                        overshoot  ||
-                        limit_hit
-                    ) &&
-                    !travel_overrun
-                ) begin
-
-                    if (
-                        positive_overrun_now ||
-                        negative_overrun_now
-                    ) begin
-
-                        travel_overrun <= 1'b1;
-
-                    end
-
-                end
-
-                // =================================================
-                // Active travel monitoring
-                // =================================================
-
-                if (busy) begin
-
-                    // ---------------------------------------------
-                    // Positive physical limit has highest priority.
-                    // ---------------------------------------------
-
-                    if (
-                        (latched_target_travel > 0) &&
-                        limit_pos
-                    ) begin
-
-                        busy          <= 1'b0;
-                        done          <= 1'b0;
-
-                        limit_hit     <= 1'b1;
-                        limit_pos_hit <= 1'b1;
-
-                    end
-
-                    // ---------------------------------------------
-                    // Negative physical limit.
-                    // ---------------------------------------------
-
-                    else if (
-                        (latched_target_travel < 0) &&
-                        limit_neg
-                    ) begin
-
-                        busy          <= 1'b0;
-                        done          <= 1'b0;
-
-                        limit_hit     <= 1'b1;
-                        limit_neg_hit <= 1'b1;
-
-                    end
-
-                    // ---------------------------------------------
-                    // Normal arrival inside tolerance window.
-                    // ---------------------------------------------
-
-                    else if (
-                        abs_position_error <= tolerance_ext
-                    ) begin
-
-                        busy <= 1'b0;
-                        done <= 1'b1;
-
-                    end
-
-                    // ---------------------------------------------
-                    // Target was skipped.
-                    //
-                    // This is NOT a normal completion.
-                    // ---------------------------------------------
-
-                    else if (
-                        positive_overshoot_now ||
-                        negative_overshoot_now
-                    ) begin
-
-                        busy      <= 1'b0;
-                        done      <= 1'b0;
-                        overshoot <= 1'b1;
-
-                    end
-
-                end
-
-            end
-
-        end
-
-    end
-
-endmodule

+ 0 - 79
rtl/pwm_control_demo.v

@@ -1,79 +0,0 @@
-`timescale 1ns/1ps
-
-module pwm_control_demo (
-    input  wire                    clk,
-    input  wire                    reset_n,
-
-    // Control command: -128 .. +127
-    input  wire signed [7:0]       cmd,
-
-    // Safety/control signals
-    input  wire                    enable,
-    input  wire                    fault,
-
-    // Observable internal results
-    output reg  signed [7:0]       limited_cmd,
-    output reg                     direction,
-    output reg  [6:0]              duty,
-
-    // Actual PWM waveform
-    output wire                    pwm_out
-);
-
-    // 0..99 PWM carrier counter
-    reg [6:0] pwm_counter;
-
-    // ---------------------------------------------------------
-    // 1. Saturation limiter: command limited to -90 .. +90
-    // 2. Sign -> direction
-    // 3. Absolute value -> PWM duty
-    // ---------------------------------------------------------
-    always @(*) begin
-        if (cmd > 8'sd90)
-            limited_cmd = 8'sd90;
-        else if (cmd < -8'sd90)
-            limited_cmd = -8'sd90;
-        else
-            limited_cmd = cmd;
-
-        if (limited_cmd < 0) begin
-            direction = 1'b1;          // reverse
-            duty = -limited_cmd;
-        end else begin
-            direction = 1'b0;          // forward
-            duty = limited_cmd;
-        end
-    end
-
-    // ---------------------------------------------------------
-    // PWM carrier: 0,1,2 ... 99,0,1...
-    // ---------------------------------------------------------
-    always @(posedge clk or negedge reset_n) begin
-        if (!reset_n)
-            pwm_counter <= 7'd0;
-        else if (pwm_counter == 7'd99)
-            pwm_counter <= 7'd0;
-        else
-            pwm_counter <= pwm_counter + 1'b1;
-    end
-
-    // ---------------------------------------------------------
-    // PWM output
-    //
-    // duty=25 -> 25 high clocks / 100 clocks = 25%
-    //
-    // enable=0 or fault=1 -> PWM forced OFF
-    // ---------------------------------------------------------
-    assign pwm_out =
-        reset_n &&
-        enable &&
-        !fault &&
-        (pwm_counter < duty);
-
-endmodule
-//CI rollout test
-//automatic trigger test
-// poll scm trigger test
-// argo events test
-// full automatic ci test
-// webhook delivery test

+ 0 - 940
sim/axis_travel_monitor_tb.v

@@ -1,940 +0,0 @@
-`timescale 1ns/1ps
-
-module axis_travel_monitor_tb;
-
-    reg clk;
-    reg reset_n;
-    reg start;
-
-    reg signed [31:0] current_position;
-    reg signed [31:0] target_travel;
-
-    reg [31:0] tolerance;
-
-    reg limit_pos;
-    reg limit_neg;
-
-    wire signed [31:0] start_position;
-    wire signed [31:0] target_position;
-    wire signed [31:0] travel;
-
-    wire busy;
-    wire in_position;
-    wire done;
-
-    wire limit_hit;
-    wire limit_pos_hit;
-    wire limit_neg_hit;
-
-    integer errors;
-    integer checks;
-
-    integer i;
-
-    integer random_start;
-    integer random_distance;
-    integer random_tolerance;
-    integer random_target;
-    integer random_middle;
-
-    reg [31:0] lfsr;
-
-    axis_travel_monitor dut (
-        .clk(clk),
-        .reset_n(reset_n),
-
-        .start(start),
-
-        .current_position(current_position),
-        .target_travel(target_travel),
-
-        .tolerance(tolerance),
-
-        .limit_pos(limit_pos),
-        .limit_neg(limit_neg),
-
-        .start_position(start_position),
-        .target_position(target_position),
-        .travel(travel),
-
-        .busy(busy),
-        .in_position(in_position),
-        .done(done),
-
-        .limit_hit(limit_hit),
-        .limit_pos_hit(limit_pos_hit),
-        .limit_neg_hit(limit_neg_hit)
-    );
-
-    // ------------------------------------------------------------
-    // Clock
-    // ------------------------------------------------------------
-
-    initial clk = 0;
-    always #5 clk = ~clk;
-
-    // ------------------------------------------------------------
-    // Reset
-    // ------------------------------------------------------------
-
-    task reset_dut;
-        begin
-
-            reset_n = 0;
-            start = 0;
-
-            current_position = 0;
-            target_travel = 0;
-            tolerance = 0;
-
-            limit_pos = 0;
-            limit_neg = 0;
-
-            repeat (3)
-                @(posedge clk);
-
-            #1;
-
-            reset_n = 1;
-
-            @(posedge clk);
-            #1;
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // Generate one-cycle START pulse
-    // ------------------------------------------------------------
-
-    task start_move;
-
-        input integer position;
-        input integer distance;
-        input integer tolerance_value;
-
-        begin
-
-            current_position = position;
-            target_travel = distance;
-            tolerance = tolerance_value;
-
-            limit_pos = 0;
-            limit_neg = 0;
-
-            @(negedge clk);
-
-            start = 1;
-
-            @(posedge clk);
-            #1;
-
-            start = 0;
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // Check helper
-    // ------------------------------------------------------------
-
-    task expect_value;
-
-        input integer condition;
-        input [8*80-1:0] message;
-
-        begin
-
-            checks = checks + 1;
-
-            if (!condition) begin
-
-                $display(
-                    "FAIL: %0s",
-                    message
-                );
-
-                errors = errors + 1;
-
-            end
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // MAIN
-    // ------------------------------------------------------------
-
-    initial begin
-
-        errors = 0;
-        checks = 0;
-
-        lfsr = 32'h1ACE_B00C;
-
-        reset_dut();
-
-        $display("");
-        $display("============================================================");
-        $display("       AXIS TRAVEL MONITOR AUTOMATED VERIFICATION");
-        $display("============================================================");
-
-
-        // ========================================================
-        // TEST A
-        // Positive travel
-        // ========================================================
-
-        $display("");
-        $display("[A] Positive travel");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-        expect_value(
-            start_position == 1000,
-            "start_position should be 1000"
-        );
-
-        expect_value(
-            target_position == 1500,
-            "target_position should be 1500"
-        );
-
-        expect_value(
-            busy == 1,
-            "positive move should be busy"
-        );
-
-
-        current_position = 1200;
-        #1;
-
-        expect_value(
-            travel == 200,
-            "travel should be 200"
-        );
-
-        expect_value(
-            in_position == 0,
-            "1200 must not be in target window"
-        );
-
-
-        current_position = 1494;
-        #1;
-
-        expect_value(
-            in_position == 0,
-            "1494 must be outside tolerance"
-        );
-
-
-        current_position = 1495;
-        #1;
-
-        expect_value(
-            in_position == 1,
-            "1495 must be inside tolerance"
-        );
-
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            done == 1,
-            "positive travel should complete"
-        );
-
-        expect_value(
-            busy == 0,
-            "busy should clear after completion"
-        );
-
-        $display("PASS [A] Positive travel");
-
-
-        // ========================================================
-        // TEST B
-        // Negative travel
-        // ========================================================
-
-        $display("");
-        $display("[B] Negative travel");
-
-        start_move(
-            3000,
-            -500,
-            5
-        );
-
-        expect_value(
-            start_position == 3000,
-            "negative start_position"
-        );
-
-        expect_value(
-            target_position == 2500,
-            "negative target_position"
-        );
-
-
-        current_position = 2506;
-        #1;
-
-        expect_value(
-            in_position == 0,
-            "2506 must be outside tolerance"
-        );
-
-
-        current_position = 2505;
-        #1;
-
-        expect_value(
-            in_position == 1,
-            "2505 must be inside tolerance"
-        );
-
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            done == 1,
-            "negative travel should complete"
-        );
-
-        expect_value(
-            travel == -495,
-            "negative travel calculation"
-        );
-
-        $display("PASS [B] Negative travel");
-
-
-        // ========================================================
-        // TEST C
-        // Exact tolerance boundaries
-        // ========================================================
-
-        $display("");
-        $display("[C] Position tolerance window");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-
-        current_position = 1494;
-        #1;
-
-        expect_value(
-            in_position == 0,
-            "target-6 must fail"
-        );
-
-
-        current_position = 1495;
-        #1;
-
-        expect_value(
-            in_position == 1,
-            "target-5 must pass"
-        );
-
-
-        current_position = 1505;
-        #1;
-
-        expect_value(
-            in_position == 1,
-            "target+5 must pass"
-        );
-
-
-        current_position = 1506;
-        #1;
-
-        expect_value(
-            in_position == 0,
-            "target+6 must fail"
-        );
-
-        $display("PASS [C] Tolerance window");
-
-
-        // ========================================================
-        // TEST D
-        // Positive limit during positive travel
-        // ========================================================
-
-        $display("");
-        $display("[D] Positive limit");
-
-        start_move(
-            1000,
-            2000,
-            5
-        );
-
-
-        current_position = 1300;
-
-        limit_pos = 1;
-
-        @(posedge clk);
-        #1;
-
-
-        expect_value(
-            busy == 0,
-            "positive limit must terminate travel"
-        );
-
-        expect_value(
-            done == 0,
-            "limit termination must not be normal DONE"
-        );
-
-        expect_value(
-            limit_hit == 1,
-            "limit_hit must latch"
-        );
-
-        expect_value(
-            limit_pos_hit == 1,
-            "positive limit flag must latch"
-        );
-
-        expect_value(
-            limit_neg_hit == 0,
-            "negative limit flag must remain clear"
-        );
-
-        limit_pos = 0;
-
-        $display("PASS [D] Positive limit");
-
-
-        // ========================================================
-        // TEST E
-        // Negative limit during negative travel
-        // ========================================================
-
-        $display("");
-        $display("[E] Negative limit");
-
-        start_move(
-            3000,
-            -2000,
-            5
-        );
-
-
-        current_position = 2700;
-
-        limit_neg = 1;
-
-        @(posedge clk);
-        #1;
-
-
-        expect_value(
-            busy == 0,
-            "negative limit must terminate travel"
-        );
-
-        expect_value(
-            done == 0,
-            "negative limit must not generate DONE"
-        );
-
-        expect_value(
-            limit_hit == 1,
-            "limit_hit must latch on negative limit"
-        );
-
-        expect_value(
-            limit_neg_hit == 1,
-            "negative limit flag must latch"
-        );
-
-        limit_neg = 0;
-
-        $display("PASS [E] Negative limit");
-
-
-        // ========================================================
-        // TEST F
-        // Wrong-direction limit must not terminate movement
-        // ========================================================
-
-        $display("");
-        $display("[F] Opposite limit immunity");
-
-        start_move(
-            1000,
-            1000,
-            5
-        );
-
-
-        limit_neg = 1;
-
-        @(posedge clk);
-        #1;
-
-
-        expect_value(
-            busy == 1,
-            "negative limit should not stop positive travel"
-        );
-
-        expect_value(
-            limit_hit == 0,
-            "wrong-direction limit must not latch"
-        );
-
-        limit_neg = 0;
-
-        $display("PASS [F] Opposite limit immunity");
-
-
-        // ========================================================
-        // TEST G
-        // Reset during travel
-        // ========================================================
-
-        $display("");
-        $display("[G] Reset during active travel");
-
-        start_move(
-            5000,
-            1000,
-            5
-        );
-
-        current_position = 5300;
-
-
-        reset_n = 0;
-
-        #1;
-
-
-        expect_value(
-            busy == 0,
-            "reset must clear busy"
-        );
-
-        expect_value(
-            done == 0,
-            "reset must clear done"
-        );
-
-        expect_value(
-            limit_hit == 0,
-            "reset must clear limit_hit"
-        );
-
-
-        reset_n = 1;
-
-        @(posedge clk);
-        #1;
-
-        $display("PASS [G] Reset");
-
-
-        // ========================================================
-        // TEST H
-        // New start while previous travel is still active
-        // ========================================================
-
-        $display("");
-        $display("[H] Restart / new segment");
-
-        start_move(
-            1000,
-            1000,
-            5
-        );
-
-
-        current_position = 1300;
-
-
-        // New travel begins from 1300.
-        start_move(
-            1300,
-            200,
-            2
-        );
-
-
-        expect_value(
-            start_position == 1300,
-            "restart must capture new start position"
-        );
-
-        expect_value(
-            target_position == 1500,
-            "restart target should be 1500"
-        );
-
-        expect_value(
-            travel == 0,
-            "new segment travel must restart from zero"
-        );
-
-        expect_value(
-            busy == 1,
-            "new segment should be busy"
-        );
-
-
-        current_position = 1500;
-
-        @(posedge clk);
-        #1;
-
-
-        expect_value(
-            done == 1,
-            "restarted travel should complete"
-        );
-
-        $display("PASS [H] Restart");
-
-
-        // ========================================================
-        // TEST I
-        // Zero travel
-        // ========================================================
-
-        $display("");
-        $display("[I] Zero-distance travel");
-
-        start_move(
-            12345,
-            0,
-            0
-        );
-
-
-        expect_value(
-            start_position == 12345,
-            "zero travel start position"
-        );
-
-        expect_value(
-            target_position == 12345,
-            "zero travel target position"
-        );
-
-        expect_value(
-            busy == 0,
-            "zero travel must not remain busy"
-        );
-
-        expect_value(
-            done == 1,
-            "zero travel should complete immediately"
-        );
-
-        expect_value(
-            in_position == 1,
-            "zero travel should be in position"
-        );
-
-        $display("PASS [I] Zero-distance travel");
-
-
-        // ========================================================
-        // TEST J
-        // Negative absolute positions
-        // ========================================================
-
-        $display("");
-        $display("[J] Negative absolute positions");
-
-        start_move(
-            -5000,
-            750,
-            3
-        );
-
-
-        expect_value(
-            target_position == -4250,
-            "negative-coordinate target"
-        );
-
-
-        current_position = -4250;
-
-        @(posedge clk);
-        #1;
-
-
-        expect_value(
-            done == 1,
-            "negative-coordinate move should complete"
-        );
-
-        expect_value(
-            travel == 750,
-            "travel across negative coordinates"
-        );
-
-        $display("PASS [J] Negative absolute positions");
-
-
-        // ========================================================
-        // TEST K
-        // 500 deterministic pseudo-random travel segments
-        // ========================================================
-
-        $display("");
-        $display("[K] 500 randomized travel segments");
-
-
-        for (i = 0; i < 500; i = i + 1) begin
-
-            // LFSR
-            lfsr = {
-                lfsr[30:0],
-                lfsr[31] ^
-                lfsr[21] ^
-                lfsr[1] ^
-                lfsr[0]
-            };
-
-
-            random_start =
-                $signed(lfsr[15:0]);
-
-
-            // Make distance between 50 and 1049.
-            random_distance =
-                50 + (lfsr[25:16] % 1000);
-
-
-            // Random direction.
-            if (lfsr[26])
-                random_distance = -random_distance;
-
-
-            random_tolerance =
-                lfsr[30:27] % 6;
-
-
-            random_target =
-                random_start +
-                random_distance;
-
-
-            random_middle =
-                random_start +
-                random_distance / 2;
-
-
-            start_move(
-                random_start,
-                random_distance,
-                random_tolerance
-            );
-
-
-            checks = checks + 3;
-
-
-            if (start_position != random_start) begin
-
-                $display(
-                    "FAIL RANDOM START: case=%0d expected=%0d actual=%0d",
-                    i,
-                    random_start,
-                    start_position
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (target_position != random_target) begin
-
-                $display(
-                    "FAIL RANDOM TARGET: case=%0d expected=%0d actual=%0d",
-                    i,
-                    random_target,
-                    target_position
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (!busy) begin
-
-                $display(
-                    "FAIL RANDOM BUSY: case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            // Halfway should still be active.
-            current_position = random_middle;
-
-            @(posedge clk);
-            #1;
-
-
-            checks = checks + 1;
-
-
-            if (!busy) begin
-
-                $display(
-                    "FAIL RANDOM EARLY DONE: case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            // Move exactly to target.
-            current_position = random_target;
-
-            @(posedge clk);
-            #1;
-
-
-            checks = checks + 3;
-
-
-            if (!done) begin
-
-                $display(
-                    "FAIL RANDOM DONE: case=%0d start=%0d distance=%0d target=%0d current=%0d",
-                    i,
-                    random_start,
-                    random_distance,
-                    random_target,
-                    current_position
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (busy) begin
-
-                $display(
-                    "FAIL RANDOM BUSY CLEAR: case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (!in_position) begin
-
-                $display(
-                    "FAIL RANDOM IN_POSITION: case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if ((i % 100) == 0) begin
-
-                $display(
-                    "Random progress: %0d / 500",
-                    i
-                );
-
-            end
-
-        end
-
-
-        $display("PASS [K] 500 randomized travel segments");
-
-
-        // ========================================================
-        // FINAL RESULT
-        // ========================================================
-
-        $display("");
-        $display("============================================================");
-        $display("TOTAL CHECKS : %0d", checks);
-        $display("TOTAL ERRORS : %0d", errors);
-        $display("============================================================");
-
-
-        if (errors == 0) begin
-
-            $display("");
-            $display("ALL AXIS TRAVEL TESTS PASSED");
-
-            $display("");
-            $display("Verified:");
-            $display("  - positive travel");
-            $display("  - negative travel");
-            $display("  - start-position capture");
-            $display("  - relative travel calculation");
-            $display("  - target-position calculation");
-            $display("  - tolerance / in-position window");
-            $display("  - positive limit");
-            $display("  - negative limit");
-            $display("  - opposite-limit handling");
-            $display("  - reset");
-            $display("  - restart during travel");
-            $display("  - zero-distance travel");
-            $display("  - negative coordinates");
-            $display("  - 500 randomized travel segments");
-
-            $display("");
-            $display("============================================================");
-
-            $finish;
-
-        end else begin
-
-            $display("");
-            $display(
-                "AXIS TRAVEL TEST FAILED: %0d error(s)",
-                errors
-            );
-
-            $display("============================================================");
-
-            $fatal(1);
-
-        end
-
-    end
-
-endmodule

+ 0 - 815
sim/axis_travel_overrun_tb.v

@@ -1,815 +0,0 @@
-`timescale 1ns/1ps
-
-module axis_travel_overrun_tb;
-
-    reg clk;
-    reg reset_n;
-    reg start;
-
-    reg signed [31:0] current_position;
-    reg signed [31:0] target_travel;
-
-    reg [31:0] tolerance;
-
-    reg limit_pos;
-    reg limit_neg;
-
-    wire signed [31:0] start_position;
-    wire signed [31:0] target_position;
-    wire signed [31:0] travel;
-
-    wire busy;
-    wire in_position;
-    wire done;
-
-    wire limit_hit;
-    wire limit_pos_hit;
-    wire limit_neg_hit;
-
-    wire overshoot;
-    wire travel_overrun;
-
-    integer errors;
-    integer checks;
-
-    integer i;
-
-    integer random_start;
-    integer random_distance;
-    integer random_target;
-    integer random_tolerance;
-    integer random_excess;
-
-    reg [31:0] lfsr;
-
-    axis_travel_monitor #(
-        .OVERRUN_LIMIT(20)
-    ) dut (
-        .clk(clk),
-        .reset_n(reset_n),
-
-        .start(start),
-
-        .current_position(current_position),
-        .target_travel(target_travel),
-
-        .tolerance(tolerance),
-
-        .limit_pos(limit_pos),
-        .limit_neg(limit_neg),
-
-        .start_position(start_position),
-        .target_position(target_position),
-        .travel(travel),
-
-        .busy(busy),
-        .in_position(in_position),
-        .done(done),
-
-        .limit_hit(limit_hit),
-        .limit_pos_hit(limit_pos_hit),
-        .limit_neg_hit(limit_neg_hit),
-
-        .overshoot(overshoot),
-        .travel_overrun(travel_overrun)
-    );
-
-    // ------------------------------------------------------------
-    // Clock
-    // ------------------------------------------------------------
-
-    initial clk = 0;
-    always #5 clk = ~clk;
-
-    // ------------------------------------------------------------
-    // Reset
-    // ------------------------------------------------------------
-
-    task reset_dut;
-        begin
-
-            reset_n = 0;
-
-            start = 0;
-
-            current_position = 0;
-            target_travel = 0;
-
-            tolerance = 0;
-
-            limit_pos = 0;
-            limit_neg = 0;
-
-            repeat (3)
-                @(posedge clk);
-
-            #1;
-
-            reset_n = 1;
-
-            @(posedge clk);
-            #1;
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // Start one travel
-    // ------------------------------------------------------------
-
-    task start_move;
-
-        input integer position;
-        input integer distance;
-        input integer tolerance_value;
-
-        begin
-
-            current_position = position;
-            target_travel = distance;
-            tolerance = tolerance_value;
-
-            limit_pos = 0;
-            limit_neg = 0;
-
-            @(negedge clk);
-
-            start = 1;
-
-            @(posedge clk);
-            #1;
-
-            start = 0;
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // Generic expectation
-    // ------------------------------------------------------------
-
-    task expect_value;
-
-        input integer condition;
-        input [8*100-1:0] message;
-
-        begin
-
-            checks = checks + 1;
-
-            if (!condition) begin
-
-                $display(
-                    "FAIL: %0s",
-                    message
-                );
-
-                errors = errors + 1;
-
-            end
-
-        end
-    endtask
-
-    // ------------------------------------------------------------
-    // MAIN
-    // ------------------------------------------------------------
-
-    initial begin
-
-        errors = 0;
-        checks = 0;
-
-        lfsr = 32'hA55A_1234;
-
-        reset_dut();
-
-        $display("");
-        $display("============================================================");
-        $display("       AXIS OVERSHOOT / OVERRUN VERIFICATION");
-        $display("============================================================");
-
-
-        // ========================================================
-        // TEST A
-        //
-        // Positive overshoot:
-        //
-        // target    = 1500
-        // tolerance = 5
-        //
-        // 1490 -> 1510
-        //
-        // skips the valid 1495..1505 target window.
-        // ========================================================
-
-        $display("");
-        $display("[A] Positive target overshoot");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-        current_position = 1490;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            busy == 1,
-            "1490 should still be active"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "1490 must not be overshoot"
-        );
-
-
-        current_position = 1510;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            busy == 0,
-            "positive overshoot must terminate travel"
-        );
-
-        expect_value(
-            done == 0,
-            "overshoot must not generate normal DONE"
-        );
-
-        expect_value(
-            overshoot == 1,
-            "positive overshoot flag must latch"
-        );
-
-        expect_value(
-            in_position == 0,
-            "1510 must not be in position"
-        );
-
-        expect_value(
-            travel_overrun == 0,
-            "10-count overshoot must not trigger 20-count overrun"
-        );
-
-        $display("PASS [A] Positive overshoot detected");
-
-
-        // ========================================================
-        // TEST B
-        //
-        // Negative overshoot.
-        //
-        // target=2500
-        //
-        // 2510 -> 2490
-        // ========================================================
-
-        $display("");
-        $display("[B] Negative target overshoot");
-
-        start_move(
-            3000,
-            -500,
-            5
-        );
-
-        current_position = 2510;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            busy == 1,
-            "2510 should still be active"
-        );
-
-
-        current_position = 2490;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            busy == 0,
-            "negative overshoot must terminate travel"
-        );
-
-        expect_value(
-            done == 0,
-            "negative overshoot must not generate DONE"
-        );
-
-        expect_value(
-            overshoot == 1,
-            "negative overshoot flag must latch"
-        );
-
-        expect_value(
-            travel_overrun == 0,
-            "10-count negative overshoot is below overrun threshold"
-        );
-
-        $display("PASS [B] Negative overshoot detected");
-
-
-        // ========================================================
-        // TEST C
-        //
-        // Serious positive overrun.
-        //
-        // target = 1500
-        // current = 1525
-        //
-        // exceeds target by 25.
-        // ========================================================
-
-        $display("");
-        $display("[C] Positive travel overrun");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-        current_position = 1525;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            overshoot == 1,
-            "1525 must trigger overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 1,
-            "1525 must trigger 20-count travel overrun"
-        );
-
-        expect_value(
-            done == 0,
-            "serious overrun must not be normal DONE"
-        );
-
-        $display("PASS [C] Positive travel overrun detected");
-
-
-        // ========================================================
-        // TEST D
-        //
-        // Serious negative overrun.
-        // ========================================================
-
-        $display("");
-        $display("[D] Negative travel overrun");
-
-        start_move(
-            3000,
-            -500,
-            5
-        );
-
-        current_position = 2475;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            overshoot == 1,
-            "2475 must trigger negative overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 1,
-            "2475 must trigger negative travel overrun"
-        );
-
-        expect_value(
-            done == 0,
-            "negative overrun must not be normal DONE"
-        );
-
-        $display("PASS [D] Negative travel overrun detected");
-
-
-        // ========================================================
-        // TEST E
-        //
-        // Reach target normally first.
-        //
-        // Then mechanics continue moving beyond target.
-        //
-        // FPGA must still detect travel_overrun.
-        // ========================================================
-
-        $display("");
-        $display("[E] Post-completion mechanical drift");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-        current_position = 1500;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            done == 1,
-            "1500 must complete normally"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "normal arrival must not overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 0,
-            "normal arrival must not overrun"
-        );
-
-
-        // Simulate mechanics continuing after command completion.
-        current_position = 1525;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            done == 1,
-            "original normal completion remains latched"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "post-completion drift is not skipped-target overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 1,
-            "continued movement must trigger overrun"
-        );
-
-        $display("PASS [E] Post-completion overrun detected");
-
-
-        // ========================================================
-        // TEST F
-        //
-        // New START must clear old error flags.
-        // ========================================================
-
-        $display("");
-        $display("[F] New segment clears previous alarms");
-
-        start_move(
-            2000,
-            -300,
-            5
-        );
-
-        expect_value(
-            busy == 1,
-            "new segment must become active"
-        );
-
-        expect_value(
-            done == 0,
-            "new segment clears old DONE"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "new segment clears overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 0,
-            "new segment clears travel_overrun"
-        );
-
-        expect_value(
-            limit_hit == 0,
-            "new segment clears limit_hit"
-        );
-
-        $display("PASS [F] Alarm reset on new START");
-
-
-        // ========================================================
-        // TEST G
-        //
-        // Limit has priority over target overshoot.
-        //
-        // Position is already too far,
-        // but physical positive limit is active simultaneously.
-        //
-        // Result:
-        //
-        // limit_hit = 1
-        // overshoot = 0
-        // ========================================================
-
-        $display("");
-        $display("[G] Physical limit priority");
-
-        start_move(
-            1000,
-            500,
-            5
-        );
-
-        current_position = 1525;
-        limit_pos = 1;
-
-        @(posedge clk);
-        #1;
-
-        expect_value(
-            limit_hit == 1,
-            "physical limit must latch"
-        );
-
-        expect_value(
-            limit_pos_hit == 1,
-            "positive limit flag must latch"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "limit must take priority over overshoot state"
-        );
-
-        expect_value(
-            done == 0,
-            "limit event is not normal completion"
-        );
-
-        limit_pos = 0;
-
-        $display("PASS [G] Limit priority");
-
-
-        // ========================================================
-        // TEST H
-        //
-        // 300 pseudo-random target-crossing tests.
-        //
-        // Every case deliberately jumps past target.
-        // ========================================================
-
-        $display("");
-        $display("[H] 300 randomized target-crossing tests");
-
-        for (i = 0; i < 300; i = i + 1) begin
-
-            // LFSR
-            lfsr = {
-                lfsr[30:0],
-                lfsr[31] ^
-                lfsr[21] ^
-                lfsr[1] ^
-                lfsr[0]
-            };
-
-
-            random_start =
-                $signed(lfsr[15:0]);
-
-
-            random_distance =
-                100 + (lfsr[25:16] % 900);
-
-
-            if (lfsr[26])
-                random_distance = -random_distance;
-
-
-            random_tolerance =
-                lfsr[29:27] % 6;
-
-
-            random_target =
-                random_start +
-                random_distance;
-
-
-            // Always jump beyond tolerance.
-            random_excess =
-                random_tolerance +
-                1 +
-                (lfsr[15:8] % 30);
-
-
-            start_move(
-                random_start,
-                random_distance,
-                random_tolerance
-            );
-
-
-            if (random_distance > 0)
-                current_position =
-                    random_target + random_excess;
-            else
-                current_position =
-                    random_target - random_excess;
-
-
-            @(posedge clk);
-            #1;
-
-
-            checks = checks + 4;
-
-
-            if (!overshoot) begin
-
-                $display(
-                    "FAIL RANDOM OVERSHOOT case=%0d start=%0d distance=%0d target=%0d current=%0d tolerance=%0d",
-                    i,
-                    random_start,
-                    random_distance,
-                    random_target,
-                    current_position,
-                    random_tolerance
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (busy) begin
-
-                $display(
-                    "FAIL RANDOM BUSY case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (done) begin
-
-                $display(
-                    "FAIL RANDOM DONE case=%0d",
-                    i
-                );
-
-                errors = errors + 1;
-
-            end
-
-
-            if (random_excess >= 20) begin
-
-                if (!travel_overrun) begin
-
-                    $display(
-                        "FAIL RANDOM OVERRUN case=%0d excess=%0d",
-                        i,
-                        random_excess
-                    );
-
-                    errors = errors + 1;
-
-                end
-
-            end else begin
-
-                if (travel_overrun) begin
-
-                    $display(
-                        "FAIL RANDOM FALSE OVERRUN case=%0d excess=%0d",
-                        i,
-                        random_excess
-                    );
-
-                    errors = errors + 1;
-
-                end
-
-            end
-
-
-            if ((i % 50) == 0) begin
-
-                $display(
-                    "Random progress: %0d / 300",
-                    i
-                );
-
-            end
-
-        end
-
-        $display("PASS [H] 300 randomized target-crossing tests");
-
-
-        // ========================================================
-        // TEST I
-        //
-        // RESET clears all alarms.
-        // ========================================================
-
-        $display("");
-        $display("[I] Reset clears error state");
-
-        reset_n = 0;
-
-        #1;
-
-        expect_value(
-            busy == 0,
-            "reset clears busy"
-        );
-
-        expect_value(
-            done == 0,
-            "reset clears done"
-        );
-
-        expect_value(
-            overshoot == 0,
-            "reset clears overshoot"
-        );
-
-        expect_value(
-            travel_overrun == 0,
-            "reset clears travel_overrun"
-        );
-
-        expect_value(
-            limit_hit == 0,
-            "reset clears limit_hit"
-        );
-
-        reset_n = 1;
-
-        $display("PASS [I] Reset clears state");
-
-
-        // ========================================================
-        // FINAL RESULT
-        // ========================================================
-
-        $display("");
-        $display("============================================================");
-        $display("TOTAL CHECKS : %0d", checks);
-        $display("TOTAL ERRORS : %0d", errors);
-        $display("============================================================");
-
-
-        if (errors == 0) begin
-
-            $display("");
-            $display("ALL AXIS OVERSHOOT TESTS PASSED");
-
-            $display("");
-            $display("Verified:");
-            $display("  - positive overshoot");
-            $display("  - negative overshoot");
-            $display("  - positive travel overrun");
-            $display("  - negative travel overrun");
-            $display("  - post-completion drift");
-            $display("  - alarm clearing on new START");
-            $display("  - physical-limit priority");
-            $display("  - 300 randomized target crossings");
-            $display("  - reset alarm clearing");
-
-            $display("");
-            $display("============================================================");
-
-            $finish;
-
-        end else begin
-
-            $display("");
-            $display(
-                "AXIS OVERSHOOT TEST FAILED: %0d error(s)",
-                errors
-            );
-
-            $display("============================================================");
-
-            $fatal(1);
-
-        end
-
-    end
-
-endmodule

+ 0 - 168
sim/pwm_control_demo_tb.v

@@ -1,168 +0,0 @@
-`timescale 1ns/1ps
-
-module pwm_control_demo_tb;
-
-    reg clk;
-    reg reset_n;
-    reg signed [7:0] cmd;
-    reg enable;
-    reg fault;
-
-    wire signed [7:0] limited_cmd;
-    wire direction;
-    wire [6:0] duty;
-    wire pwm_out;
-
-    integer errors;
-    integer high_count;
-    integer i;
-
-    pwm_control_demo dut (
-        .clk(clk),
-        .reset_n(reset_n),
-        .cmd(cmd),
-        .enable(enable),
-        .fault(fault),
-        .limited_cmd(limited_cmd),
-        .direction(direction),
-        .duty(duty),
-        .pwm_out(pwm_out)
-    );
-
-    // 100 MHz simulation clock.
-    // Frequency itself is not important for this demo;
-    // PWM duty ratio is what we verify.
-    initial clk = 0;
-    always #5 clk = ~clk;
-
-    task check_control;
-        input signed [7:0] test_cmd;
-        input signed [7:0] expected_limit;
-        input expected_direction;
-        input [6:0] expected_duty;
-        begin
-            cmd = test_cmd;
-            #1;
-
-            if (limited_cmd !== expected_limit) begin
-                $display("FAIL limiter: cmd=%0d expected=%0d actual=%0d",
-                         test_cmd, expected_limit, limited_cmd);
-                errors = errors + 1;
-            end else begin
-                $display("PASS limiter: cmd=%0d -> %0d",
-                         test_cmd, limited_cmd);
-            end
-
-            if (direction !== expected_direction) begin
-                $display("FAIL direction: cmd=%0d expected=%0d actual=%0d",
-                         test_cmd, expected_direction, direction);
-                errors = errors + 1;
-            end else begin
-                $display("PASS direction: cmd=%0d direction=%0d",
-                         test_cmd, direction);
-            end
-
-            if (duty !== expected_duty) begin
-                $display("FAIL duty: cmd=%0d expected=%0d actual=%0d",
-                         test_cmd, expected_duty, duty);
-                errors = errors + 1;
-            end else begin
-                $display("PASS duty: cmd=%0d duty=%0d%%",
-                         test_cmd, duty);
-            end
-        end
-    endtask
-
-    task check_pwm;
-        input [6:0] expected_percent;
-        begin
-            high_count = 0;
-
-            // Measure exactly one complete 100-clock PWM period.
-            for (i = 0; i < 100; i = i + 1) begin
-                @(negedge clk);
-                if (pwm_out)
-                    high_count = high_count + 1;
-            end
-
-            if (high_count !== expected_percent) begin
-                $display("FAIL PWM: expected=%0d%% measured=%0d%%",
-                         expected_percent, high_count);
-                errors = errors + 1;
-            end else begin
-                $display("PASS PWM: expected=%0d%% measured=%0d%%",
-                         expected_percent, high_count);
-            end
-        end
-    endtask
-
-    initial begin
-        errors = 0;
-        reset_n = 0;
-        cmd = 0;
-        enable = 0;
-        fault = 0;
-
-        repeat (3) @(posedge clk);
-        reset_n = 1;
-
-        $display("");
-        $display("========== PWM CONTROL TEST ==========");
-
-        // Normal forward command
-        enable = 1;
-        fault = 0;
-        check_control(25, 25, 0, 25);
-        check_pwm(25);
-
-        // Another normal command
-        check_control(50, 50, 0, 50);
-        check_pwm(50);
-
-        // Upper limiter
-        check_control(95, 90, 0, 90);
-        check_pwm(90);
-
-        // Reverse command
-        check_control(-50, -50, 1, 50);
-        check_pwm(50);
-
-        // Lower limiter
-        check_control(-120, -90, 1, 90);
-        check_pwm(90);
-
-        // Zero command
-        check_control(0, 0, 0, 0);
-        check_pwm(0);
-
-        // Disable interlock
-        cmd = 50;
-        enable = 0;
-        fault = 0;
-        #1;
-        check_pwm(0);
-        $display("PASS enable=0 forces PWM OFF");
-
-        // Fault interlock
-        enable = 1;
-        fault = 1;
-        #1;
-        check_pwm(0);
-        $display("PASS fault=1 forces PWM OFF");
-
-        $display("");
-
-        if (errors == 0) begin
-            $display("======================================");
-            $display("ALL TESTS PASSED");
-            $display("======================================");
-            $finish;
-        end else begin
-            $display("======================================");
-            $display("TEST FAILED: %0d error(s)", errors);
-            $display("======================================");
-            $fatal(1);
-        end
-    end
-
-endmodule

Разница между файлами не показана из-за своего большого размера
+ 0 - 1233
sim/pwm_control_motor_scenario_tb.v