`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: Bucknell University // Engineer: Rob Kurtz, // Mike Ragusa, // Andrew Rahimi // // Create Date: 13:48:46 04/05/2012 // Design Name: Wall-Evader // Module Name: RoboBrains // Project Name: Wall-Evader // Target Devices: FPGA/Robot // Tool versions: N/A // Description: A Robot that detects walls and rotates 180 degrees, continuing // forward motion in the direction opposite the wall. // // Dependencies: None // ////////////////////////////////////////////////////////////////////////////////// /* // MAIN MODULE: Integrates the modules DriveControl and sensorCity such that // data obtained from the sensor may be used to influence drive decisions. */ module RoboBrains( input clock, output motor1Dir, output motor1En, output motor2Dir, output motor2En, input sensorF, output wallF, output ADClock1, output ADCS ); wire clk; clkdiv myClock(clock, clk); assign ADClock1=clk; wire wallFIn; assign wallFIn = wallF; DriveControl drive(clk, motor1Dir, motor1En, motor2Dir, motor2En, wallFIn); sensorCity sensors(sensorF, clk, wallF, ADCS); endmodule /* // DRIVE CONTROL: Implements state logic for drive decisions. Two states exist. // State 0 drives both motors forward at top speed. State 1 drives the right motor // forward at top speed and the left motor backwards at half of top speed for a finite time. // // The robot stays in state 0 until a wall is encountered. At this time, the robot enters // state 1 and stays in state 1 for a time necessary for the robot to execute ~180 degree turn. */ module DriveControl( input clk, output motor1Dir, output motor1En, output motor2Dir, output motor2En, input wallFIn ); reg [14:0] counter, counter_next; reg state, state_next; reg [6:0] speed_m1, speed_m1_next, speed_m2, speed_m2_next; reg dir_m1, dir_m1_next, dir_m2, dir_m2_next; //127 for full speed (arg 2) PWMDrive left(clk, speed_m1, dir_m1, motor1Dir, motor1En); PWMDrive right(clk, speed_m2, dir_m2, motor2Dir, motor2En); initial begin counter = 0; state = 0; end // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @ (posedge clk) begin counter <= counter_next; state <= state_next; speed_m1 <= speed_m1_next; dir_m1 <= dir_m1_next; speed_m2 <= speed_m2_next; dir_m2 <= dir_m2_next; end // ------------- COMBINATIONAL LOGIC ------------------ // blocking, update next_states // ---------------------------------------------------- always @ * begin if(wallFIn == 1 && state == 0)begin counter_next = 0; state_next = 1; end else if(counter == 15'd4000 && state==1) begin counter_next = 0; state_next = 0; end else begin state_next = state; counter_next = counter + 15'd1; end if(state == 1'd0) begin speed_m1_next = 127; dir_m1_next = 0; speed_m2_next = 127; dir_m2_next = 0; end else begin // condition for LEFT TURN speed_m1_next = 127; dir_m1_next = 0; speed_m2_next = 63; dir_m2_next = 1; end end endmodule /* // PULSE WIDTH MODULATION DRIVE: Drives a motor. This module is instantiated // in the DriveControl module twice -- once for each motor. // // Pulse width modulation is the first of two industry-wide protocols implemented // in this design. */ module PWMDrive( input clock, input speed, input direction, output reg dir, output reg en ); // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @ (posedge clock) begin dir <= direction; en <= speed; end endmodule /* // CLOCK DIVIDER: Increases the period of a clock cycle to a reasonable rate. */ module clkdiv(input fastclk, output reg slowclk); reg [15:0] counter; initial counter = 0; // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @ (posedge fastclk) begin if(counter ==15'd25000) begin slowclk <= ~slowclk; counter =0; end else counter=counter +1; end endmodule /* // CLOCK DIVIDER 16: Further slows the period of a clock cycle by a // factor of 16. This module is used in the implemented of the SPI // protocol, which uses a 16 bit cycle to serialize data. */ module clkdiv16(input fastclk, output reg slowclk); reg [5:0] counter; initial counter = 0; // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @ (posedge fastclk) begin if(counter ==5'd16) begin slowclk <= ~slowclk; counter =0; end else counter=counter +1; end endmodule /* // SENSOR CITY: Instantiates a SerialAD module and raises a flag based // on the output of the SerialAD module. Sensor city raises a flag on // the basis of the decimal value stored in the 12-bit vector sensorFdig. // If this value is greater than 3100, then Sensor city raises its flag. // // 3100 is a valid member of integers ranged [0 - 4096], which is the output // range of the Analog to Digital Converter (A/D) used in this design. 3100 // represents a desirable proximity to a wall such that a reversal in the Robot's // direction is desirable. */ module sensorCity ( input sensorF, input clk, output reg wallF, output sensorFCS ); wire [11:0]sensorFdig; wire clk16; clkdiv16 clk16Divider(clk, clk16); SerialAD sadf(sensorF, clk, sensorFdig, sensorFCS); initial begin wallF = 0; end // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @(posedge clk16) begin if(sensorFdig < 12'd3100) begin wallF <= 0; end else wallF <= 1; end endmodule /* // SERIAL AD: Implements the Serial Peripheral Interface (SPI) in the context // of the Digilent A/D 1 Module. Here, each analog value was represented as 12 // bits belonging to a 16 bit cycle. The first 4 bits are leading zeros; they // mark the beginning of a new cycle. The remaining 12 bits is the decimal value // associated with the original analog value. These bits are transmitted beginning // with the most significant bit (and ending with the least significant bit). // // INPUT DataStream: analog data stream. // INPUT ADClock: clock for A/D. // OUTPUT OutBits: 12-bit reg containing digital equivalent. // OUTPUT con: chip select for A/D. */ module SerialAD( input DataStream, input ADClock, output reg [11:0] OutBits, output reg conv // chip select ); //register declarations reg conv_next; reg [4:0] count, count_next; reg [11:0] data_temp_next; initial begin conv_next = 1; count = 0; count_next = 0; data_temp_next = 0; end // --------------- SEQUENTIAL LOGIC ------------------ // non-blocking, push out next_states to outputs // --------------------------------------------------- always @ (posedge ADClock) begin count <= count_next; OutBits <= data_temp_next; conv <= conv_next; end // ------------- COMBINATIONAL LOGIC ------------------ // blocking, update next_states // ---------------------------------------------------- always @ * begin data_temp_next = {OutBits[10:0], DataStream}; if (count == 5'd16) begin count_next = 4'd0; conv_next = 1'd1; end else begin count_next = count + 4'd1; conv_next = 1'd0; end end endmodule