`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Updated 8/12/2018 V2.lab5c
// Create Date: 10/1/2015 V1.0
// Design Name:
// Module Name: labkit
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module labkit(
   input CLK100MHZ,
   input[15:0] SW,
   input BTNC, BTNU, BTNL, BTNR, BTND,
   output[3:0] VGA_R,
   output[3:0] VGA_B,
   output[3:0] VGA_G,
   input[7:0] JB,
   output VGA_HS,
   output VGA_VS,
   output LED16_B, LED16_G, LED16_R,
   output LED17_B, LED17_G, LED17_R,
   output[15:0] LED,
   output[7:0] SEG,  // segments A-G (0-6), DP (7)
   output[7:0] AN    // Display 0-7
   );


// create 25mhz system clock for 640 x 480 VGA timing - in xvga.v
//    wire clock_25mhz;
//    clock_quarter_divider clockgen(.clk100_mhz(CLK100MHZ), .clock_25mhz(clock_25mhz));


// create 65mhz system clock for 1024 x 768 XVGA timing
    clk_wiz_0_clk_wiz clkdivider(.clk_in1(CLK100MHZ), .clk_out1(clock_65mhz));


//  instantiate 7-segment display;
    wire [31:0] data;
    wire [6:0] segments;
    display_8hex display(.clk(clock_65mhz),.data(data), .seg(segments), .strobe(AN));
    assign SEG[6:0] = segments;
    assign SEG[7] = 1'b1;

//////////////////////////////////////////////////////////////////////////////////
//
//  modify these lines as needed and insert your lab here

    //assign LED = SW;
    //assign JB[7:0] = 8'b0;
    
    //assign data = {28'h0123456, SW[3:0]};   // display 0123456 + SW
    assign LED16_R = BTNL;                  // left button -> red led
    assign LED16_G = BTNC;                  // center button -> green led
    assign LED16_B = BTNR;                  // right button -> blue led
    assign LED17_R = BTNL;
    assign LED17_G = BTNC;
    assign LED17_B = BTNR;


//
//////////////////////////////////////////////////////////////////////////////////
   wire enable;   // used to sample at  16 samples per data bit @ 9600
   wire din;      // data in from IMU/Teensy
   wire done;     // got one data packet
   
   synchronize syn3 (.clk(clock_65mhz), .in(JB[0]), .out(din));
   clock16x clk_enable(.clk(clock_65mhz), .enable(enable));

   wire [15:0] xdata, x,  xneg;
   wire [15:0] ydata, y,  yneg;
   wire [59:0] dout;  // 60 bits of data read in

   serialin myserial(.din(din), .clk(clock_65mhz), . enable(enable), .done(done),
                  .dout(dout));
                                    
   assign x= {dout[17:10], dout[7:0]};      //  x axis data bit extracted from the 60 bits
   assign y= {dout[36:29], dout[26:19]};    //  y axis data

   assign xneg = ~x+1;  //  convert from twos complement if negative number
   assign yneg = ~y+1;
   
   // this section displays twos complement in + - format
   assign xdata[15:12] = x[15] ? 4'hF : 4'h0;  // show "F" if negative, zero otherwise
   assign xdata[11:0] = x[15] ? xneg[15:4]  : x[15:4];  // display in +- format
   
   assign ydata[15:12] = y[15] ? 4'hF : 4'h0;
   assign ydata[11:0] = y[15] ? yneg[15:4]  : y[15:4];
  
   assign data = {xdata, ydata}; // x,y data to be displayed on hex display 
   
   assign LED = dout[15:0];  // used for debug

//////////////////////////////////////////////////////////////////////////////////
// sample Verilog to generate color bars or border

    wire [10:0] hcount;
    wire [9:0] vcount;
    wire hsync, vsync, at_display_area;
    xvga xvga1(.vclock(clock_65mhz),.hcount(hcount),.vcount(vcount),
          .hsync(hsync),.vsync(vsync),.blank(blank));
    wire [11:0] rgb;   // rgb is 12 bits

    wire border = (hcount==0 | hcount==1023 | vcount==0 | vcount==767 |
                  ( hcount == 512 && vcount>64 && vcount < 704) |
                  ( vcount == 384 && hcount>64 && hcount < 960));

    wire [11:0] pixel, pixelr;  // pixelr is the fixed ring
    
// pseudo low pass filter, running average of 4 samples    
    wire [10:0] xlevel = x[15] ? (512-SW[14:9]-(xneg[15:6]*2)) : (512-SW[14:9]+(x[15:6]*2));
    wire [9:0] ylevel = y[15] ? (384-SW[14:9]-(yneg[15:7]*2)) : (384-SW[14:9]+(y[15:7]*2));

    reg [10:0] xa[3:0];
    reg [9:0] ya[3:0];
    reg [1:0] index;
    wire [12:0] sumxa = xa[0] + xa[1] + xa[2] + xa[3];
    wire [11:0] sumya = ya[0] + ya[1] + ya[2] + ya[3];
    
    always @(posedge clock_65mhz) begin 
    
        if (done) begin
           index <= index + 1;
           xa[index] <= xlevel;
           ya[index] <= ylevel;
         end
         end
    
    reg signed [11:0] xerror;
    reg signed [10:0] yerror;
    reg old;
    
    
    always @(posedge clock_65mhz) begin
        old <= SW[15];
        if (SW[15]&&!old) begin
        xerror <= {1'b0, sumxa[12:2]}-(512-SW[14:9]);
        yerror <= {1'b0, sumya[11:2]} - (384-SW[14:9]);
        end
        end
        
    wire [10:0] newx = SW[15] ? (sumxa[12:2]-xerror) : sumxa[12:2];
    wire [9:0] newy = SW[15] ? (sumya[11:2]-yerror) : sumya[11:2];
    
    
      // character display module: sample string in middle of screen
     wire [63:0] cstring = "LAB 5c";
     wire [2:0]  cdpixel;
     char_string_display cd(clock_65mhz,hcount,vcount,
                cdpixel,cstring,11'd768,10'd200);
                

    assign rgb = SW[0] ? {12{border}} :(pixel | {12{border}} | pixelr | {12{cdpixel[2]}}); // {4{cdpixel[2]},4{cdpixel[1]},4{cdpixel[0]}});
    
    //assign rgb = SW[0] ? {12{border}} : {{4{hcount[7]}}, {4{hcount[6]}}, {4{hcount[5]}}};

   rblob circle(.clk(clock_65mhz), .radius(SW[14:9]), .x(newx), 
     .y(newy), .hcount(hcount), .vcount(vcount), .pixel(pixel));

   ring ring2(.clk(clock_65mhz), .radius(6'b1111_11), .x(448), 
     .y(320), .hcount(hcount), .vcount(vcount), .pixel(pixelr));
     
// the following lines are required for the Nexys4 VGA circuit
    assign VGA_R = ~blank ? rgb[11:8]: 0;
    assign VGA_G = ~blank ? rgb[7:4] : 0;
    assign VGA_B = ~blank ? rgb[3:0] : 0;

    synchronize #(.NSYNC(4)) syn1(.clk(clock_65mhz), .in(hsync), .out(hsync2));
    synchronize #(.NSYNC(4)) syn2(.clk(clock_65mhz), .in(vsync), .out(vsync2));

    assign VGA_HS = ~hsync2;
    assign VGA_VS = ~vsync2;
endmodule

module synchronize #(parameter NSYNC = 6)  // number of sync flops.  must be >= 2
                   (input clk,in,
                    output reg out);

  reg [NSYNC-2:0] sync;

  always @ (posedge clk)
  begin
    {out,sync} <= {sync[NSYNC-2:0],in};
  end
endmodule

module ring #(parameter COLOR = 12'b0011_1111_1111)
    (input clk,
    input [6:0] radius,
    input [10:0] x,hcount,
    input [9:0] y,vcount,
    output reg [11:0] pixel
    );

reg [13:0] rsquared, rsq2;
reg [13:0] xsq, ysq;

// make sure difference is positive number
wire [10:0] x1 = ((x + radius) > hcount) ? (x + radius - hcount) : (hcount - x - radius);
wire [9:0] y1 = ((y +radius) > vcount) ? (y + radius- vcount) : (vcount - y -radius);

always @(posedge clk) begin

rsquared <= radius * radius;
rsq2 <= (radius-3) * (radius-3);
xsq <= x1*x1;
ysq <= y1*y1;

if ((x1<radius) && (y1<radius))
	begin
	//if (((x1 * x1) + (y1 * y1)) < radius * radius)     // 1024 = 32 ^2
	
	if (   ((xsq + ysq) < rsquared)&&((xsq + ysq) > rsq2)   )
	
	  pixel <= COLOR;
	else pixel <= 0;
	end
	else pixel <= 0;
//else pixel = 0;
end
endmodule