【问题标题】:Controlling 4 motors using FPGA使用 FPGA 控制 4 个电机
【发布时间】:2016-12-12 10:10:49
【问题描述】:

我正在尝试使用 FPGA 控制 4 个电机。 (Verilog HDL) 我使用always块和自定义模块编写了一个代码(它控制一个伺服电机,它的输入值-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

我猜在侧边调用模块总是阻塞会导致错误。有没有替代算法/方法来解决这个问题?

谢谢。

【问题讨论】:

    标签: verilog motordriver


    【解决方案1】:

    虽然我不能 100% 确定您想要从 Servo_Motor 模块获得什么输出,但似乎对 Verilog 如何将其综合到 FPGA 配置中存在很多误解。首先,正如您所认识到的,您不能在 always 块中实例化模块;有关模块的说明以及应如何使用它们,请参阅此答案:

    How can i instantiate a module inside an if statement in verilog?

    基本上,模块是设计中执行特定任务的结构,它们不像函数那样被称为。就 FPGA 而言,它们是对硬件块的描述以及它必须如何运行、它具有哪些寄存器等。在您当前的代码中,您试图调用它们来执行任务,然后“返回”结果,当您需要实例化它们时(因此它们独立于direction 而存在)并且是否使用它们的输出取决于direction

    其他几点建议:

    1) Servo 模块没有启用行,因此在更改模块的实例化位置时应将其删除。

    2) 将非阻塞分配 (&lt;=) 用于寄存器(即时钟 always 块)和阻塞分配 (=) 用于组合逻辑(就像您对 Servo 中的最后一个块所做的那样模块,没错)。注意,REGCNT 需要切换到 NBA。

    3) 对于最后一个块(以及任何其他组合 always 块),使用 always @(*) 而不是 always @(CNT or REG),最好使用隐式敏感度列表而不是显式以避免锁定

    4) RESETN 建议断言低复位,而您实现断言高复位。要么将网络命名为RESET,要么让他们使用negedgeif (~RESETN)

    5) integer 类型被指定仅用于模拟,请改为使用这些 reg [31:0](或者您真正需要的任何位)。

    希望这有助于澄清一些观点,RTL 中的思考与编程非常不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-08
      • 2014-01-29
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多