dakies/OSS_Verilog huggingface dataset:
module debouncer(
	input clk,rst_n,pushbutton,  //push-button is active-low
	output key                   //output is active high for easier use with other modules
	); 

	reg pushbutton_1=1'b0;       
	reg[31:0] cnt=32'd0;         //debounce timer   
	assign key=pushbutton_1;

	always @(posedge clk,negedge rst_n)
	begin
		if(!rst_n) 
			begin 
				pushbutton_1<=1'b0; 
				cnt<=32'd0;
			end
		else if(pushbutton_1!=(!pushbutton)) 
			begin 
				pushbutton_1<=(cnt==32'd500_000)?(!pushbutton_1):pushbutton_1; //pushbutton must stabilize for 500_000 cycles(10ms for 50MHz) before output changes
				cnt<=(cnt==32'd500_000)?20'd0:(cnt+1'b1);
			end
		else cnt<=32'd0;
	end

	
endmodule
module led_dimmer_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg [3:0] w;
   reg en;
	// Outputs
	wire pwm;

	// Instantiate the Unit Under Test (UUT)
	led_dimmer uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.w(w), 
		.pwm(pwm),
		.en(en)
	);
	always begin
	clk=1'b0;
	#1;
	clk=1'b1;
	#1;
	end
	integer i;

	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 1;
		w = 0;
		en=1;
		@(negedge clk) rst_n=0;
		@(negedge clk) rst_n=1;     
		
		//4 ns
		
		for(i=0;i<=15;i=i+1) begin
		w=i;
		#100;
		end
		#100 $stop;
		
	end
      
endmodule
module led_dimmer(
	input clk,rst_n,
	input en,
	input[3:0] w, //4-bit resolution. Duty cycle=w/16
	output pwm
    );
	 
	 reg[3:0] counter_reg=0;
	 reg pwm_reg=0;
	 wire[3:0] counter_nxt;
	 wire pwm_nxt;
	 wire max_tick;
	 
	 //registers
	 always @(posedge clk,negedge rst_n) begin
		 if(!rst_n) begin
			counter_reg<=0;
			pwm_reg<=0;
		 end
		 else begin
			if(en) begin
			counter_reg<=counter_nxt;
			pwm_reg<=pwm_nxt;
			end
			else begin 
			counter_reg<=0;
			pwm_reg<=0;
			end
		 end
	 end
	 
	 //next-state logic for counter
	 assign counter_nxt=(counter_reg==4'd15)?0:counter_reg+1;
	 assign max_tick=(counter_reg==4'd15)?1:0;
	 
	 //next state logic for pwm_reg
	 assign pwm_nxt=max_tick? (w?1:0) : ((counter_nxt==w)?0:pwm_reg);//if w is logic 1 then the period will start with 1, but if w is zero then obviously it will start with 0
	 
	 //output
	 assign pwm=pwm_reg;
	 
	 


endmodule
module kb(   //extract only the real bytes from received packets of data(no break code)
	input clk,rst_n,
	input ps2d,ps2c,
	input rd_fifo,
	output [8:0] rd_data, //{shift,data}
	output fifo_empty
    );
	 wire[10:0] dout;
	 wire rx_dont_tick;
	 wire wr;
	 wire [8:0] wr_data;
	 
 
	 ps2_rx m0
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_en(1),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.dout(dout),
		.rx_done_tick(rx_done_tick)
    );
	 
	 kb_data m1
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_done_tick(rx_done_tick),
		.din(dout[8:1]),
		.wr(wr),
		.wr_data(wr_data)
    );
	 
	  fifo #(.W(2),.B(9)) m2
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(wr),
		.rd(rd_fifo), //
		.wr_data(wr_data),
		.rd_data(rd_data),//
		.full(),
		.empty(fifo_empty) //
    );
	 
endmodule
module greater_than_2bit_TB;

	// Inputs
	reg [1:0] a;
	reg [1:0] b;

	// Outputs
	wire gt;
	reg[4:0] counter;
	
	
	// Instantiate the Unit Under Test (UUT)
	greater_than_2bit uut (
		.a(a), 
		.b(b), 
		.gt(gt)
	);

	initial begin
		$display("a[1] a[0] b[1] b[0] gt");
		for(counter=0;counter<=15;counter=counter+1'b1) begin
			a=counter[3:2];
			b=counter[1:0];
			$strobe("%b     %b     %b    %b   %b",a[1],a[0],b[1],b[0],gt);
			#10;
		end
		$stop;
	end
      
endmodule
module eq2(
	input wire[1:0] a, b, 
	output wire aeqb 
    );

	// internal signal declar.ation 
	wire eO, e1;

	// instantiate ~H'O I- bit comparators 
	eq1 eq_bit0_unit(.i0(a[0]), .i1(b[0]) , .eq(eO)) ; 
	eq1 eq_bitl_unit(.eq(e1), .i0(a[1]), .i1(b[1])); 
 // a and b are equal if individual bits are equal 
	assign aeqb = eO & e1; 
endmodule
module greater_than_4bit_TB;

	// Inputs
	reg [3:0] a;
	reg [3:0] b;

	// Outputs
	wire gt;
	reg[8:0] counter;
	// Instantiate the Unit Under Test (UUT)
	greater_than_4bit uut (
		.a(a), 
		.b(b), 
		.gt(gt)
	);

	initial begin
		$display("a b  gt");
		for(counter=0;counter<=255;counter=counter+1'b1) begin
			a=counter[7:4];
			b=counter[3:0];
			$strobe("%0d %0d  %b",a,b,gt);
			#10;
		end
		$stop;

	end
      
endmodule
module greater_than_2bit(
	input  wire[1:0] a,b,
	output wire gt
    );
	 
	 //signal declarations for terms in sum-of-product 
	 wire sp1,sp2,sp3,sp4,sp5,sp6;
	 
	 //use table as reference
	 assign sp1= !a[1] & a[0] & !b[1] & !b[0];
	 assign sp2= a[1] & !a[0] & !b[1] & !b[0];
	 assign sp3= a[1] & !a[0] & !b[1] & b[0];
	 assign sp4= a[1] & a[0] & !b[1] & !b[0];
	 assign sp5= a[1] & a[0] & !b[1] & b[0];
	 assign sp6= a[1] & a[0] & b[1] & !b[0];
	 
	 assign gt = sp1 || sp2 || sp3 || sp4 || sp5 || sp6;


endmodule
module eq1(
	input wire i0,i1,
	output wire eq
    );
	// signal declaration 
	wire p0, pl; 

	// body 
	// sum of two product terms 
	assign eq = p0 || pl; 
	
	// product terms 
	assign p0 = ~i0 & ~i1; 
	assign pl = i0 & i1;

endmodule
module greater_than_4bit(
	input wire[3:0] a,b,
	output wire gt
    );
	 
	 wire[1:0] a1,a0,b1,b0 ; //a1=2 MSB of "a" input , a0=2 LSB of "a" input , b1=2 MSB of "b" input , b0=2 LSB of "b" input
	 wire gt1,gt0; //gt1=true if a1>b1 , g0=true if a0>b0
	 wire aeqb;
	 assign a1=a[3:2],
				a0=a[1:0],
				b1=b[3:2],
				b0=b[1:0];
				
	 //overall logic for 4-bit greater than circuit
	 assign gt=gt1 || (aeqb&&gt0);
	 
	 greater_than_2bit m0
	 (
		.a(a1),
		.b(b1),
		.gt(gt1)
    );
	 
	 greater_than_2bit m1
	 (
		.a(a0),
		.b(b0),
		.gt(gt0)
    );
	 
	 eq2 m2
	 (
		.a(a1),
		.b(b1), 
		.aeqb(aeqb) 
    );


endmodule
module dual_port_syn //dual port synchronous ram(uses block ram)
	#(
		parameter ADDR_WIDTH=11, 
					 DATA_WIDTH=8
	)
	(
		input clk,
		input we, //if write:write data based on addr_a , if read:read data for both addr_a and addr_b
		input[DATA_WIDTH-1:0] din,
		input[ADDR_WIDTH-1:0] addr_a,addr_b,
		output[DATA_WIDTH-1:0] dout_a,dout_b	
	);
	
	reg[DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
	reg[ADDR_WIDTH-1:0] addr_a_q,addr_b_q;
	
	always @(posedge clk) begin
		if(we) ram[addr_a]<=din;
		addr_a_q<=addr_a;
		addr_b_q<=addr_b;	
	end
	assign dout_a=ram[addr_a_q];
	assign dout_b=ram[addr_b_q];
endmodule
module uart_teminal
	(
	input clk,rst_n,
	input rx, //ascii characters will come from pc serial port via UART
	output[4:0] vga_out_r,
	output[5:0] vga_out_g,
	output[4:0] vga_out_b,
	output vga_out_vs,vga_out_hs
    );
	 
	 wire[11:0] pixel_x,pixel_y;
	 wire video_on;
	 wire[2:0] rgb;
	 
	 
	 assign vga_out_r=rgb[2]? 5'b111_11:0 ;
	 assign vga_out_g=rgb[1]? 6'b111_111:0 ;
	 assign vga_out_b=rgb[0]? 5'b111_11:0 ;
	 

	 vga_core m0
	(
		.clk(clk_out),  //clock must be 25MHz for 640x480 
		.rst_n(rst_n),
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
    );	
	 
	full_screen_gen m1 //generates the characters to be displayed on screen, the ASCII characters will come from pc serial port via UART
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.rx(rx),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y),
		.video_on(video_on),
		.rgb(rgb)
    );
	
	 dcm_25MHz m2
		(// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 );      
	
endmodule
module top_module
	(
		input clk, rst_n,
		input[1:0] key, ////key[1] is for changing speed of both balls, key[0] for changing location of both ball(randomly)
		output[4:0] vga_out_r,
		output[5:0] vga_out_g,
		output[4:0] vga_out_b,
		output vga_out_vs,vga_out_hs
    );
	 
	wire clk_out;
	wire video_on;
	wire[11:0] pixel_x,pixel_y;
	dcm_25MHz m0
   (// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 );
	 vga_core m1
	(
		.clk(clk_out),
		.rst_n(rst_n), //clock must be 25MHz for 640x480 
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
    );
	 
	 two_balls_in_a_box m2 //two balls bounce inside a 100x100 box
	 (
		.clk(clk_out),
		.rst_n(rst_n),
		.key(key),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y),
		.r(vga_out_r),
		.g(vga_out_g),
		.b(vga_out_b)
    );	
	 
	 
	 
endmodule
module fifo
	#(parameter W=11,B=8)
	(
	input clk,rst_n,
	input wr,rd,
	input[B-1:0] wr_data,
	output[B-1:0] rd_data,
	output reg full,empty	
//	output reg[W-1:0] rd_ptr,wr_ptr
    );
	 initial begin
		full=0;
		empty=1;
	 end
	 reg[W-1:0] rd_ptr=0,wr_ptr=0;
	 reg[B-1:0] array_reg[2**W-1:0];

	 
	 //register file operation
	 always @(posedge clk) begin
		if(wr && !full && !(wr&&rd&&empty)) array_reg[wr_ptr]=wr_data;
	 end
	 assign rd_data=array_reg[rd_ptr];
	 
	 //fifo operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			rd_ptr=0;
			wr_ptr=0;
			full=0;
			empty=1;
		end
		else begin
			case({rd,wr})
				2'b01: if(!full) begin
							wr_ptr=wr_ptr+1;
							empty=0;
							full=(wr_ptr==rd_ptr);
						 end
				2'b10: if(!empty) begin
							rd_ptr=rd_ptr+1;
							full=0;
							empty=(rd_ptr==wr_ptr);
						 end
				2'b11: if(!empty && !full) begin
								rd_ptr=rd_ptr+1;
								wr_ptr=wr_ptr+1;
						 end
			endcase
		end
	 end

endmodule
module dual_port_syn //synchronous dual port ram(uses block RAM resources)
	#(
		parameter ADDR_WIDTH=11, 
					 DATA_WIDTH=8
	)
	(
		input clk,
		input we, //if write:write data based on addr_a , if read:read data for both addr_a and addr_b
		input[DATA_WIDTH-1:0] din,
		input[ADDR_WIDTH-1:0] addr_a,addr_b,
		output[DATA_WIDTH-1:0] dout_a,dout_b	
	);
	
	reg[DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
	reg[ADDR_WIDTH-1:0] addr_a_q,addr_b_q;
	
	always @(posedge clk) begin
		if(we) ram[addr_a]<=din;
		addr_a_q<=addr_a;
		addr_b_q<=addr_b;	
	end
	assign dout_a=ram[addr_a_q];
	assign dout_b=ram[addr_b_q];
endmodule
module underlined_cursor
	(
	input clk,rst_n,
	input rx, //ASCII characters to be displayed on screen will come from pc serial terminal
	input[2:0] key, //key[0] to move cursor to right,key[1] to move cursor down,key[2] to write new ASCII character to current cursor
	output[4:0] vga_out_r,
	output[5:0] vga_out_g,
	output[4:0] vga_out_b,
	output vga_out_vs,vga_out_hs
    );
	 
	 wire[11:0] pixel_x,pixel_y;
	 wire video_on;
	 wire[2:0] rgb;
	 
	 
	 assign vga_out_r=rgb[2]? 5'b111_11:0 ;
	 assign vga_out_g=rgb[1]? 6'b111_111:0 ;
	 assign vga_out_b=rgb[0]? 5'b111_11:0 ;
	 

	 vga_core m0
	(
		.clk(clk_out),  //clock must be 25MHz for 640x480 
		.rst_n(rst_n),
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
    );	
	 
	full_screen_gen m1
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.rx(rx),
		.key(key), //key[0] to move cursor to right,key[1] to move cursor down,key[2] to write new ASCII character to current cursor
		.pixel_x(pixel_x),
		.pixel_y(pixel_y),
		.video_on(video_on),
		.rgb(rgb)
    );
	
	 dcm_25MHz m2
		(// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 );      
	
endmodule
module fibo(
	input clk,rst_n,
	input start,
	input[4:0] i, //limit is until the 31st fibonacci
	output[20:0] fibo,
	output reg done_tick
    );
	//FSM state declarations
	 localparam[1:0] idle=2'd0,
							op=2'd1,
							done=2'd2;
	 reg[1:0] state_reg;
	 reg[20:0] i1,i0;
	 reg[4:0] n;
	 
	 //FSM register operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			i1<=0;
			i0<=0;
			n<=0;
			done_tick=0;
			state_reg<=idle;
		end
		else begin
			done_tick=0;                     
			case(state_reg) 
				idle: if(start) begin
							i1<=1;
							i0<=0;
							n<=i;
							state_reg<=op;
						end
				 op: begin
						if(n==0) begin
							i1<=0;
							state_reg<=done;
						end
						else if(n==1) state_reg<=done;
						else begin
							i1<=i0+i1;
							i0<=i1;
							n<=n-1;
						end				 
					  end
			  done: begin
						done_tick=1;
						state_reg<=idle;
					  end
		  default: state_reg<=idle;		 
			endcase
		end
	 end
	 assign fibo=i1;
endmodule
module fibo_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg start;
	reg [4:0] i;

	// Outputs
	wire [20:0] fibo;
	wire done_tick;

	// Instantiate the Unit Under Test (UUT)
	fibo uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.start(start), 
		.i(i), 
		.fibo(fibo), 
		.done_tick(done_tick)
	);
	always begin
		clk=0;
		#5;
		clk=1;
		#5;
	end
	integer idx,file1;
	initial begin
		// Initialize Inputs
		rst_n = 1;
		start = 0;
		i = 0;
		$display("i -> Fibonacci\n");
		for(idx=0;idx<32;idx=idx+1) begin
		@(negedge clk)
			start=1;
			i=idx;			
			wait(done_tick);
			start=0;
			repeat(5) @(negedge clk);
			$display("%d -> %d",i,fibo);
		end
		$stop;

	end
      
endmodule
module vga_core_800x600(
	input clk,rst_n, //clock must be 50MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		
	 
	 //800x600 parameters
	 localparam HD=800, //Horizontal Display
					HR=64, //Right Border
					HRet=120, //Horizontal Retrace
					HL=56, //Left Border
					
					VD=600, //Vertical Display
					VB=23, //Bottom Border
					VRet=6, //Vertical Retrace
					VT=37; //Top Border
					
	reg[11:0] vctr_q=0,vctr_d; //counter for vertical scan
	reg[11:0] hctr_q=0,hctr_d; //counter for vertical scan
	reg hsync_q=0,hsync_d; //horizontal sync is buffered for a glitchless output
	reg vsync_q=0,vsync_d; //vertical sync is buffered for a glitchless output
	
	//vctr and hctr register operation
	always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			vctr_q<=0;
			hctr_q<=0;
			vsync_q<=0;
			hsync_q<=0;
		end
		else begin
			vctr_q<=vctr_d;
			hctr_q<=hctr_d;
			vsync_q<=vsync_d;
			hsync_q<=hsync_d;
		end
	end
	
	//horizontal and vertical counter logic for horizontal sync and vertical sync
	always @* begin
		vctr_d=vctr_q;
		hctr_d=hctr_q;
		video_on=0;
		hsync_d=1; 
		vsync_d=1; 
		
		if(hctr_q==HD+HR+HRet+HL-1) hctr_d=0; //horizontal counter
		else hctr_d=hctr_q+1'b1;
		
		if(vctr_q==VD+VB+VRet+VT-1) vctr_d=0; //vertical counter
		else if(hctr_q==HD+HR+HRet+HL-1) vctr_d=vctr_q+1'b1;
		
		if(hctr_q<HD && vctr_q<VD) video_on=1; //video_on 
		
		if( (hctr_d>=HD+HR) && (hctr_d<=HD+HR+HRet-1) ) hsync_d=0; //d-input is used as condition (not the present "q")to remove the one-clock delay due to buffering the horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //d-input is used as condition (not the present "q")to remove the one-clock delay due to buffering the vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

endmodule
module debounce_explicit(
	input clk,rst_n,
	input sw,
	output reg db_level,db_tick
    );
	 
	 //FSM symbolic declaration
	 localparam[1:0]  idle=2'b00,
							delay0=2'b01,
							one=2'b10,
							delay1=2'b11;
	 localparam N=21; //21 bits is 42ms -> 2^N/50MHz=42ms
	 reg[1:0] state_reg,state_nxt;
	 reg[N-1:0] timer_reg,timer_nxt;
	 reg timer_zero,timer_inc,timer_tick; //control and status signal
	 
	 //FSM and timer register
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			timer_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			timer_reg<=timer_nxt;
		end
	 end
	 
	 //FSM control path next-state logic
	 always @* begin
		state_nxt=state_reg;
		timer_zero=0;
		timer_inc=0;
		db_tick=0;
		db_level=0;       
		
		case(state_reg)
			  idle: if(sw==1) begin
							timer_zero=1; //load the timer with value of zero
							state_nxt=delay0;
					  end
			delay0: if(sw==1) begin
							timer_inc=1;//increment timer by 1
							if(timer_tick) begin //if timer reaches the max(nxt edge will wrap the timer to zero again)
								state_nxt=one; 
								db_tick=1;
							end
					  end
					  else state_nxt=idle;
		      one: begin
							db_level=1;
							if(sw==0) begin
								timer_zero=1;  //load the timer with value of zero
								state_nxt=delay1;
							end
					  end
		   delay1: begin
							db_level=1;
							if(sw==0) begin
								timer_inc=1;
								if(timer_tick) //if timer reaches the max(wherein the nxt edge will wrap the timer to zero again)
									state_nxt=idle;
							end
							else state_nxt=one;
					   end
			 default: state_nxt=idle;
			endcase					
		end
		
		//Datapath(timer) logic and operation
		always @* begin
			timer_nxt=timer_reg;
			if(timer_zero) timer_nxt=0; //load zero 
			else if(timer_inc) timer_nxt=timer_reg+1; //increment by one
			timer_tick=(timer_reg=={N{1'b1}})?1:0; //notify if timer is already at max
		end


endmodule
module top_module(
	input clk,rst_n,
	input key, //swicthes between VGA(640x480) and SVGA(800x600) modes
	output reg vga_out_vs,vga_out_hs,
	output[4:0] vga_out_r,
	output[5:0] vga_out_g,
	output[4:0] vga_out_b
    );
	 
	 wire key_tick;
	 reg video_on;
	 reg[11:0] pixel_x,pixel_y;
	 
	 wire a_hsynx,a_vsync,a_video_on;
	 wire[11:0] a_pixel_x,a_pixel_y;
	 wire b_hsynx,b_vsync,b_video_on;
	 wire[11:0] b_pixel_x,b_pixel_y;
	 
	 reg vga_q=0; //switch between VGA and SVGA
	 
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) vga_q<=0;
		else if(key_tick) vga_q<=!vga_q;
	 end
	 
	 //logic for alternating the output resolution
	 always @* begin
		if(vga_q) begin
			vga_out_vs=a_vsync;
			vga_out_hs=a_hsync;
			video_on=a_video_on;
			pixel_x=a_pixel_x;
			pixel_y=a_pixel_y;
		end
		else begin
			vga_out_vs=b_vsync;
			vga_out_hs=b_hsync;
			video_on=b_video_on;
			pixel_x=b_pixel_x;
			pixel_y=b_pixel_y;
		end
	 end


	 clk_25MHz m0
   (// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 ); 
	 
	 vga_core_640x480 m1
	 (
		.clk(clk_out), //clock must be 25MHz for 640x480 
		.rst_n(rst_n), 
		.hsync(a_hsync),
		.vsync(a_vsync),
		.video_on(a_video_on),
		.pixel_x(a_pixel_x),
		.pixel_y(a_pixel_y)
    );	
	 
	  vga_core_800x600 m2
	 (
		.clk(clk),
		.rst_n(rst_n), //clock must be 50MHz for 640x480 
		.hsync(b_hsync),
		.vsync(b_vsync),
		.video_on(b_video_on),
		.pixel_x(b_pixel_x),
		.pixel_y(b_pixel_y)
    );
	 
	debounce_explicit m3
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw(key),
		.db_level(),
		.db_tick(key_tick)
    );
	 
	 grid_pixel m4 //generates 100x100 grid pixel pattern
	(
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y),
		.r(vga_out_r),
		.g(vga_out_g),
		.b(vga_out_b)
	);
endmodule
module vga_core_640x480(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		
	 //640x480 parameters
	 localparam HD=640, //Horizontal Display
					HR=16, //Right Border
					HRet=96, //Horizontal Retrace
					HL=48, //Left Border
					
					VD=480, //Vertical Display
					VB=10, //Bottom Border
					VRet=2, //Vertical Retrace
					VT=33; //Top Border
					
	reg[11:0] vctr_q=0,vctr_d; //counter for vertical scan
	reg[11:0] hctr_q=0,hctr_d; //counter for vertical scan
	reg hsync_q=0,hsync_d; //horizontal sync is buffered for a glitchless output
	reg vsync_q=0,vsync_d; //vertical sync is buffered for a glitchless output
	
	
	//vctr and hctr register operation
	always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			vctr_q<=0;
			hctr_q<=0;
			vsync_q<=0;
			hsync_q<=0;
		end
		else begin
			vctr_q<=vctr_d;
			hctr_q<=hctr_d;
			vsync_q<=vsync_d;
			hsync_q<=hsync_d;
		end
	end
	
	//horizontal and vertical counter logic for horizontal sync and vertical sync
	always @* begin
		vctr_d=vctr_q;
		hctr_d=hctr_q;
		video_on=0;
		hsync_d=1; 
		vsync_d=1; 
		
		if(hctr_q==HD+HR+HRet+HL-1) hctr_d=0; //horizontal counter
		else hctr_d=hctr_q+1'b1;
		
		if(vctr_q==VD+VB+VRet+VT-1) vctr_d=0; //vertical counter
		else if(hctr_q==HD+HR+HRet+HL-1) vctr_d=vctr_q+1'b1;
		
		if(hctr_q<HD && vctr_q<VD) video_on=1; //video_on 
		
		if( (hctr_d>=HD+HR) && (hctr_d<=HD+HR+HRet-1) ) hsync_d=0;  //d-input is used as condition (not the present "q")to remove the one-clock delay due to buffering the horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //d-input is used as condition (not the present "q")to remove the one-clock delay due to buffering the vertical sync 
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

endmodule
module top_pong_animated
	(
		input clk, rst_n,
		input[1:0] key, //key[1] to move down,key[0] to move up
		output[4:0] vga_out_r,
		output[5:0] vga_out_g,
		output[4:0] vga_out_b,
		output vga_out_vs,vga_out_hs
    );
	 
	wire clk_out;
	wire video_on;
	wire[11:0] pixel_x,pixel_y;
	dcm_25MHz m0
   (// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 );
	 
	 vga_core m1  //clock must be 25MHz for 640x480 
	(
		.clk(clk_out),
		.rst_n(rst_n), 
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
    );
	 
	 pong_animated m2 //classic pong game but with breakable "bricks" rather than wall
	 (
		.clk(clk_out),
		.rst_n(rst_n),
		.key(key),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y),
		.r(vga_out_r),
		.g(vga_out_g),
		.b(vga_out_b)
    );	
	 
	 
	 
endmodule
module LED_mux
	#(parameter N=19) //last 3 bits will be used as output. Frequency=50MHz/(2^(N-3)). So N=19 will have 763Hz
	(
	input clk,rst,
	input[7:0] in0,in1,in2,in3,in4,in5, 
	output [7:0] seg_out,
	output reg[5:0] sel_out
    );
	 
	 
	 reg[N-1:0] r_reg=0;
	 reg[7:0] hex_out=0;
	 wire[N-1:0] r_nxt;
	 wire[2:0] out_counter; //last 3 bits to be used as output signal
	 
	 
	 //N-bit counter
	 always @(posedge clk,negedge rst)
	 if(!rst) r_reg<=0;
	 else r_reg<=r_nxt;
	 
	 assign r_nxt=(r_reg=={3'd5,{(N-3){1'b1}}})?19'd0:r_reg+1'b1; //last 3 bits counts from 0 to 5(6 turns) then wraps around
	 assign out_counter=r_reg[N-1:N-3];
	 
	 
	 //sel_out output logic
	 always @(out_counter) begin
		 sel_out=6'b111_111;    //active low
		 sel_out[out_counter]=1'b0;
	 end
	  
	 //hex_out output logic
	 always @* begin
		 hex_out=0;
			 casez(out_counter)
			 3'b000: hex_out=in0;
			 3'b001: hex_out=in1;
			 3'b010: hex_out=in2;
			 3'b011: hex_out=in3;
			 3'b100: hex_out=in4;
			 3'b101: hex_out=in5;
			 endcase
	 end
	 
	 assign seg_out=hex_out;
	 	

		
endmodule
module heartbeat_TB;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire [7:0] in0;
	wire [7:0] in1;
	wire [7:0] in2;
	wire [7:0] in3;
	wire [7:0] in4;
	wire [7:0] in5;

	// Instantiate the Unit Under Test (UUT)
	heartbeat 
	#(.turns(10)) uut // (base clock is 100MHz -> 100MHz/10 =10Mhz) 10Mhz frequency per pattern  OR 100ns per pattern
	(
		.clk(clk), 
		.rst_n(rst_n), 
		.in0(in0), 
		.in1(in1), 
		.in2(in2), 
		.in3(in3), 
		.in4(in4), 
		.in5(in5)
	);
	
	always begin
	clk=1'b1;
	#5;
	clk=1'b0;
	#5;
	end

	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 1;
		

	end
      
endmodule
module heartbeat
	#(parameter turns=5_000_000) //// 50MHz/turns = 50MHz/5_000_000 = 10Hz(100ms) per pattern or 600ms per beat
	(
	input clk,rst_n,
	output reg[7:0] in0,in1,in2,in3,in4,in5
    );
	 
	 reg[23:0] mod_turns=0; // counter to determine the duration between patterns of beats
	 reg[2:0] mod_6=0; //counts 0-to-3(4 turns) since there are 4 patterns per rotation then rest from 4-to-5  SO THAT THE HEARTBEAT WILL BE REALISTIC
	 wire[23:0] mod_turns_nxt;
	 wire[2:0] mod_6_nxt;
	 wire mod_turns_max;
	 
	 //registers
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			mod_turns<=0;
			mod_6<=0;
		end
		else begin
			mod_turns<=mod_turns_nxt;
			mod_6<=mod_6_nxt;
		end
	 end
	 

	 
	 //next-state logics
	 assign mod_turns_nxt=(mod_turns==turns-1)?0:mod_turns+1;
	 assign mod_turns_max=(mod_turns==turns-1)?1:0;
	 assign mod_6_nxt=mod_turns_max? ((mod_6==5)?0:mod_6+1) :mod_6;
	 
	 //mod_6 determines what segment is "on" and what pattern is on that segment
	 always @* begin
	 in0=8'hff; in1=8'hff; in2=8'hff; in3=8'hff; in4=8'hff; in5=8'hff; //default off
		 case(mod_6)
		 2'd0: begin in3=8'b1_1001_111; in2=8'b1_1111_001; end //first pattern of heartbeat 
		 2'd1: begin in3=8'b1_1111_001; in2=8'b1_1001_111; end //second pattern of heartbeat
		 2'd2: begin in4=8'b1_1111_001; in1=8'b1_1001_111; end //third pattern of heartbeat
		 2'd3: begin in5=8'b1_1111_001; in0=8'b1_1001_111; end //fourth pattern of heartbeat
		 //rest on 4 and 5
		 endcase
	 end
	 
endmodule
module heartbeat_TEST
	(
	input clk,rst_n,
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 wire [7:0] in0,in1,in2,in3,in4,in5;
	 
	 heartbeat #(.turns(6_000_000)) //0.120 sec per pattern = 0.720 sec per heartbeat
	 heartbeat_m0
		(
		.clk(clk),
		.rst_n(rst_n),
		.in0(in0),
		.in1(in1),
		.in2(in2),
		.in3(in3),
		.in4(in4),
		.in5(in5)
		 );
	 LED_mux led_mux_m0
		(
		.clk(clk),
		.rst(rst_n),
		.in0(in0),
		.in1(in1),
		.in2(in2),
		.in3(in3),
		.in4(in4),
		.in5(in5),
		.seg_out(seg_out),
		.sel_out(sel_out)
		 );


endmodule
module mouse_test(
	input clk,rst_n,
	input key0,key1,
	inout ps2d,ps2c,
	output[7:0] seg_out,
	output[5:0] sel_out	
    );
	 reg [10:0] xcounter_reg,xcounter_nxt; //3 MSBs serve as index for the 6 seven-segments(movement of x-axis)
	 reg [10:0] ycounter_reg,ycounter_nxt; //4 MSBs serve as index for the counter displayed on the seven segment(movement of the y-axis)
	 reg[5:0] in0,in1,in2,in3,in4,in5;
	 wire[8:0] x,y;
	 wire[2:0] btn;
	 wire m_done_tick;
	mouse m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.key0(key0),
		.key1(key1),
		.ps2c(ps2c),
		.ps2d(ps2d),
		.x(x),
		.y(y),
		.btn(btn),
		.m_done_tick(m_done_tick)
    );
	 LED_mux m1
	(
		.clk(clk),
		.rst(rst_n), 
		.in0(in0),
		.in1(in1),
		.in2(in2),
		.in3(in3),
		.in4(in4),
		.in5(in5), //format: {dp,char[4:0]} , dp is active high
		.seg_out(seg_out),
		.sel_out(sel_out)
    );
	 //logic for the counter of x and y-axis movement
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			xcounter_reg<=0;
			ycounter_reg<=0;
		end
		else begin
			xcounter_reg<=xcounter_nxt;
			ycounter_reg<=ycounter_nxt;			
		end
	 end
	 
	 always @* begin
		 xcounter_nxt=xcounter_reg;
		 ycounter_nxt=ycounter_reg;
		 in0=6'd28; //code for off-seven segment
		 in1=6'd28;
		 in2=6'd28;
		 in3=6'd28;
		 in4=6'd28;
		 in5=6'd28;
		 
			if(m_done_tick) begin
				if(btn[1]) xcounter_nxt={3'b101,8'd0};//right button pushed=rightmost seven-segment on
				else if(btn[0]) xcounter_nxt=0;//left button pushed=leftmost seven-segment on
				else begin //increment counter based on x-axis and y-axis movement
					xcounter_nxt=(x[8]==1)? xcounter_reg-{~{x[7:0]}}+1 : xcounter_reg+x[7:0];
					ycounter_nxt=(y[8]==1)? ycounter_reg-{~{y[7:0]}}+1 : ycounter_reg+y[7:0];
					
					if(xcounter_nxt[10:8]==3'd6) xcounter_nxt[10:8]=3'd0;
					else if(xcounter_nxt[10:8]==3'd7) xcounter_nxt[10:8]=3'd5;
					if(ycounter_nxt[10:7]==4'd10) ycounter_nxt[10:7]=4'd0;
					else if(ycounter_nxt[10:7]==4'd15) ycounter_nxt[10:7]=4'd9;
				end
			end
			case(xcounter_nxt[10:8]) //chooses which seven-segment will display the y movement counter
				3'd0: in5={2'd0,ycounter_nxt[10:7]};
				3'd1: in4={2'd0,ycounter_nxt[10:7]};
				3'd2: in3={2'd0,ycounter_nxt[10:7]};
				3'd3: in2={2'd0,ycounter_nxt[10:7]};
				3'd4: in1={2'd0,ycounter_nxt[10:7]};
				3'd5: in0={2'd0,ycounter_nxt[10:7]};
			endcase
			
	 end
	



endmodule
module mouse(
	input clk,rst_n,
	input key0,key1, 
	inout ps2c,ps2d,
	output[8:0] x,y,
	output[2:0] btn,
	output reg m_done_tick
    );
	 
	 //FSM state-declarations
	 localparam[2:0] idle=3'd0,
							response=3'd1,
							byte1=3'd2,
							byte2=3'd3,
							byte3=3'd4,
							done=3'd5,
							reset=3'd6,
							rest=3'd7;
	 reg[2:0] state_reg,state_nxt;
	 reg[8:0] x_reg,x_nxt;
	 reg[8:0] y_reg,y_nxt;
	 reg[2:0] btn_reg,btn_nxt;
	 reg[7:0] din;
	 reg wr_ps2;
	 wire key0_tick,key1_tick;
	 wire[7:0] rx_data;
	 wire[10:0] dout;
	 wire rx_done_tick,tx_done_tick;
	 
	 //FSM register operations
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			x_reg<=0;
			y_reg<=0;
			btn_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			x_reg<=x_nxt;
			y_reg<=y_nxt;
			btn_reg<=btn_nxt;
		end
	 end
	 
	 //FSM next-state logics
	 always @* begin
		state_nxt=state_reg;
		x_nxt=x_reg;
		y_nxt=y_reg;
		btn_nxt=btn_reg;
		wr_ps2=0;
		m_done_tick=0;
		din=0;
		if(key1_tick) state_nxt=reset;
		else if(key0_tick) state_nxt=idle;
		else begin
			case(state_reg)
					idle: begin //transmit code F4 for enable stream
								din=8'hf4;
								wr_ps2=1;
								if(tx_done_tick==1) state_nxt=response;
							end
				response: if(rx_done_tick==1) state_nxt=byte1;//wait for the acknowledge response FE
				  byte1: if(rx_done_tick==1) begin //first packet
								x_nxt[8]=rx_data[5]; //4
								y_nxt[8]=rx_data[6]; //5
								btn_nxt=rx_data[3:1]; //2:0
								state_nxt=byte2;
							end
				  byte2: if(rx_done_tick==1) begin //2nd packet
								x_nxt[7:0]=rx_data;
								state_nxt=byte3;
							end
				  byte3: if(rx_done_tick==1) begin //3rd packet
								y_nxt[7:0]=rx_data;
								state_nxt=done;
							end
					done: begin
								m_done_tick=1;
								state_nxt=byte1;
							end
				  reset: begin
								din=8'hff;
								wr_ps2=1;
								state_nxt=rest;
							end
				   rest: state_nxt=rest;
				default: state_nxt=idle;
			endcase
		end
	 end
	 
	ps2_rxtx m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.din(din), //transmitted data is always F4(enable stream mode of mouse)
		.wr_ps2(wr_ps2),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.dout(dout), //11bit-data received from rx
		.rx_done_tick(rx_done_tick),
		.tx_done_tick(tx_done_tick)
    );
	 assign rx_data=dout[8:1]; //real data extracted(no start,parity,and stop bits)
	 
	 assign x=x_reg;
	 assign y=y_reg;
	assign btn=btn_reg;
	
	debounce_explicit m1(
		.clk(clk),
		.rst_n(rst_n),
		.sw({!key0}),
		.db_level(),
		.db_tick(key0_tick)
    );
	 
	debounce_explicit m2(
		.clk(clk),
		.rst_n(rst_n),
		.sw({!key1}),
		.db_level(),
		.db_tick(key1_tick)
    );


	 
	
	


endmodule
module fp_greaterthan_TB;

	// Inputs
	reg [12:0] first;
	reg [12:0] second;

	// Outputs
	wire gt;
	reg[11:0] i=12'b0;

	// Instantiate the Unit Under Test (UUT)
	fp_greaterthan uut (
		.first(first), 
		.second(second), 
		.gt(gt)
	);

	initial begin
		// Initialize Inputs
		first = 0;
		second = 0;

		// Wait 100 ns for global reset to finish
		#100;

		for(i={12{1'b1}};i>0;i=i-1) begin  //test consecutive numbers
		#5 first={1'b0,i};      //pos-pos so gt is always equal to 1        
			second={1'b0,i-1'b1};             
		#5 first={1'b1,i};      //neg-pos so gt is always equal to 0		
			second={1'b0,i-1'b1};
		#5 first={1'b0,i};      //pos-neg so gt is always equal to 1
			second={1'b1,i-1'b1};
		#5 first={1'b1,i};      //neg-neg so gt is always equal to 0
			second={1'b1,i-1'b1};
		#2 $display(" ");
		end
	end
	
	initial begin
	$display("first         second        gt");
	$monitor("%b %b %d",first,second,gt);
	end
	initial begin
	#21000 $finish;
	end
	
      
endmodule
module fp_greaterthan(
	input wire[12:0] first,second,
	output reg gt
    );
	 always @* begin
	 gt=1'b0;
	 if(!first[12] && !second[12] && first[11:0]>second[11:0] ) gt=1'b1;  //if first and second are both positive
	 else if(first[12] && second[12] && first[11:0]<second[11:0]) gt=1'b1; //if first and second are both negative
	 else if(!first[12] && second[12]) gt=1'b1; //if first is positive and second is negative
	 end 


endmodule
module bcd2bin_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg start;
	reg [3:0] dig1;
	reg [3:0] dig0;

	// Outputs
	wire [6:0] bin;
	wire ready;
	wire done_tick;
	integer i;
	// Instantiate the Unit Under Test (UUT)
	bcd2bin uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.start(start), 
		.dig1(dig1), 
		.dig0(dig0), 
		.bin(bin), 
		.ready(ready), 
		.done_tick(done_tick)
	);
	always begin
		clk=0;
		#5;
		clk=1;
		#5;
	end

	initial begin
		// Initialize Inputs

		rst_n = 1;
		start = 0;
		dig1 = 0;
		dig0 = 0;
		@(negedge clk); //reset
		rst_n=0;
		@(negedge clk);
		rst_n=1;
		@(negedge clk);
		$display("BCD_input   Binary_output(Decimal_value)");
		for(i=0;i<=99;i=i+1) begin
			start=1;
			dig1=i/10; //second digit of i
			dig0=i-dig1*10; //first digit of i
			wait(done_tick);
			start=0;
			$display("     %0d          %b(%0d)",i,bin,bin);
			repeat(5)@(negedge clk);
		end
		$stop;
		
	end
      
endmodule
module baud_generator
	(
	input clk,rst_n,
	input[11:0] baud_dvsr, //2605 for 12000baud , 1303 for 2400baud , 652 for 4800baud , 326 for 9600baud , 162 for 19200 , 27 for 115200
	output reg s_tick
    );
	 reg[11:0] counter=0;
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) counter<=0;
		else begin
			s_tick=0;
			if(counter==baud_dvsr-1) begin
				s_tick=1;
				counter<=0;
			end
			else begin
				counter<=counter+1;
			end
			
		end
	 end
	 
endmodule
module uart_test(
	input clk,rst_n,
	input btn0,btn1,btn2,
	input rx,
	output tx,
	output[7:0] seg_out,
	output[5:0] sel_out,
	output[3:0] led
    );
	 wire btn2_tick;
	 wire[7:0] wr_data,rd_data;
	 wire rx_empty,tx_empty;
	 
	 top_module m0
	 (
		.clk(clk),
		.rst_n(rst_n),
		.btn0(btn0),
		.btn1(btn1), //btn0=choose_key , btn1=enter_key 
		.rx(rx), 
		.rd_uart(btn2_tick),
		.wr_uart(btn2_tick),
		.wr_data(wr_data),
		.rd_data(rd_data),
		.tx(tx),
		.rx_empty(rx_empty),
		.tx_empty(tx_empty),
		.seg_out(seg_out),
		.sel_out(sel_out)
    );
	 
	 debounce_explicit m1
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw({!btn2}),
		.db_level(),
		.db_tick(btn2_tick)
    );
	 
	 assign wr_data=rd_data+1; //just add 1 to the value received then transmit it back
	 assign led={4{rx_empty}};
	 


endmodule
module ascii_conv( //converts the real data from kb module to ASCII
	input[7:0] rd_data,
	output reg[7:0] ascii
    );
 always @* begin
		ascii=0;
		case(rd_data)
			8'h45: ascii = 8'h30; //0
			8'h16: ascii = 8'h31; //1
			8'h1e: ascii = 8'h32; //2
			8'h26: ascii = 8'h33; //3
			8'h25: ascii = 8'h34; //4
			8'h2e: ascii = 8'h35; //5
			8'h36: ascii = 8'h36; //6
			8'h3d: ascii = 8'h37; //7
			8'h3e: ascii = 8'h38; //8
			8'h46: ascii = 8'h39; //9
			
			8'h1c: ascii = 8'h41; //A
			8'h32: ascii = 8'h42; //B
			8'h21: ascii = 8'h43; //C
			8'h23: ascii = 8'h44; //D
			8'h24: ascii = 8'h45; //E
			8'h2b: ascii = 8'h46; //F
			8'h34: ascii = 8'h47; //G
			8'h33: ascii = 8'h48; //H
			8'h43: ascii = 8'h49; //I
			8'h3b: ascii = 8'h4a; //J
			8'h42: ascii = 8'h4b; //K
			8'h4b: ascii = 8'h4c; //L
			8'h3a: ascii = 8'h4d; //M
			8'h31: ascii = 8'h4e; //N
			8'h44: ascii = 8'h4f; //O
			8'h4d: ascii = 8'h50; //P
			8'h15: ascii = 8'h51; //Q
			8'h2d: ascii = 8'h52; //R
			8'h1b: ascii = 8'h53; //S
			8'h2c: ascii = 8'h54; //T
			8'h3c: ascii = 8'h55; //U
			8'h2a: ascii = 8'h56; //V
			8'h1d: ascii = 8'h57; //W
			8'h22: ascii = 8'h58; //X
			8'h35: ascii = 8'h59; //Y
			8'h1a: ascii = 8'h5a; //Z
			
			8'h0e: ascii = 8'h60; // `
			8'h4e: ascii = 8'h2d; // - 
			8'h55: ascii = 8'h3d; // =
			8'h54: ascii = 8'h5b; // [
			8'h5b: ascii = 8'h5d; // ]
			8'h5d: ascii = 8'h5c; // \
			8'h4c: ascii = 8'h3b; // ;
			8'h52: ascii = 8'h27; // '
			8'h41: ascii = 8'h2c; // ,
			8'h49: ascii = 8'h2e; // .
			8'h4a: ascii = 8'h2f; // /
			
			8'h29: ascii = 8'h20; //Y
			8'h5a: ascii = 8'h0d; //Z 
			8'h66: ascii = 8'h08; //Z 
			default: ascii = 8'h2a;
			
		endcase
	 end

endmodule
module kb(   //extract only the real bytes from received packets of data(no break code)
	input clk,rst_n,
	input ps2d,ps2c,
	input rd_fifo,
	output [7:0] rd_data,
	output fifo_empty
    );
	 wire[10:0] dout;
	 wire rx_dont_tick;
	 wire wr;
	 wire [7:0] wr_data;
	 
 
	 ps2_rx m0 //receive packets from ps2 keyboard
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_en(1),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.dout(dout),
		.rx_done_tick(rx_done_tick)
    );
	 
	 kb_data m1 //extract the real data from the packets(the hex f0(break code) is removed)
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_done_tick(rx_done_tick),
		.din(dout[8:1]),
		.wr(wr),
		.wr_data(wr_data)
    );
	 
	  fifo #(.W(4),.B(8)) m2 //store the packets of data
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(wr),
		.rd(rd_fifo), 
		.wr_data(wr_data),
		.rd_data(rd_data),
		.full(),
		.empty(fifo_empty) 
    );
	 
endmodule
module kb_test(
	input clk,rst_n,
	input ps2d,ps2c,
	output tx
    );
	 wire rd_fifo;
	 wire[7:0] rd_data,ascii;
	 wire fifo_empty;
	 kb m0 //extract only the real bytes(only the make code,no break code) from received packets of data. Data is stored at fifo waiting to be read
	 (
		.clk(clk),
		.rst_n(rst_n),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.rd_fifo({!fifo_empty}),
		.rd_data(rd_data),
		.fifo_empty(fifo_empty) 
    );
	 
	 ascii_conv m1 //converts data from "kb" module to ASCII
	 (
		.rd_data(rd_data),
		.ascii(ascii)
    );
	 
	 uart #(.DBIT(8),.SB_TICK(16),.DVSR(326),.DVSR_WIDTH(9),.FIFO_W(4)) m2//baudrate=9600  transfers the ASCII to pc
	(
		.clk(clk),
		.rst_n(rst_n),
		.rd_uart(0),
		.wr_uart({!fifo_empty}),
		.wr_data(ascii),
		.rx(1),
		.tx(tx),
		.rd_data(),
		.rx_empty(),
		.tx_full()
    );
	 



endmodule
module kb_data(
	input clk,rst_n,
	input rx_done_tick,
	input[7:0] din,
	output reg wr,
	output reg[7:0] wr_data
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							scan=2'd1,
							breakcode=2'd3;
	 reg[1:0] state_reg;
	 //FSM register operations
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) state_reg<=idle;
		
		else begin
		wr=0;
		wr_data=0;
			case(state_reg)
				idle: if(rx_done_tick) begin //wait for the makecode
							if(din==8'hf0) state_reg<=breakcode;
							else begin
								wr_data=din;
								wr=1;
								state_reg<=scan;
							end							
						 end
				scan: if(rx_done_tick) begin //wait for the breakcode which starts with 8'hf0
							if(din==8'hf0) state_reg<=breakcode;
							else begin
								wr_data=din;
								wr=1;
							end
						end
		 breakcode: if(rx_done_tick) state_reg<=idle;	//skip the makecode after the breakcode 8'hf0 						
			endcase
		end
	 end
	 


endmodule
module debouncing_TEST(
	input clk,rst_n,
	input sw, //active low
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 
	 reg[3:0] counter_db=0,counter_sw=0; //counts from 0-to-9 then wraps up
	 reg sw_reg=0,db_reg=0;
	 wire[3:0] counter_db_nxt,counter_sw_nxt;
	 wire db,tick_db,tick_sw;
	 
	 //debounce module instantiation
	early_debounce debounce_module
	(
	.clk(clk),
	.rst_n(rst_n),
	.sw_low(sw), //active low
	.db(db) //active high output
    );
	 
	 //rising-edge-detection and 10-mod-counter circuit
	 always@(posedge clk,negedge rst_n) begin
		if(!rst_n) begin 
			sw_reg<=0;
			db_reg<=0;
			counter_db<=0;
			counter_sw<=0;
			
		end
		else begin
			sw_reg<=sw;
			db_reg<=db;
			counter_db<=counter_db_nxt;
			counter_sw<=counter_sw_nxt;
		end
	 end
	 assign tick_db=(db && !db_reg);
	 assign tick_sw=(!sw && sw_reg);
	 assign counter_db_nxt=tick_db?((counter_db==9)?0:counter_db+1):counter_db; //increment if tick is asserted(or when rising edge signal occurs)
	 assign counter_sw_nxt=tick_sw?((counter_sw==9)?0:counter_sw+1):counter_sw; //increment if tick is asserted(or when rising edge signal occurs)
	 
	 //Seven-segment-TIME-MUX Circuit
		LED_mux led_mux
		(
		.clk(clk),
		.rst(rst_n),
		.in0({1'b0,counter_db}),
		.in1({1'b1,counter_sw}),
		.in2(0),
		.in3(0),
		.in4(0),
		.in5(0),
		.seg_out(seg_out),
		.sel_out(sel_out)
		 );

endmodule
module early_debounce(
	input clk,rst_n,
	input sw_low,//active low input
	output reg db //active high output
    );
	 //FSM declarations
	 localparam[2:0] start=3'd0,
						  one=3'd1,
						  delay1=3'd2,
						  delay2=3'd3,
						  zero=3'd4,
						  delay3=3'd5;
	 reg[2:0] state_reg,state_nxt;
	 
	 //20-ms counter delarations
	 localparam N=21; // 2^N/50MHz=2^20/50MHz=20.97ms period
	 reg[N-1:0] counter_reg=0;
	 wire tick;
	 wire level=!sw_low;
	 //FSM and 20ms-counter register operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=start;
			counter_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			counter_reg<=counter_reg+1;
		end
	 end
	assign tick=(counter_reg==0); //ticks at the end of every 20.97ms
	 
	 
	 //FSM next-state and output logic
	 always @* begin
		state_nxt=state_reg;
		db=0;
		case(state_reg)
			 start: if(level) state_nxt=one; //rising edge
				one: begin   //wait for 20ms
							db=1;
							if(tick) state_nxt=delay1;
					  end
			delay1: begin //wait for 20ms
						db=1;
						if(tick) state_nxt=delay2;
					  end
			delay2: begin
						 db=1;
						 if(!level) state_nxt=zero; //wait here until falling edge comes
					  end
			  zero: if(tick) state_nxt=delay3;
			delay3: if(tick) state_nxt=start;
			default: state_nxt=start;						
		endcase
	 end

endmodule
module debouncing_button_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg sw_low;

	// Outputs
	wire db;

	// Instantiate the Unit Under Test (UUT)
	early_debounce uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.sw_low(sw_low), 
		.db(db)
	);
	always begin //100MHz -> 2^1/100MHz= 20ns
	clk=1'b1;
	#5;
	clk=1'b0;
	#5;
	end

	initial begin
		// Initialize Inputs
		rst_n = 1;

		sw_low=1;
		#100 sw_low=0;
		#200 sw_low=1;
		#100 sw_low=0;
		#20 sw_low=1;
		#100 $stop;		
	
	end
      
endmodule
module mouse_test(
	input clk,rst_n,
	input key0,key1,
	inout ps2d,ps2c,
	output reg[3:0] led	
    );
	 reg [10:0] counter_reg,counter_nxt; //2 MSBs serve as index for the 4 leds
	 wire[8:0] x;
	 wire[2:0] btn;
	 wire m_done_tick;
	 //module instantiations
	mouse m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.key0(key0), //key0 will transmit code for enabling the stream mode
		.key1(key1), //key1 will reset the mouse and dosable stream  mode
		.ps2c(ps2c),
		.ps2d(ps2d),
		.x(x),
		.y(),
		.btn(btn),
		.m_done_tick(m_done_tick)
    );
	 
	 //logic for the running leds(led will follow the x-axis movememt)
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) counter_reg<=0;
		else counter_reg<=counter_nxt;
	 end
	 
	 always @* begin
		 counter_nxt=counter_reg;
		 led=4'd0;
			if(m_done_tick) begin
				if(btn[1]) counter_nxt=12'hfff;//right button pushed
				else if(btn[0]) counter_nxt=0;//left button pushed
				else begin //increment/decrement counter based on x-axis movement
					counter_nxt=(x[8]==1)? counter_reg-{~{x[7:0]}}+1 : counter_reg+x[7:0]; //note: moving left will produce a 2s complement number
				end
			end
			case(counter_reg[10:9]) 
				2'b00: led[0]=1;//leftmost
				2'b01: led[1]=1;
				2'b10: led[2]=1;
				2'b11: led[3]=1; //rightmost
				default: led[2:1]=2'b11;
			endcase
	 end
	



endmodule
module monitor
	#(parameter N=3)
	(
	input clk,rst_n,
	input syn_clr,load,en,up,
	input[N-1:0] d,
	input[N-1:0] q,
	input max_tick,min_tick
    );
	 reg syn_clr_reg,load_reg,en_reg,up_reg,rst_reg;
	 reg[N-1:0] d_reg,result,q_reg;
	 reg[39:0] msg;
	 initial begin
		$display("time sync_clr/load/en/up q result msg");
	 end
	 always @(posedge clk) begin
		syn_clr_reg<=syn_clr;
		load_reg<=load;
		en_reg<=en;
		up_reg<=up;
		d_reg<=d;
		q_reg<=q;
		rst_reg<=1;
		msg=(result===q)?" ":"ERROR";
		$strobe("%0d %b%b%b%b %0d %0d %s",$time,syn_clr,load,en,up,q,result,msg);
	 end
	 
	 always @* begin
		if(!rst_n) rst_reg=0;
		if(!rst_reg) result=0;
		else begin
			if(syn_clr_reg) result=0;
			else if(load_reg) result=d;
			else if(en_reg && up_reg) result=q_reg+1;
			else if(en_reg && !up_reg) result=q_reg-1;
			else result=q_reg;
		end
	 end
	 
endmodule
module universal_binary_counter_TB;

	// Inputs
	wire clk;
	wire rst_n;
	wire syn_clr;
	wire load;
	wire en;
	wire up;
	wire[2:0] d;

	// Outputs
	wire [2:0] q;
	wire max_tick;
	wire min_tick;

	// Instantiate the Unit Under Test (UUT)
	universal_binary_counter #(.N(3)) uut1 
	(
		.clk(clk), 
		.rst_n(rst_n), 
		.syn_clr(syn_clr), 
		.load(load), 
		.en(en), 
		.up(up), 
		.d(d), 
		.q(q), 
		.max_tick(max_tick), 
		.min_tick(min_tick)
	);
	
	 test_vector #(.N(3),.T(20)) uut2
	(
		.clk(clk),
		.rst_n(rst_n),
		.syn_clr(syn_clr),
		.load(load),
		.en(en),
		.up(up),
		.d(d)
    );
	 
	 monitor #(.N(3)) uut3
	(
		.clk(clk),
		.rst_n(rst_n),
		.syn_clr(syn_clr),
		.load(load),
		.en(en),
		.up(up),
		.d(d),
		.q(q),
		.max_tick(max_tick),
		.min_tick(min_tick)
    );
    
endmodule
module universal_binary_counter
	#(parameter N=3)
	(
		input clk,rst_n,
		input syn_clr,load,en,up,
		input[N-1:0] d,
		output reg[N-1:0] q,
		output max_tick,min_tick	
    );//register plus next-state logics
	 initial q=0;
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) q<=0;
		else if(syn_clr) q<=0;
		else if(load) q<=d;
		else if(en && up) q<=q+1;
		else if(en && ~up) q<=q-1;
	 end
	assign max_tick=(q=={N{1'b1}})?1:0;
	assign min_tick=(q==0)?1:0;

endmodule
module test_vector
	#(parameter N=3,T=20)
	(
	output reg clk,rst_n,
	output reg syn_clr,load,en,up,
	output reg[N-1:0] d
    );
	 
	 always begin
		clk=0;
		#(T/2);
		clk=1;
		#(T/2);
	 end
	 
	 initial begin
		initialize(); 
		counting(10,1); //count up for 10 cycles(0-7-2)
		load_data(5); //load 5
		counting (7,0); //count down for 7 cycles(7-0-6)
		_syn_clr(); //clear
		counting(4,1); //count up for 4 cycles (0-4);
		asyn_clr(); //rst
		load_data(7); //load 7
		counting(7,0) ; //count down for 7 cycles (7-0)		
		$stop;
	 end
	 
	 task initialize(); begin //initialize value
		@(negedge clk);
		rst_n=1;
		syn_clr=0;
		load=0;
		en=0;
		up=0;
		d=0;
	 end
	 endtask
	 
	 task asyn_clr(); begin //reset
		@(negedge clk);
		rst_n=0;
		#(T/4);
		rst_n=1;
	 end
	 endtask
	 
	 task _syn_clr(); begin
		@(negedge clk);
		syn_clr=1;
		@(negedge clk);
		syn_clr=0;
	 end
	 endtask
	 
	 task load_data(input integer n); begin //load value
		@(negedge clk);
		load=1;
		d=n;
		@(negedge clk);
		load=0;
	 end
	 endtask
	 
	 task counting(input integer count,input updown); begin //count up/down
		@(negedge clk);
		en=1;
		up=updown;
		repeat(count) @(negedge clk);
		en=0;
	 end
	 endtask

	 
	 









endmodule
module kb_banner(
	input clk,rst_n,
	input ps2d,ps2c,
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 
	wire[4:0] in0,in1,in2,in3,in4,in5;
	
	rotating_LED m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.in0(in0),
		.in1(in1),
		.in2(in2),
		.in3(in3),
		.in4(in4),
		.in5(in5) //{decimalpoint,hexadecimal}
    );
	 
	LED_mux m1
	(
		.clk(clk),
		.rst(rst_n),
		.in0({1'b0,in0}),
		.in1({1'b0,in1}),
		.in2({1'b0,in2}),
		.in3({1'b0,in3}),
		.in4({1'b0,in4}),
		.in5({1'b0,in5}),
		.seg_out(seg_out),
		.sel_out(sel_out)
    );


endmodule
module kb(   //extract only the real bytes from received packets of data(no break code)
	input clk,rst_n,
	input ps2d,ps2c,
	input rd_fifo,
	output [8:0] rd_data, //{shift,data}
	output fifo_empty
    );
	 wire[10:0] dout;
	 wire rx_dont_tick;
	 wire wr;
	 wire [8:0] wr_data;
	 
 
	 ps2_rx m0
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_en(1),
		.ps2d(ps2d),
		.ps2c(ps2c),
		.dout(dout),
		.rx_done_tick(rx_done_tick)
    );
	 
	 kb_data m1
	 (
		.clk(clk),
		.rst_n(rst_n),
		.rx_done_tick(rx_done_tick),
		.din(dout[8:1]),
		.wr(wr),
		.wr_data(wr_data)
    );
	 
	  fifo #(.W(4),.B(9)) m2
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(wr),
		.rd(rd_fifo), //
		.wr_data(wr_data),
		.rd_data(rd_data),//
		.full(),
		.empty(fifo_empty) //
    );
	 
endmodule