| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- `timescale 1ns/1ps
- module axis_travel_monitor (
- input wire clk,
- input wire reset_n,
- // Start a new travel segment.
- // On start, current_position becomes the new start_position.
- input wire start,
- // Current position, for example encoder pulse count.
- input wire signed [31:0] current_position,
- // Relative travel command.
- // +500 = move positive by 500
- // -500 = move negative by 500
- input wire signed [31:0] target_travel,
- // Allowed target-position error.
- input wire [31:0] tolerance,
- // Physical limit inputs.
- input wire limit_pos,
- input wire limit_neg,
- // Latched position where this travel started.
- 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 window.
- output wire in_position,
- // Latched completion flag.
- // Cleared by next start or reset.
- output reg done,
- // Latched limit status.
- output reg limit_hit,
- output reg limit_pos_hit,
- output reg limit_neg_hit
- );
- // Keep the direction of the current travel command.
- reg signed [31:0] latched_target_travel;
- // ------------------------------------------------------------
- // Actual travelled distance
- // ------------------------------------------------------------
- assign travel =
- current_position - start_position;
- // ------------------------------------------------------------
- // Position error
- //
- // Use 33 bits so subtraction itself does not overflow when
- // comparing two signed 32-bit positions.
- // ------------------------------------------------------------
- wire signed [32:0] current_ext;
- wire signed [32:0] target_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 position_error =
- current_ext - target_ext;
- assign abs_position_error =
- position_error[32]
- ? -position_error
- : position_error;
- // ------------------------------------------------------------
- // In-position window
- //
- // Example:
- //
- // target = 1500
- // tolerance = 5
- //
- // 1495 ... 1505 => in_position = 1
- // ------------------------------------------------------------
- assign in_position =
- (busy || done) &&
- (abs_position_error <= {1'b0, tolerance});
- // ------------------------------------------------------------
- // Main travel 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;
- end else begin
- // ----------------------------------------------------
- // New travel command
- //
- // A new start always creates a new measurement 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;
- // Zero-distance request is already complete.
- if (target_travel == 0) begin
- busy <= 1'b0;
- done <= 1'b1;
- end else begin
- busy <= 1'b1;
- end
- end
- // ----------------------------------------------------
- // Monitor active travel
- // ----------------------------------------------------
- else if (busy) begin
- // Positive motion:
- // positive limit is relevant.
- 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 motion:
- // negative limit is relevant.
- 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
- // Reached requested position.
- else if (
- abs_position_error <=
- {1'b0, tolerance}
- ) begin
- busy <= 1'b0;
- done <= 1'b1;
- end
- end
- end
- end
- endmodule
|