In this lab, you will learn how to create and use different clock frequencies in your Verilog code, as well as how to use the encoder subsystem, which lets you track the rotation of the wheels. By tracking the rotation of the wheels, you will learn to make your car do precise turns and movements, down to single degree turns.
Clock DomainsBefore we can implement a new hardware subsystem in the encoders, we have to implement a new Verilog software concept. Up until this point, we have been synchronizing our systems using the onboard clock of the WebFPGA, WF_CLK. A quick reminder, it runs at a 16MHz frequency, with a 62.5ms period. See the waveform below:
However, this clock may not be the correct frequency for our application. Or, maybe we’re trying to write code for the WebFPGA to interface with another piece of hardware that has its own, different frequency clock. Either way, this section of the lab will detail how we can create a different clock in our system, and provide you a module to do so. Dealing with systems that operate in multiple clock domains is an important Verilog skill, and a necessary one to be able to use the encoders. But before we talk about the new subsystem, let’s look at a module that will let us generate a slower clock. Look at the inputs and outputs, and try to think what you would set them to when you would use this module in a program.
module newclock (
input clk, enable,
input [15:0] divider,
output reg newclk
);
reg [16:0] counter;
always @(posedge clk)
begin
if (enable)
begin
counter <= counter + 1;
if (counter == divider)
begin
counter <= 0;
newclk <= ~newclk;
end
end
else
begin
newclk <= 0;
counter <= 0;
end
end
endmodule
As you can see, the above module accepts a clock, an enable signal, and a variable called divider, and outputs the new clock. Can you intuit what the divider variable does, looking at the code above? Knowing this, can you write code that outputs a clock that runs at half the speed of the WebFPGA clock? What about one fourth of the speed? Most importantly, can you verify (either through an oscilloscope or by writing code to stimulate an LED) that your clock is running at the relative speed to the WebFPGA clock?
Using a slower clock is necessary to use the encoders, but beyond that, there’s not much else practical use with the RSLK and the WebFPGA. However, multiple clock domain Verilog code is very important in more complex Verilog modules, and using/coding them will be something you explore in future Verilog courses. Consider this your first exposure to the subject.
EncodersThe encoder subsystems on the RSLK are located on the motor assembly of the car, and come integrated when you assemble your RSLK. See the picture below, for reference. The encoders generate digital signal pulses as the wheel of the RSLK turns. By piping these pulses into our Verilog modules, we can interpret them and use them to track the rotations of the wheels. See the pin assignment for the encoders (and for a quick review, the motor control signals) below:
// Pin Map
// @MAP_IO motorL_pwm 0
// @MAP_IO motorL_dir 1
// @MAP_IO motorL_en 2
// @MAP_IO motorL_encdr 12
// @MAP_IO motorR_pwm 3
// @MAP_IO motorR_dir 4
// @MAP_IO motorR_en 5
// @MAP_IO motorR_encdr 14
The motorL/R_encdr signals are inputs into our system, and represent those encoder pulses I mentioned earlier. By incrementing a counter value every time we see an encoder pulse (or decrementing it, if the motors are moving backwards), we can track how many degrees the tires are rotating, 1 pulse equals 1 degree of rotation. 360 degrees of rotation creates 1 revolution of the wheel. Knowing this, we can track how many revolutions our wheels have done, or do more granular moves with specific degrees. The module below we created will accept inputs for what direction the motor is going, if the motors are on, if we’re using the encoders, the actual encoder pulse, and the clock.
module encoder (
input clk, motor_dir, motor_en, encoder_en, encoder_pulse,
output reg signed [10:0] rev, deg
);
reg signed [10:0] old_deg, old_rev;
//degree overflow signal
wire ov_deg;
always @(posedge clk)
begin
if (encoder_en && !ov_deg)
deg <= old_deg;
else if (encoder_en && ov_deg)
begin
rev = old_rev;
deg = 11'sd0;
end
else
begin
deg <= 11'sd0;
rev <= 11'sd0;
end
end
always @(posedge encoder_pulse)
begin
if (motor_dir)
begin
old_deg <= deg - 11'sd1;
end
else
begin
old_deg <= deg + 11'sd1;
end
end
assign ov_deg = (deg >= 11'sd360) || (deg <= -11'sd360);
always @(*) begin
if (motor_dir)
old_rev <= rev - 11'sd1;
else
old_rev <= rev + 11'sd1;
end
endmodule
The outputs of the above modules can be used to make precise movements with your car. You’re going to want to create 2 instances of the module, one for each wheel. That way, you can do precise movements with each wheel. For example, rotate one wheel 180 degrees forward, and one wheel 180 degrees backward, and you’ll get a 90 degree turn of the car’s wheels. Use the output of the encoder modules to determine decision points in your state machines. However, if you’ve already plopped that above module into your code and wired everything up, you may find you’re unable to get consistent movements with your car. Remembering what we mentioned before (that you would need the move clock module to make the encoders work), what do you think is happening with the car? How can you use the new clock module to fix it? Test your solution by marking a point on your wheels to see if the car is doing the correct degrees of rotations/number of revolutions. Once you are confident in your cars accuracy, see if you can make your car do the following:
- Move 3 revolutions forward, then 3 revolutions backwards (make sure you set your wheel speed to low using the motor module, 3 revolutions can be a lot at high speed). Your car should end approximately in the same spot it started. If you’re having trouble with your car drifting, consider decreasing the speed of one of the motors to compensate for differences in the motors.
- Move in a square (so, 4 straight lines of equal length, with 4 90 degree turns, ending near the spot it started at)
- Move in a triangle (you can pick the shape of the triangle. Different triangle types have different challenges associated with them, just make sure the car ends where it started).
Congratulations! You almost have a fully functional car. At this point, you can exert an extremely precise measure of control on your car, all while using Verilog code that has multiple modules; if you’re using our motor, encoder, and new clock module, you should have 4 modules total (counting your FPGA top). This is no small feat for Verilog code! Using this toolkit of modules, you can make your car do a lot of things. But the next and final lab is the big kahuna. The final subsystem and assignment. The IR sensors, and black line following.
Comments