使用FPGA控制4个电机
Controlling 4 motors using FPGA
我正在尝试使用 FPGA 控制 4 个电机。 (Verilog 高密度语言)
我使用 always 块和自定义模块编写了一个代码(它控制一个伺服电机,它的输入 values-L_CTRL 和 R_CTRL 确定伺服电机是向左还是向右旋转一步)
这是自定义模块代码:
module Servo(CLK, RESETN, L_CTRL, R_CTRL, SERVO);
input CLK;
input RESETN, L_CTRL, R_CTRL;
output SERVO;
integer REG, CNT;
reg L, R;
reg SERVO;
always @(posedge RESETN or posedge CLK)
begin
if (RESETN) CNT = 0;
else
if (CNT >= 199) CNT = 0;
else CNT = CNT + 1;
end
always @(posedge RESETN or posedge CLK)
begin
if (RESETN)
REG = 15;
else
begin
L <= L_CTRL; R <= R_CTRL;
if (L == 0 & L_CTRL & REG > 7)
REG = REG - 1;
else if (R == 0 & R_CTRL & REG < 23)
REG = REG + 1;
end
end
always @(CNT or REG)
begin
if (CNT < REG)
SERVO = 1;
else
SERVO = 0;
end
endmodule
我编写了控制 4 个电机的代码:
module Servo_Motor(direction,CLK,RESETN,SERVO);
input [1:0]direction;
input CLK, RESETN;
reg L_CTRL, R_CTRL;
reg [3:0] SERVO;
output [3:0] SERVO;
//servo0, servo1->x_axis
//servo2, servo3->y_axis
always @(posedge RESETN or posedge CLK)
begin
if(direction==2'b01)//east
begin
L_CTRL<=0; R_CTRL<=1;
Servo S0(CLK, RESETN, L_CTRL, R_CTRL, SERVO[0], enable_0);
Servo S1(CLK, RESETN, L_CTRL, R_CTRL, SERVO[1], enable_1);
SERVO[2]<=0;
SERVO[3]<=0;
end
else if(direction==2'b11)//SOUTH
begin
L_CTRL<=1; R_CTRL<=0;
Servo S2(CLK, RESETN, L_CTRL, R_CTRL, SERVO[2], enable_2);
Servo S3(CLK, RESETN, L_CTRL, R_CTRL, SERVO[3], enable_3);
SERVO[0]<=0;
SERVO[1]<=0;
end
else if(direction==2'b10)//WEST
begin
L_CTRL<=1; R_CTRL<=0;
Servo S0(CLK, RESETN, L_CTRL, R_CTRL, SERVO[0], enable_0);
Servo S1(CLK, RESETN, L_CTRL, R_CTRL, SERVO[1], enable_1);
SERVO[2]<=0;
SERVO[3]<=0;
end
else if(direction==2'b00)//NORTH
begin
L_CTRL<=0; R_CTRL<=1;
Servo S2(CLK, RESETN, L_CTRL, R_CTRL, SERVO[2], enable_2);
Servo S3(CLK, RESETN, L_CTRL, R_CTRL, SERVO[3], enable_3);
SERVO[0]<=0;
SERVO[1]<=0;
end
end
endmodule
我猜在side always block 中调用模块会导致错误。有没有其他方法 algorithm/method 可以解决这个问题?
谢谢。
虽然我不是 100% 确定您想要从 Servo_Motor
模块输出什么,但似乎对 Verilog 如何综合到 FPGA 配置中存在很多误解。首先,正如您所认识到的,您不能在 always
块中实例化模块;请参阅此答案以了解模块及其使用方式的说明:
基本上,模块是设计中执行特定任务的结构,它们不像函数那样被调用。就 FPGA 而言,它们是对硬件块的描述以及它必须如何工作,它有什么寄存器等。在您当前的代码中,您试图调用它们来执行任务,然后 "return"结果,当您需要实例化它们时(因此它们独立于 direction
而存在)并且是否使用它们的输出取决于 direction
.
其他一些提示:
1) Servo
模块没有启用行,因此在更改模块实例化位置时应将其删除。
2) 对寄存器(即时钟 always
块)使用非阻塞赋值 (<=
),对组合逻辑使用阻塞赋值 (=
)(就像你为Servo
模块中的最后一个块,没错)。注意,REG
和CNT
需要切换到NBA。
3) 对于最后一个块(和任何其他组合 always
块),使用 always @(*)
而不是 always @(CNT or REG)
,最好使用隐式敏感列表而不是显式以避免闭锁
4) RESETN
建议断言低复位,而您实施断言高复位。将网络命名为 RESET
或使用 negedge
和 if (~RESETN)
5) integer
类型指定仅用于模拟,将这些设为 reg [31:0]
(或者您真正需要的任何位数)。
希望这有助于阐明一些观点,RTL 中的思维与编程有很大不同。
我正在尝试使用 FPGA 控制 4 个电机。 (Verilog 高密度语言) 我使用 always 块和自定义模块编写了一个代码(它控制一个伺服电机,它的输入 values-L_CTRL 和 R_CTRL 确定伺服电机是向左还是向右旋转一步)
这是自定义模块代码:
module Servo(CLK, RESETN, L_CTRL, R_CTRL, SERVO);
input CLK;
input RESETN, L_CTRL, R_CTRL;
output SERVO;
integer REG, CNT;
reg L, R;
reg SERVO;
always @(posedge RESETN or posedge CLK)
begin
if (RESETN) CNT = 0;
else
if (CNT >= 199) CNT = 0;
else CNT = CNT + 1;
end
always @(posedge RESETN or posedge CLK)
begin
if (RESETN)
REG = 15;
else
begin
L <= L_CTRL; R <= R_CTRL;
if (L == 0 & L_CTRL & REG > 7)
REG = REG - 1;
else if (R == 0 & R_CTRL & REG < 23)
REG = REG + 1;
end
end
always @(CNT or REG)
begin
if (CNT < REG)
SERVO = 1;
else
SERVO = 0;
end
endmodule
我编写了控制 4 个电机的代码:
module Servo_Motor(direction,CLK,RESETN,SERVO);
input [1:0]direction;
input CLK, RESETN;
reg L_CTRL, R_CTRL;
reg [3:0] SERVO;
output [3:0] SERVO;
//servo0, servo1->x_axis
//servo2, servo3->y_axis
always @(posedge RESETN or posedge CLK)
begin
if(direction==2'b01)//east
begin
L_CTRL<=0; R_CTRL<=1;
Servo S0(CLK, RESETN, L_CTRL, R_CTRL, SERVO[0], enable_0);
Servo S1(CLK, RESETN, L_CTRL, R_CTRL, SERVO[1], enable_1);
SERVO[2]<=0;
SERVO[3]<=0;
end
else if(direction==2'b11)//SOUTH
begin
L_CTRL<=1; R_CTRL<=0;
Servo S2(CLK, RESETN, L_CTRL, R_CTRL, SERVO[2], enable_2);
Servo S3(CLK, RESETN, L_CTRL, R_CTRL, SERVO[3], enable_3);
SERVO[0]<=0;
SERVO[1]<=0;
end
else if(direction==2'b10)//WEST
begin
L_CTRL<=1; R_CTRL<=0;
Servo S0(CLK, RESETN, L_CTRL, R_CTRL, SERVO[0], enable_0);
Servo S1(CLK, RESETN, L_CTRL, R_CTRL, SERVO[1], enable_1);
SERVO[2]<=0;
SERVO[3]<=0;
end
else if(direction==2'b00)//NORTH
begin
L_CTRL<=0; R_CTRL<=1;
Servo S2(CLK, RESETN, L_CTRL, R_CTRL, SERVO[2], enable_2);
Servo S3(CLK, RESETN, L_CTRL, R_CTRL, SERVO[3], enable_3);
SERVO[0]<=0;
SERVO[1]<=0;
end
end
endmodule
我猜在side always block 中调用模块会导致错误。有没有其他方法 algorithm/method 可以解决这个问题?
谢谢。
虽然我不是 100% 确定您想要从 Servo_Motor
模块输出什么,但似乎对 Verilog 如何综合到 FPGA 配置中存在很多误解。首先,正如您所认识到的,您不能在 always
块中实例化模块;请参阅此答案以了解模块及其使用方式的说明:
基本上,模块是设计中执行特定任务的结构,它们不像函数那样被调用。就 FPGA 而言,它们是对硬件块的描述以及它必须如何工作,它有什么寄存器等。在您当前的代码中,您试图调用它们来执行任务,然后 "return"结果,当您需要实例化它们时(因此它们独立于 direction
而存在)并且是否使用它们的输出取决于 direction
.
其他一些提示:
1) Servo
模块没有启用行,因此在更改模块实例化位置时应将其删除。
2) 对寄存器(即时钟 always
块)使用非阻塞赋值 (<=
),对组合逻辑使用阻塞赋值 (=
)(就像你为Servo
模块中的最后一个块,没错)。注意,REG
和CNT
需要切换到NBA。
3) 对于最后一个块(和任何其他组合 always
块),使用 always @(*)
而不是 always @(CNT or REG)
,最好使用隐式敏感列表而不是显式以避免闭锁
4) RESETN
建议断言低复位,而您实施断言高复位。将网络命名为 RESET
或使用 negedge
和 if (~RESETN)
5) integer
类型指定仅用于模拟,将这些设为 reg [31:0]
(或者您真正需要的任何位数)。
希望这有助于阐明一些观点,RTL 中的思维与编程有很大不同。