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.
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.