1. 直线插补基础模块
任务目标
设计并实现一个用于单轴直线插补的FPGA基础模块。该模块接收目标位置与运动方向,输出位置计数与方向控制信号,用于验证直线插补中最基本的“位置-方向”联动逻辑。本案例聚焦于插补运算的底层支撑——位置累加与方向判定,不涉及多轴协同或速度规划。
模块功能定义
模块输入:clk(系统时钟)、rst_n(异步复位,低有效)、target_pos[15:0](目标位置,无符号数)、go(启动脉冲,高电平有效一个周期)。
模块输出:current_pos[15:0](当前位置计数)、dir(运动方向,1为正向/远离原点,0为负向/朝向原点)、done(到位标志,高电平表示已到达目标位置)。
工作逻辑:当go有效时,模块锁存目标位置并清零内部运行标志;每个时钟周期比较当前计数值与目标值,若未到达则按方向步进(递增或递减)当前位置;当当前位置等于目标位置时,done置高一个周期并停止运动。
Verilog核心实现
<code>module line_interp_base #(
parameter DATA_WIDTH = 16
)(
input wire clk,
input wire rst_n,
input wire [DATA_WIDTH-1:0] target_pos,
input wire go,
output reg [DATA_WIDTH-1:0] current_pos,
output reg dir,
output reg done
);
reg [DATA_WIDTH-1:0] target_reg;
reg running;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
current_pos <= {DATA_WIDTH{1'b0}};
target_reg <= {DATA_WIDTH{1'b0}};
dir <= 1'b1;
done <= 1'b0;
running <= 1'b0;
end
else begin
// 默认输出
done <= 1'b0;
if (go) begin
target_reg <= target_pos;
// 方向判定:目标大于当前则正向,否则负向
dir <= (target_pos > current_pos) ? 1'b1 : 1'b0;
running <= (target_pos != current_pos) ? 1'b1 : 1'b0;
end
else if (running) begin
if (current_pos == target_reg) begin
running <= 1'b0;
done <= 1'b1;
end
else if (dir) begin
current_pos <= current_pos + 1'b1;
end
else begin
current_pos <= current_pos - 1'b1;
end
end
end
end
endmodule
仿真验证方法
使用Verilog testbench验证模块行为。测试流程:
- 复位后确认
current_pos=0、done=0。 - 设置
target_pos=100,拉高go一个周期,观察dir应为1,随后每个时钟周期current_pos递增1,直到等于100时done输出一个周期高电平。 - 再次设置
target_pos=50(小于当前值100),触发go,确认dir=0,current_pos递减至50后done置位。
通过条件:仿真波形中current_pos严格按单步加减到达目标值,dir方向正确,done在到达时刻恰好拉高一个时钟周期,且到达后位置保持不变。
关键点说明
- 方向判定在
go有效瞬间完成,基于当前计数值与目标值的比较结果,避免运行中方向抖动。 - 当
target_pos等于当前值时,go触发后running不置位,done也不会拉高——这是边界情况,如需“零行程完成”指示,可在go分支中增加done输出逻辑。 - 本模块为纯组合步进逻辑,未做加减速规划,实际插补系统中该模块作为位置环基础,由上层速度规划器控制
go信号的触发间隔。