verilogmotordriver

Controlling 4 motors using FPGA


I'm trying to control 4 motors using FPGA. (Verilog HDL) I made a code using always block and custom module(which controls one servo motor, and it's input values-L_CTRL and R_CTRL determines whether servo motor spins one step to left or right)

Here is custom module code:

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

and I made code for controlling 4 motors:

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

I guess calling module in side always block causes error. Are there any alternative algorithm/method to solve this problem?

Thanks.


Solution

  • While Im not 100% sure what output you want from your Servo_Motor module, there seems to be alot of misunderstanding of how Verilog synthesizes into an FPGA configuration. First and foremost, as you recognize, you cannot instantiate modules in always blocks; see this answer for an explanation of modules and how they should be used:

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

    Basically, modules are structures within the design that perform a specific task, they are not called like functions. In terms of an FPGA, they are a description of a block of hardware and how it must behave, what registers it has, etc. In your current code, you are trying to call them to perform a task and then "return" the result, when you need to be instantiating them (so they exist independent of the direction) and either using their output or not depending on the direction.

    A few other pointers:

    1) The Servo module doesnt have an enable line, so you should remove it when you change where the modules are instantiated.

    2) Use non-blocking assignments (<=) for registers (ie, clocked always blocks) and blocking assignments (=) for combinational logic (like you do for the last block in the Servo module, thats correct). Note, REG and CNT need to be switched to NBA.

    3) For the last block (and any other combinational always blocks), use always @(*) rather than always @(CNT or REG), its better to have implicit sensitivity lists rather than explicit to avoid latching

    4) RESETN suggests an asserted low reset, while you implement an asserted high reset. Either make the net named RESET or which them to use negedge and if (~RESETN)

    5) integer type is designated only to be used in simulation, make these reg [31:0] instead (or however many bits you really need).

    Hope this helps clarify some points, thinking in RTL is very different than programming.