Skip to content

Instantly share code, notes, and snippets.

@Premraj02
Created January 31, 2022 17:24
Show Gist options
  • Save Premraj02/ff78f56e6804f53e6c3d2018cdb7e09d to your computer and use it in GitHub Desktop.
Save Premraj02/ff78f56e6804f53e6c3d2018cdb7e09d to your computer and use it in GitHub Desktop.
module ADC(
input clk_50, //50 MHz clock PIN_R8
input dout, //digital output from ADC128S022 (serial 12-bit) PIN_A9
input reset,
output adc_cs_n, //ADC128S022 Chip Select PIN_A10
output din, //Ch. address input to ADC128S022 (serial) PIN_B10
output adc_sck, //2.5 MHz ADC clock PIN_B14
output [11:0]d_out_ch5, //12-bit output of ch. 5 (parallel)
output [11:0]d_out_ch6, //12-bit output of ch. 6 (parallel)
output [11:0]d_out_ch7 //12-bit output of ch. 7 (parallel)
);
parameter n = 20; //clock scaling parameter 50MHz/2.5MHz
reg [4:0]C_COUNT = 0; //register for counting cycles of 50MHz clock
reg [8:0]d1 = 9'b111011101; //register to store channel adresses
reg [1:0]din_r = 0; //register to store current adress output
reg [11:0]d_out_5 = 0; //register to store combined output data
reg [11:0]d_out_6 = 0;
reg [11:0]d_out_7 = 0;
reg [11:0]d_out5 = 0; //register to store ch5 output
reg [11:0]d_out6 = 0; //register to store ch6 output
reg [11:0]d_out7 = 0; //register to store ch7 output
reg [5:0]c = 0;
//---------Assigning chip select pin---------
assign adc_cs_n = 0;
//---------Scale the clock from 50 to 2.5 MHz---------
always @(negedge clk_50)begin
if(reset == 0)
begin
C_COUNT <= 0;
end
if(C_COUNT == 20)begin
C_COUNT <= 1;
end else begin
C_COUNT <= C_COUNT + 1;
end
end
assign adc_sck = C_COUNT > 10;
always @(negedge adc_sck)begin
if(reset == 0)
begin
c <= 0;
end
if(c == 47)begin
c <= 0;
end else begin
c <= c + 1;
end
end
assign data_frame = c;
always @(negedge adc_sck)begin
if(reset == 0)
begin
din_r <= 0;
end
case(c)
1:din_r <= d1[0];
2:din_r <= d1[1];
3:din_r <= d1[2];
17:din_r <= d1[3];
18:din_r <= d1[4];
19:din_r <= d1[5];
33:din_r <= d1[6];
34:din_r <= d1[7];
35:din_r <= d1[8];
default din_r <= 0;
endcase
end
assign din = din_r;
always @(posedge adc_sck)begin
if(reset == 0)
begin
d_out_5 <= 0;
d_out_6 <= 0;
d_out_7 <= 0;
d_out5 <= 0;
d_out6 <= 0;
d_out7 <= 0;
end
case(c)
4:d_out_7[11] <= dout;
5:d_out_7[10] <= dout;
6:d_out_7[9] <= dout;
7:d_out_7[8] <= dout;
8:d_out_7[7] <= dout;
9:d_out_7[6] <= dout;
10:d_out_7[5] <= dout;
11:d_out_7[4] <= dout;
12:d_out_7[3] <= dout;
13:d_out_7[2] <= dout;
14:d_out_7[1] <= dout;
15:d_out_7[0] <= dout;
16:d_out7 <= d_out_7;
20:d_out_5[11] <= dout;
21:d_out_5[10] <= dout;
22:d_out_5[9] <= dout;
23:d_out_5[8] <= dout;
24:d_out_5[7] <= dout;
25:d_out_5[6] <= dout;
26:d_out_5[5] <= dout;
27:d_out_5[4] <= dout;
28:d_out_5[3] <= dout;
29:d_out_5[2] <= dout;
30:d_out_5[1] <= dout;
31:d_out_5[0] <= dout;
32:d_out5 <= d_out_5;
36:d_out_6[11] <= dout;
37:d_out_6[10] <= dout;
38:d_out_6[9] <= dout;
39:d_out_6[8] <= dout;
40:d_out_6[7] <= dout;
41:d_out_6[6] <= dout;
42:d_out_6[5] <= dout;
43:d_out_6[4] <= dout;
44:d_out_6[3] <= dout;
45:d_out_6[2] <= dout;
46:d_out_6[1] <= dout;
47:d_out_6[0] <= dout;
0:d_out6 <= d_out_6;
endcase
end
assign d_out_ch5 = d_out5;
assign d_out_ch6 = d_out6;
assign d_out_ch7 = d_out7;
endmodule
module ColorDetect(
input clk_50,
input C_in,
output S0,
output S1,
output S2,
output S3,
output HL,
output [2:0]id2
);
reg [15:0]red = 0;
reg [15:0]green = 0;
reg [15:0]blue = 0;
reg [15:0]const = 2000;
reg [15:0]count2 = 0;
reg [15:0]clravg = 0;
reg [1:0]S23 = 0;
reg flag = 0;
reg f = 1;
reg hl = 0;
integer redcnt = 0;
integer greencnt = 0;
integer bluecnt = 0;
reg [2:0]clr1=1;
reg [2:0]clr2=2;
reg [2:0]clr3=3;
reg [2:0]clr4=1;
reg [2:0]clr5=2;
reg [15:0]rtemp=0;
reg [15:0]gtemp=0;
reg [15:0]btemp=0;
reg [2:0]clr= 0; //0=no_clr, 1=RED, 2=GREEN, 3=BLUE
parameter [2:0] cred= 0;
parameter [2:0] cgreen= 3;
parameter [2:0] cblue= 1;
parameter [2:0] ColorDetect= 2;
always @(posedge clk_50)begin
case(S23)
cred: begin
if(C_in == 1) begin
count2 <= count2 + 1;
flag = 1;
end
if(C_in == 0) begin
if(flag == 1)
begin
rtemp <= count2;
count2<=0;
S23 = S23 + 1;
flag = 0;
end
end
end
cgreen: begin
if(C_in == 1) begin
count2 <= count2 + 1;
flag = 1;
end
if(C_in == 0) begin
if(flag == 1)
begin
gtemp <= count2;
count2<=0;
S23 = S23 + 1;
flag = 0;
end
end
end
cblue: begin
if(C_in == 1) begin
count2 <= count2 + 1;
flag = 1;
end
if(C_in == 0) begin
if(flag == 1)
begin
btemp <= count2;
count2<=0;
S23 = S23 + 1;
flag = 0;
end
end
end
ColorDetect: begin
if(C_in == 1) begin
count2 <= count2 + 1;
flag = 1;
end
if(C_in == 0) begin
if(flag == 1)
begin
//red <= count2;
red <= rtemp;
green <= gtemp;
blue <= btemp;
count2<=0;
S23 = S23 + 1;
flag = 0;
end
end
end
endcase
clravg = red[15:2] + green [15:2] + blue[15:2] + const[15:2];
if(clravg > 1800 && clravg < 3000)
begin
if(red<green && red < blue)
begin
redcnt = redcnt + 1;
/*clr1 <= clr2;
clr2 <= clr3;
clr3 <= clr4;
clr4 <= clr5;
clr5 <= 1;
if(f == 1 && clr1 == clr2 && clr2 == clr3 && clr3 == clr4 && clr4 == clr5)
begin
clr <= 1;
hl <= 1;
f <= 0;*/
end else if(green < red && green < blue)
begin
greencnt = greencnt +1;
/*clr1 <= clr2;
clr2 <= clr3;
clr3 <= clr4;
clr4 <= clr5;
clr5 <= 2;
if(f == 1 && clr1 == clr2 && clr2 == clr3 && clr3 == clr4 && clr4 == clr5)
begin
clr <= 2;
hl <= 1;
f <= 0;*/
end else if(blue < red && blue < green)
begin
bluecnt = bluecnt +1;
/* clr1 <= clr2;
clr2 <= clr3;
clr3 <= clr4;
clr4 <= clr5;
clr5 <= 3;
if(f == 1 && clr1 == clr2 && clr2 == clr3 && clr3 == clr4 && clr4 == clr5)
begin
clr <= 3;
hl <= 1;
f <= 0;*/
end
if(redcnt == 4000000)
begin
if(flag == 0)
begin
clr <= 1;
hl <= 1;
f <= 0;
end
end
if(greencnt == 4000000)
begin
if(flag == 0)
begin
clr <= 2;
hl <= 1;
f <= 0;
end
end
if(bluecnt == 4000000)
begin
if(flag == 0)
begin
clr <= 3;
hl <= 1;
f <= 0;
end
end
end else if(clravg < 1500)
begin
clr = 0;
hl <= 0;
f <= 1;
redcnt = 0;
greencnt = 0;
bluecnt = 0;
end
end
assign S0 = 1;
assign S1 = 1;
assign S2 = S23[1];
assign S3 = S23[0];
assign id2 = clr;
assign HL = hl;
endmodule
module LSA(
output [7:0]m1, //motor1 PIN_D3
output [7:0]m2, //motor2 PIN_C3
input [11:0]s1, //12-bit output of ch. 5 (parallel)
input [11:0]s2, //12-bit output of ch. 6 (parallel)
input [11:0]s3, //12-bit output of ch. 7 (parallel)
input clk_50, //50 MHz clock
input reset,
output Led1, //Led used to indicate position of bot i.e. node or line
output Led2,
output Led3,
output HL1, // to control uart
output [2:0] id
);
reg signed[7:0]error = 0;
reg signed[7:0]difference = 0;
reg signed[7:0]correction = 0;
reg signed[7:0]cumulative_error = 0;
reg signed[7:0]preverror = 0;
reg [3:0]nodecount = -4'd1; //No. of nodes bot has traversed, initially set to -1
//reg [3:0]flag=0;
reg flag = 0;
reg led1=0;
reg led2=0;
reg led3=0;
reg [7:0]odc =50; //optimum duty cycle
reg [7:0]mo1 = 50; // pwm to motor1, initially set to 50
reg [7:0]mo2 = 50; // pwm to motor2, initially set to 50
reg [7:0]ml1 = 50; // pwm to motor1 when it is on line
reg [7:0]ml2 = 50; // pwm to motor2 when it is on line
reg [7:0]mn1 = 50; // pwm to motor1 when it is on node
reg [7:0]mn2 = 50; // pwm to motor2 when it is on node
reg [11:0]thr = 2000; //Condition to differentiate between white and black surface
reg [7:0]r_COUNT = 0; //counter
reg clk_1 = 0; //1 MHz Clock
reg [2:0] id1 =0; //to control uart
reg hl;
/*reg [9:0]s1v1=0;
reg [9:0]s1v2=0;
reg [9:0]s1v3=0;
reg [9:0]s1v4=0;
reg [9:0]s1v5=0;
reg [9:0]s1v6=0;
reg [9:0]s2v1=0;
reg [9:0]s2v2=0;
reg [9:0]s2v3=0;
reg [9:0]s2v4=0;
reg [9:0]s2v5=0;
reg [9:0]s2v6=0;
reg [9:0]s3v1=0;
reg [9:0]s3v2=0;
reg [9:0]s3v3=0;
reg [9:0]s3v4=0;
reg [9:0]s3v5=0;
reg [9:0]s3v6=0;
reg [11:0]s1avg=0;
reg [11:0]s2avg=0;
reg [11:0]s3avg=0;*/
always @(posedge clk_50) begin //Scaling down of 50MHz clock to 1 MHz
if(reset == 0)
begin
r_COUNT <= 0;
end
if (r_COUNT == 49 )begin //Check if count reaches 49
r_COUNT <= 0; //Reset counter if it reaches 49
end else begin
r_COUNT <= r_COUNT + 1; //increment counter by 1 till 49
end
clk_1 <= (r_COUNT < 25);
end
always @(posedge clk_1) begin
if(reset == 0)
begin
nodecount <=-4'd1 ; //Initially node count set to -1
end
led1 <= (s1>thr); //Led lights up when s1 has a greater value than 2000
led2 <= (s2>thr); //Led lights up when s2 has a greater value than 2000
led3 <= (s3>thr); //Led lights up when s3 has a greater value than 2000
error = (s1>thr) - (s3>thr); //Relative error between sensors s1 and s3: values range from -1 to 1 P
cumulative_error <= cumulative_error + error; //Adds up the error to give a cumulative error I
if (cumulative_error > 10) //Condition to reset the value of cumulative error to 10 if it crosses 10
begin
cumulative_error <= 10;
end
if (cumulative_error < -10) //Condition to reset the value of cumulative error to -10 if it crosses -10
begin
cumulative_error <= -10;
end
if (s1<thr && s2>thr && s3<thr) //Cumulative error resets to zero when the bot is on line i.e WBW
begin
cumulative_error <= 0;
hl=0;
end
difference <= error-preverror; //forms the differential part D
correction <= ((10*error) + cumulative_error + (2*difference)); // kp = 10, ki = 1, kd =2
preverror <= error; // Stores value of current error to previous error so that it can be used in next loop cycle
ml1 <= odc - correction; // PID tuning for motor 1
ml2 <= odc + correction; // PID tuning for motor 2
if (ml1>70) //Resetting value of ml1 to 70 if it crosses 70
begin
ml1 <= 70;
end
if (ml2>70) //Resetting value of ml2 to 70 if it crosses 70
begin
ml2 <= 70;
end
if (ml1<30) //Resetting value of ml1 to 30 if it becomes less than 30
begin
ml1 <= 30;
end
if (ml2<30) //Resetting value of ml2 to 30 if it becomes less than 30
begin
ml2 <= 30;
end
/* s1v1 <= s1v2;
s1v2 <= s1v3;
s1v3 <= s1v4;
s1v4 <= s1v5;
s1v5 <= s1v6;
s1v6 <= s1[11:2];
s1avg <= s1v1 + s1v2 + s1v3 + s1v4 + s1v5 + s1v6;
s2v1 <= s2v2;
s2v2 <= s2v3;
s2v3 <= s2v4;
s2v4 <= s2v5;
s2v5 <= s2v6;
s2v6 <= s2[11:2];
s2avg <= s2v1 + s2v2 + s2v3 + s2v4 + s2v5 + s2v6;
s3v1 <= s3v2;
s3v2 <= s3v3;
s3v3 <= s3v4;
s3v4 <= s3v5;
s3v5 <= s3v6;
s3v6 <= s3[11:2];
s3avg <= s3v1 + s3v2 + s3v3 + s3v4 + s3v5 + s3v6; */
/*if(s1>thr && s2>thr && s3>thr)
begin
flag = 1;
mo1 <= 0;
mo2 <= 63;
end*/
/*if(s1>thr && s2<thr && s3<thr && flag == 1) //end turning
begin
flag <= 0;
mo1 <= odc - correction;
mo2 <= odc + correction;
end
/*if(s1<thr && s2>thr && s3<thr && flag == 1)
begin
flag <= 0;
mo1 <= odc - correction;
mo2 <= odc + correction;
end*/
if (s1 < thr && s2 > thr && s3 < thr) //ready for next node, flag resets to zero on line : WBW
begin
flag <= 0;
end
/*else begin
flag <= 1;
end*/
// Only detect node once.
if (s1>thr && s2>thr && s3>thr && flag == 0) //detect node
begin
if (nodecount == 7) // Nodecount resets to zero if it crosses 7
begin
id1 = 4;
hl = 1;
nodecount <= 0;
flag <= 1; //flag set to 1 when it detects a node
end else
begin
id1 = 4;
hl = 1;
nodecount <= nodecount + 1;
flag <= 1;
end
end
/*if (s1>thr && s2>thr && s3>thr)
begin
if(flag == 3)
begin
if (nodecount == 7)
begin
nodecount <= 0;
flag <= 0;
flag2 <= 1;
end else
begin
nodecount <= nodecount + 1;
flag <=0;
flag2 <= 1;
end
end else
begin
flag <= flag + 1;
end
end else
begin
flag <= 0;
end*/
if(flag == 1) //Detection of node and applying pwm accordingly
begin
case (nodecount)
1: begin
mn1 <= odc;
mn2 <= odc;
end
2: begin
mn1 <= 5;
mn2 <= 60;
end
3: begin
mn1 <= odc;
mn2 <= odc;
end
4: begin
mn1 <= 5;
mn2 <= 60;
end
5: begin
mn1 <= odc;
mn2 <= odc;
end
6: begin
mn1 <= odc;
mn2 <= odc;
end
7: begin
mn1 <= 5;
mn2 <= 60;
end
0: begin
mn1 <= odc;
mn2 <= odc;
end
endcase
/*
mn1 <= 5;
mn2 <= 60;*/
end
if(flag == 0) //assigning values of ml1 and ml2 (line condition) to mo1 and mo2 respectively
begin
mo1 <= ml1;
mo2 <= ml2;
end else
begin //assigning values of mn1 and mn2 (node condition) to mo1 and mo2 respectively
mo1 <= mn1;
mo2 <= mn2;
end
end
assign Led1 = led1;
assign Led2 = led2;
assign Led3 = led3;
assign id = id1;
assign HL1 = hl;
assign m1 = mo1;
assign m2 = mo2;
endmodule
module PWM(
input clk_50, // Clock input
input [7:0]DUTY_CYCLE, // Input Duty Cycle
input reset,
output PWM_OUT // Output PWM
);
// Input Clock: 50 MHz
// Output Clock: 1 MHz
// Parameter ( 50 x 10^6 / 1 x 10^6 ) = 50
parameter COUNT_ONE = 50;
reg [7:0] r_COUNT = 0;
always @(posedge clk_50) begin
if(reset == 0)
begin
r_COUNT <= 0;
end
if (DUTY_CYCLE+1) begin //Check if duty Cycle is present
if (r_COUNT == COUNT_ONE -1 )begin //Check if count reaches 49
r_COUNT <= 0; //Reset counter if it reaches 49
end else begin
r_COUNT <= r_COUNT + 1; //increment counter by 1 till 49
end
end else begin
r_COUNT <= 0; //Reset counter if duty cycle not present
end
end
// PWM Waveform
assign PWM_OUT = (r_COUNT >= DUTY_CYCLE[7:1]);
endmodule
module uart(
input clk_50M, //50 MHz clock
output tx, //UART transmit output
input HL,
input [2:0]id,
input HL1
);
////////////////////////WRITE YOUR CODE FROM HERE////////////////////
reg [1:0] flag_1=1; // To assign value to tx
reg [8:0] counter=0; // To count the number of clock cycles
parameter clk_bit = 434; // Clocks per bit
parameter Idle = 3'b000; // Cases for the state machine
parameter start = 3'b001;
parameter data = 3'b010;
parameter stop = 3'b011;
//wire [1:40] d = "SM49\n"; // To store the string. The register stores the msb of 'S' at 1 and the rest follow.
wire [1:48] d0 = "START\n";
wire [1:96] d1 = "SI-SIM1-P-#\n";
wire [1:96] d2 = "SI-SIM2-N-#\n";
wire [1:96] d3 = "SI-SIM3-W-#\n";
wire [1:40] d4 = "NODE\n";
wire [1:32] d5 = "END\n";
integer i [0:5];
initial begin
i[0] = 6;
i[1] = 12;
i[2] = 12;
i[3] = 12;
i[4] = 5;
i[5] = 4;
end
integer k=1; // As we have to transmit lsb first, we will have to go in the order 8,7,6,5,4,3,2,1,16,15
integer m=0; // 14,13... 9,24,23... 17,32,31... 25. These two variables will be used to maintain that order.
integer l=0; // This integer is to make sure we transmit one byte(8 bits) in one cycle.
reg [2:0] tx_main = 0;
reg h1=0;
reg h2=1;
reg h3=0;
reg h4=1;
always @ ( posedge HL)
begin
h1 = h1 + 1;
end
always @ ( posedge HL1)
begin
h3 = h3 + 1;
end
always @(posedge clk_50M) begin
if(h1 == h2) begin
h2 = h2 + 1;
if((id != 0) && (id != -3'd1))
begin
k=1;
end
counter = 0;
end
if(h3 == h4) begin
h4 = h4 + 1;
if((id != 0) && (id != -3'd1))
begin
k=1;
end
counter = 0;
end
case (tx_main)
Idle: begin // The Idle bit. After 434 clock cycles we jump to the start case only if counter m is <33
if(counter<clk_bit - 1) begin // If counter m is >= 33, it means that all the bytes are sent.
counter<=counter+1;
tx_main<=Idle;
flag_1=1;
end
else begin
counter<=0;
m=8*k; // Here, m is assigned the value 8,16,24,32.
if(m<=8*i[id])tx_main<=start;
else tx_main<=Idle;
end
end
start : begin // The start bit.
if(counter<clk_bit - 1) begin
counter<=counter+1;
l=0;
tx_main<=start;
flag_1=0;
end
else begin
counter<=0;
tx_main<=data;
end
end
data: begin // The data bit.
//flag_1 = d[m]; // Assigns the bit to be transmitted to flag (High or Low)
case (id)
0: begin
flag_1 = d0[m];
end
1: begin
flag_1 = d1[m];
end
2: begin
flag_1 = d2[m];
end
3: begin
flag_1 = d3[m];
end
4: begin
flag_1 = d4[m];
end
5: begin
flag_1 = d5[m];
end
endcase
if(counter<clk_bit - 1 && l<8) begin
counter<=counter+1;
tx_main<=data;
end
else begin
if(l==7) begin
tx_main<=stop;
counter<=0;
k=k+1;
end
else begin
counter<=0;
tx_main<=data;
end
l=l+1; // To make sure only 8 bits are sent.
m=m-1;
end
end
stop: begin
flag_1=1; // The stop bit.
if(counter<clk_bit - 1) begin
counter<=counter+1;
tx_main<=stop;
end
else begin
counter<=0;
tx_main<=Idle;
end
end
endcase
end
assign tx = flag_1; //assign high or low value to tx accordingly.
////////////////////////YOUR CODE ENDS HERE//////////////////////////
endmodule
///////////////////////////////MODULE ENDS///////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment