dakies/OSS_Verilog huggingface dataset:
module uart
	#(parameter DBIT=8,SB_TICK=16,DVSR=326,DVSR_WIDTH=9,FIFO_W=2) //DBIT=databits , SB_TICK=stop_bits tick(16 per bit) , DVSR= clk/(16*BaudRate) , DVSR_WIDTH=array size needed by DVSR,FIFO_WIDTH+fifo size(2^x) )
	(
	input clk,rst_n,
	input rd_uart,wr_uart,
	input[7:0] wr_data,
	input rx,
	output tx,
	output[7:0] rd_data,
	output rx_empty,tx_full
    );

	 /*
	 uart #(.DBIT(8),.SB_TICK(16),.DVSR(326),.DVSR_WIDTH(9),.FIFO_W(2)) m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.rd_uart(rd_uart),
		.wr_uart(wr_uart),
		.wr_data(wr_data),
		.rx(rx),
		.tx(tx),
		.rd_data(rd_data),
		.rx_empty(rx_empty),
		.tx_full()
    );
	 */

	 
	 wire s_tick,rx_done_tick,empty;
	 wire[7:0] dout,rd_data_tx;
	 
	 
	baud_generator #(.N(DVSR),.N_width(DVSR_WIDTH)) m0
	(
	.clk(clk),
	.rst_n(rst_n),
	.s_tick(s_tick)
    );
	 
	 uart_rx #(.DBIT(DBIT),.SB_TICK(SB_TICK)) m1 //DBIT=data bits , SB_TICK=ticks for stop bit (16 for 1 bit ,32 for 2 bits)
	(
		.clk(clk),
		.rst_n(rst_n),
		.rx(rx),
		.s_tick(s_tick),
		.rx_done_tick(rx_done_tick),
		.dout(dout)
    );
	 fifo #(.W(FIFO_W),.B(DBIT)) m2
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(rx_done_tick),
		.rd(rd_uart),
		.wr_data(dout),
		.rd_data(rd_data),
		.full(),
		.empty(rx_empty)
    );
	uart_tx #(.DBIT(DBIT),.SB_TICK(SB_TICK)) m3
	(
		.clk(clk),
		.rst_n(rst_n),
		.s_tick(s_tick), 
		.tx_start(empty),
		.din(rd_data_tx),
		.tx_done_tick(tx_done_tick),
		.tx(tx)
    );
	 fifo #(.W(FIFO_W),.B(DBIT)) m4
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(wr_uart),
		.rd(tx_done_tick),
		.wr_data(wr_data),
		.rd_data(rd_data_tx),
		.full(tx_full),
		.empty(empty)
    );

endmodule
module debounce_explicit(
	input clk,rst_n,
	input sw,
	output reg db_level,db_tick
    );
	/*
	
	debounce_explicit
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw(sw),
		.db_level(),
		.db_tick(key_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 dual_mode_disp
	(
	input clk,rst_n,
	input rx,
	input[3:0] key, //key[0] to move cursor to right,key[1] to move cursor down,key[2] to write @ current cursor,key[3] to change display mode
	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;
	 wire key3_tick;
	 reg mode_q=0;
	 wire[2:0] rgb_vertical,rgb_horizontal;
	
	 //alternates between horizontal and vertical mode
	 always @(posedge clk_out,negedge rst_n) begin 
		if(!rst_n) mode_q<=0;
		else mode_q<= key3_tick? !mode_q:mode_q;
	 end
	 
	 
	 assign rgb= mode_q? rgb_horizontal:rgb_vertical; //chooses which of the two modes will be displayed
	 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)
    );	
	 
	mode_vertical m1 //vertical mode
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.rx(rx),
		.key(key[2:0]), //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_vertical)
    );
	
	mode_horizontal m2  //horizontal mode
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.rx(rx),
		.key(key[2:0]), //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_horizontal)
    );
	 
	 dcm_25MHz m3
		(// Clock in ports
		 .clk(clk),      // IN
		 // Clock out ports
		 .clk_out(clk_out),     // OUT
		 // Status and control signals
		 .RESET(RESET),// IN
		 .LOCKED(LOCKED)
	 );  
	 
	debounce_explicit m4
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.sw(key[3]),
		.db_level(),
		.db_tick(key3_tick)
    );
	 
	
endmodule
module dual_port_syn
	#(
		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 vga_core(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		//650x480 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;
	reg vsync_q=0,vsync_d;
	//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
	
	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; //horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

endmodule
module rotating_banner
	(
	input clk,rst_n,
	input[3:0] key, //key[1:0]=char size , key[3:2]=rotating speed
	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)
    );	
	 
	 rotating_banner_gen m1
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.key(key), 
		.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 ehn_stopwatch_TEST(
	input clk,rst_n,
	input up,go,
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 wire [4:0] in0,in1,in2,in3,in4,in5;
	 
	 Enhanced_Stopwatch ehn_stopwatch(   
	.clk(clk),
	.rst_n(rst_n),
	.up(up),
	.go(go), 
	.in0(in0),
	.in1(in1),
	.in2(in2),
	.in3(in3),
	.in4(in4),
	.in5(in5)
    );
	 
	 LED_mux led_mux
		(
		.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 EnhancedStopwatch_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg up;
	reg go;

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

	// Instantiate the Unit Under Test (UUT)
	Enhanced_Stopwatch uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.up(up), 
		.go(go), 
		.in0(in0), 
		.in1(in1), 
		.in2(in2), 
		.in3(in3), 
		.in4(in4), 
		.in5(in5)
	);
	always begin //100MHz
	clk=1'b0;
	#5;
	clk=1'b1;
	#5;
	end

	initial begin //tick is every 50ns,

		rst_n = 1;
		up = 1;
		go = 1;



	end
      
endmodule
module debounce_explicit(
	input clk,rst_n,
	input sw,
	output reg db_level,db_tick
    );
	/*
	
	debounce_explicit
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw(sw),
		.db_level(),
		.db_tick(key_tick)
    );
	 
	 */
	 
	 //FSM symbolic declaration
	 localparam[1:0]  idle=2'b00,
							delay0=2'b01,
							one=2'b10,
							delay1=2'b11;
	 localparam N=19; //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 vga_core(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	input[2:0] key,
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		//650x480 parameters
	 localparam HD=640, //Horizontal Display
					HRet=96, //Horizontal Retrace
					
					VD=480, //Vertical Display
					VRet=2; //Vertical Retrace

	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;
	reg vsync_q=0,vsync_d;
	wire key1_tick,key2_tick;
	
	reg[5:0] HR_q=16,HR_d; //horizontal right border
	reg[5:0]  HL_q=48,HL_d; //horizontal left border
	reg[5:0] VB_q=10,VB_d; //vertical bottom border
	reg[5:0] VT_q=33,VT_d; //vertical top border
	
	//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;
			HR_q<=16;
			HL_q<=48;
			VB_q<=10;
			VT_q<=33;
		end
		else begin
			vctr_q<=vctr_d;
			hctr_q<=hctr_d;
			vsync_q<=vsync_d;
			hsync_q<=hsync_d;
			HR_q<=HR_d;
			HL_q<=HL_d;
			VB_q<=VB_d;
			VT_q<=VT_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; 
		HR_d=HR_q;
		HL_d=HL_q;
		VB_d=VB_q;
		VT_d=VT_q;
			
			
		//logic for movable screen
		//key_tick adjust left/right/top/bottom borders 
		
		if(key1_tick || key2_tick) begin
			if(key[0]) begin//vertical movement
				if(key1_tick) begin //MOVE UP
					VT_d=(VT_q!=0)?VT_q-1:VT_q;
					VB_d=(VT_q!=0)? VB_q+1:VB_q;
				end
				else if(key2_tick) begin //MOVE DOWN
					VT_d=(VB_q!=0)?VT_q+1:VT_q;
					VB_d=(VB_q!=0)?VB_q-1:VB_q;
				end
			end
			else begin //horizontal movement
				if(key1_tick) begin //MOVE RIGHT
					HR_d=(HR_q!=0)? HR_q-1:HR_q;
					HL_d=(HR_q!=0)? HL_q+1:HL_q;
				end
				else if(key2_tick) begin //MOVE LEFT
					HR_d=(HL_q!=0)? HR_q+1:HR_q;
					HL_d=(HL_q!=0)? HL_q-1:HL_q;
				end
			end
		end
		
		
		if(hctr_q==HD+HR_q+HRet+HL_q-1) hctr_d=0; //horizontal counter
		else hctr_d=hctr_q+1'b1;
		
		if(vctr_q==VD+VB_q+VRet+VT_q-1) vctr_d=0; //vertical counter
		else if(hctr_q==HD+HR_q+HRet+HL_q-1) vctr_d=vctr_q+1'b1;
		
		if(hctr_q<HD && vctr_q<VD) video_on=1; //video_on 
		
		if( (hctr_d>=HD+HR_q) && (hctr_d<=HD+HR_q+HRet-1) ) hsync_d=0; //horizontal sync 
		if( (vctr_d>=VD+VB_q) && (vctr_d<=VD+VB_q+VRet-1) ) vsync_d=0; //vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;
		
	debounce_explicit m0
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw(!key[1]),
		.db_level(),
		.db_tick(key1_tick)
    );
	 debounce_explicit m1
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw(!key[2]),
		.db_level(),
		.db_tick(key2_tick)
    );

endmodule
module vga_test(
	input clk, rst_n,
	input[2:0] key, //key[0] for selecting vertical or horizontal mode adjustment. key[2:1] to move the screen up/down(if vertical mode) or left/right(if horizontal mode)
	output reg[4:0] vga_out_r,
	output reg[5:0] vga_out_g,
	output reg[4:0] vga_out_b,
	output vga_out_vs,vga_out_hs
    );
	 
	
	wire clk_out;
	wire video_on;
	
		//display logic
		always @* begin
			vga_out_r=0;
			vga_out_g=0;
			vga_out_b=0;
			if(video_on) begin
				vga_out_g=6'b111_111; //display screen color is green
			end
		end
		
		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 //VGA controller(640x480) with adjustable screen position
	(
		.clk(clk_out),  //clock must be 25MHz for 640x480 
		.rst_n(rst_n),
		.key(key),
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(),
		.pixel_y()
    );


endmodule
module vga_core(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		
	 
	 //650x480 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;
	reg vsync_q=0,vsync_d;
	//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
	
	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; //horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

endmodule
module top_module
	(
		input clk, rst_n,
		input[1:0] key, //key[1] is for changing  ball speed, key[0] for changing location of 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), //clock must be 25MHz for 640x480 resolution
		.rst_n(rst_n), 
		.hsync(vga_out_hs),
		.vsync(vga_out_vs),
		.video_on(video_on),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
    );
	 
	 ball_in_a_box m2 //logic for self-bouncing ball
	 (
		.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[5:0] in0,in1,in2,in3,in4,in5, //format: {dp,char[4:0]} , dp is active high
	output reg[7:0] seg_out,
	output reg[5:0] sel_out
    );
	 
	 reg[N-1:0] r_reg=0;
	 reg[5: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
	 	 
	 //hex-to-seg decoder
	 always @* begin
		 seg_out=0;
			 case(hex_out[4:0])
			 5'd0: seg_out[6:0]=7'b0000_001;
			 5'd1: seg_out[6:0]=7'b1001_111;
			 5'd2: seg_out[6:0]=7'b0010_010;
			 5'd3: seg_out[6:0]=7'b0000_110;
			 5'd4: seg_out[6:0]=7'b1001_100;
			 5'd5: seg_out[6:0]=7'b0100_100;
			 5'd6: seg_out[6:0]=7'b0100_000;
			 5'd7: seg_out[6:0]=7'b0001_111;
			 5'd8: seg_out[6:0]=7'b0000_000;
			 5'd9: seg_out[6:0]=7'b0001_100;
	  /*A*/5'd10: seg_out[6:0]=7'b0001_000; 
	  /*b*/5'd11: seg_out[6:0]=7'b1100_000;
	  /*C*/5'd12: seg_out[6:0]=7'b0110_001;
	  /*d*/5'd13: seg_out[6:0]=7'b1000_010;
	  /*E*/5'd14: seg_out[6:0]=7'b0110_000;
	  /*F*/5'd15: seg_out[6:0]=7'b0111_000;
	  /*G*/5'd16: seg_out[6:0]=7'b0100_000;
	  /*H*/5'd17: seg_out[6:0]=7'b1001_000;
	  /*I*/5'd18: seg_out[6:0]=7'b1111_001;
	  /*J*/5'd19: seg_out[6:0]=7'b1000_011;
	  /*L*/5'd20: seg_out[6:0]=7'b1110_001;
	  /*O*/5'd21: seg_out[6:0]=7'b0000_001;
	  /*P*/5'd22: seg_out[6:0]=7'b0011_000; 
	  /*R*/5'd23: seg_out[6:0]=7'b0001_000;
	  /*S*/5'd24: seg_out[6:0]=7'b0100_100;
	  /*U*/5'd25: seg_out[6:0]=7'b1000_001;
	  /*y*/5'd26: seg_out[6:0]=7'b1000_100;
	  /*Z*/5'd27: seg_out[6:0]=7'b0010_010; 
	/*OFF*/5'd28: seg_out[6:0]=7'b1111_111; //decimal 29 to 31 will be alloted for future use
			 endcase
		 seg_out[7]=!hex_out[5]; //active high decimal
	 end

endmodule
module uart
	#(parameter DBIT=8,SB_TICK=16,DVSR=326,DVSR_WIDTH=9,FIFO_W=2)
	(
	input clk,rst_n,
	input rd_uart,wr_uart,
	input[7:0] wr_data,
	input rx,
	output tx,
	output[7:0] rd_data,
	output rx_empty,tx_full
    );

	 
	 wire s_tick,rx_done_tick,empty;
	 wire[7:0] dout,rd_data_tx;
	 
	 
	baud_generator #(.N(DVSR),.N_width(DVSR_WIDTH)) m0
	(
	.clk(clk),
	.rst_n(rst_n),
	.s_tick(s_tick)
    );
	 
	 uart_rx #(.DBIT(DBIT),.SB_TICK(SB_TICK)) m1 //DBIT=data bits , SB_TICK=ticks for stop bit (16 for 1 bit ,32 for 2 bits)
	(
		.clk(clk),
		.rst_n(rst_n),
		.rx(rx),
		.s_tick(s_tick),
		.rx_done_tick(rx_done_tick),
		.dout(dout)
    );
	 fifo #(.W(FIFO_W),.B(DBIT)) m2
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(rx_done_tick),
		.rd(rd_uart),
		.wr_data(dout),
		.rd_data(rd_data),
		.full(),
		.empty(rx_empty)
    );
	uart_tx #(.DBIT(DBIT),.SB_TICK(SB_TICK)) m3
	(
		.clk(clk),
		.rst_n(rst_n),
		.s_tick(s_tick), 
		.tx_start(empty),
		.din(rd_data_tx),
		.tx_done_tick(tx_done_tick),
		.tx(tx)
    );
	 fifo #(.W(FIFO_W),.B(DBIT)) m4
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(wr_uart),
		.rd(tx_done_tick),
		.wr_data(wr_data),
		.rd_data(rd_data_tx),
		.full(tx_full),
		.empty(empty)
    );

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 logic_analyzer
	(
	input clk,rst_n,
	input key,
	input[3:0] in_q,//4-trace square-wave inputs to be displayed on screen via VGA
	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,
	output reg[3:0] out_q //square-wave output test-signal (10kHz , 20kHz , 40kHz , 100kHz)
    );
	 
	 wire[11:0] pixel_x,pixel_y;
	 wire video_on;
	 wire[2:0] rgb;
	 wire clk_out;
	 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 //displays the four input square wave signals 
	(
		.clk(clk_out),
		.rst_n(rst_n),
		.key(key),
		.in(in_q),
		.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)
	 );    
		
	
	
	
	 //logic for free-running square test-signals 
	 reg[6:0] counter_100kHz=0; //mod_125 
	 reg[8:0] counter_40kHz=0; //mod_312
	 reg[9:0] counter_20kHz=0; //mod_625
	 reg[10:0] counter_10kHz=0; //mod_1250
	 
	 initial begin
		out_q=0;
	 end
	 
	 always @(posedge clk_out) begin
		counter_100kHz<=(counter_100kHz==124)? 0:counter_100kHz+1;
		counter_40kHz<=(counter_40kHz==311)? 0:counter_40kHz+1;
		counter_20kHz<=(counter_20kHz==624)? 0:counter_20kHz+1;
		counter_10kHz<=(counter_10kHz==1249)? 0:counter_10kHz+1;	 
		out_q[0] <= (counter_100kHz==0)? !out_q[0]:out_q[0]; //reverse the signal every restart of the free running counter to form a square
		out_q[1] <= (counter_40kHz==0)? !out_q[1]:out_q[1];
		out_q[2] <= (counter_20kHz==0)? !out_q[2]:out_q[2];
		out_q[3] <= (counter_10kHz==0)? !out_q[3]:out_q[3];
	 end
	 

endmodule
module dual_port_syn //dual port synchronous 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 vga_core(
	input clk,rst_n, //clock must be 25MHz for 640x480 
	output hsync,vsync,
	output reg video_on,
	output[11:0] pixel_x,pixel_y
    );		//650x480 parameters
	 localparam HD=640, //Horizontal Display
					HR=16, //Right Border
					HRet=96, //Horizontal Retrace
					HL=48, //Left Border
					
					VD=480, //Vertical Display
					VB=1, //Bottom Border
					VRet=2, //Vertical Retrace
					VT=42; //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;
	reg vsync_q=0,vsync_d;
	//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
	
	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; //horizontal sync 
		if( (vctr_d>=VD+VB) && (vctr_d<=VD+VB+VRet-1) ) vsync_d=0; //vertical sync
				
	end
		assign vsync=vsync_q;
		assign hsync=hsync_q;
		assign pixel_x=hctr_q;
		assign pixel_y=vctr_q;

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 bin2bcd(
	input clk,rst_n,
	input start,
	input[19:0] bin,//limit is 6 digit of bcd
	output reg ready,done_tick,
	output[3:0] dig0,dig1,dig2,dig3,dig4,dig5
    );
	 //FSM declarations
	 localparam[1:0] idle=2'd0,
							op=2'd1,
							done=2'd2;
	 localparam N=20; //width of binary
	
	 reg[1:0] state_reg,state_nxt;
	 reg[N-1:0] bin_reg,bin_nxt;
	 reg[3:0] dig0_reg,dig1_reg,dig2_reg,dig3_reg,dig4_reg,dig5_reg;
	 reg[3:0] dig0_nxt,dig1_nxt,dig2_nxt,dig3_nxt,dig4_nxt,dig5_nxt;
	 reg[4:0] n_reg,n_nxt;
	 
	 //FSM reguster operations
	 always @(posedge clk,negedge rst_n) begin
		 if(!rst_n) begin
			state_reg<=idle;
			bin_reg<=0;
			dig0_reg<=0;
			dig1_reg<=0;
			dig2_reg<=0;
			dig3_reg<=0;
			dig4_reg<=0;
			dig5_reg<=0;
			n_reg<=0;
		 end
		 else begin
			state_reg<=state_nxt;
			bin_reg<=bin_nxt;
			dig0_reg<=dig0_nxt;
			dig1_reg<=dig1_nxt;
			dig2_reg<=dig2_nxt;
			dig3_reg<=dig3_nxt;
			dig4_reg<=dig4_nxt;
			dig5_reg<=dig5_nxt;
			n_reg<=n_nxt;
		 end		 
	 end
	 //FSM next-state logics
	 always @* begin
		state_nxt=state_reg;
		bin_nxt=bin_reg;
		dig0_nxt=dig0_reg;
		dig1_nxt=dig1_reg;
		dig2_nxt=dig2_reg;
		dig3_nxt=dig3_reg;
		dig4_nxt=dig4_reg;
		dig5_nxt=dig5_reg;
		n_nxt=n_reg;
		done_tick=0;
		ready=0;
			case(state_reg) 
				idle: begin
							ready=1;
							if(start) begin
								bin_nxt=bin;
								dig0_nxt=0;
								dig1_nxt=0;
								dig2_nxt=0;
								dig3_nxt=0;
								dig4_nxt=0;
								dig5_nxt=0;
								n_nxt=N;
								state_nxt=op;
							end
						end
				  op: begin
							dig0_nxt=(dig0_reg<=4)?dig0_reg:dig0_reg+4'd3;
							dig1_nxt=(dig1_reg<=4)?dig1_reg:dig1_reg+4'd3;
							dig2_nxt=(dig2_reg<=4)?dig2_reg:dig2_reg+4'd3;
							dig3_nxt=(dig3_reg<=4)?dig3_reg:dig3_reg+4'd3;
							dig4_nxt=(dig4_reg<=4)?dig4_reg:dig4_reg+4'd3;
							dig5_nxt=(dig5_reg<=4)?dig5_reg:dig5_reg+4'd3;
							
							{dig5_nxt,dig4_nxt,dig3_nxt,dig2_nxt,dig1_nxt,dig0_nxt,bin_nxt}={dig5_nxt,dig4_nxt,dig3_nxt,dig2_nxt,dig1_nxt,dig0_nxt,bin_nxt}<<1; //shift left by 1
							n_nxt=n_reg-1;
							if(n_nxt==0) state_nxt=done;			
						end
				done: begin
							done_tick=1;
							state_nxt=idle;
						end
			default: state_nxt=idle;						
			endcase	
	 end
	 assign  dig0=dig0_reg,
				dig1=dig1_reg,
				dig2=dig2_reg,
				dig3=dig3_reg,
				dig4=dig4_reg,
				dig5=dig5_reg;
	
	 
	 

	 


endmodule
module rotating_LED_TEST(
	input clk,rst_n,
	input en,dir,
	output[7:0] seg_out,
	output[5:0] sel_out
    );
	 wire [4:0] in0,in1,in2,in3,in4,in5;
	 rotating_LED #(.turns(25_000_000)) //Frequency will be 50MHz/turns = 50MHz/15M = 3.33Hz(0.3 sec per move)
		 rot_led
			(
			.clk(clk),
			.rst_n(rst_n),
			.en(en),
			.dir(dir),
			.in0(in0),
			.in1(in1),
			.in2(in2),
			.in3(in3),
			.in4(in4),
			.in5(in5)
			 );
	 
	LED_mux led_mux
		(
		.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 rotating_LED
	#(parameter turns=15_000_000) ///Frequency will be 50MHz/turns = 50MHz/15M = 3.33Hz(0.3 sec per move)
	(
	input clk,rst_n,
	input en,dir,
	output [4:0] in0,in1,in2,in3,in4,in5 //{decimalpoint,hexadecimal}
    );
	 localparam W=10; //number of all letters/numbers to be displayed
	 
	 reg[24:0] mod_turns=0;
	 reg[5*W-1:0] words={  ////  word=0123456789 
								{1'b0,4'h0},
								{1'b0,4'h1},
								{1'b0,4'h2},
								{1'b0,4'h3},
								{1'b0,4'h4},
								{1'b0,4'h5},
								{1'b0,4'h6},
								{1'b0,4'h7},
								{1'b0,4'h8},
								{1'b0,4'h9}			
								}; //Note: If  "W" is greater than the words initialized here, it will be displayed as default zero on the leftmost digit
	  wire[24:0] mod_turns_nxt;
	  reg[5*W-1:0] words_nxt;
	  wire mod_turns_max;
	  
	  //registers
	  always @(posedge clk,negedge rst_n) begin
			if(!rst_n) begin
				mod_turns<=0;
				words<={ {1'b0,4'h0},
						  {1'b0,4'h1},
						  {1'b0,4'h2},
						  {1'b0,4'h3},
						  {1'b0,4'h4},
						  {1'b0,4'h5},
						  {1'b0,4'h6},
						  {1'b0,4'h7},
						  {1'b0,4'h8},
						  {1'b0,4'h9}			
						  };
			end
			
			else begin
				if(en) begin
					mod_turns<=mod_turns_nxt;
					words<=words_nxt;
			   end	
			end
			
	  end
	  //next-state logics
	  assign mod_turns_nxt=(mod_turns==turns)?0:mod_turns+1;
	  assign mod_turns_max=(mod_turns==turns)?1:0;
	
	  always @* begin
	  words_nxt=words;
	  if(mod_turns_max) words_nxt=dir? {words[5*W-6:0],words[5*W-1:5*W-5]}  :  {words[4:0],words[5*W-1:5]} ;  //if dir is asserted: move left , else:move right
	  end
	  
	  //output logic to be be used by the LED Multiplexing circuit (6 5-bit outputs that determine what number will be displayed on the sevensegments)
	  assign in5=words[5*W-1:5*W-5],
				in4=words[5*W-6:5*W-10],
				in3=words[5*W-11:5*W-15],
				in2=words[5*W-16:5*W-20],
				in1=words[5*W-21:5*W-25],
				in0=words[5*W-26:5*W-30];
endmodule
module ps2_monitor(
	input clk,rst_n,
	input[10:0] din,
	input rx_done_tick,
	output reg wr,
	output reg[7:0] wr_data,
	output reg done_tick
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							hex0=2'd1, //extract first hex of din then convert to ascii to be transmitted via UART
							hex1=2'd2, //extract second hex of din then convert to ascii to be transmitted via UART
							done=2'd3;
	reg[1:0] state_reg,state_nxt;
	reg[10:0] din_reg,din_nxt;
	reg[3:0] hex;
	reg[7:0] ascii;
	//FSM register operations
	always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			din_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			din_reg<=din_nxt;
		end
	end
	//FSM next-state logics
	always @* begin
		state_nxt=state_reg;
		din_nxt=din_reg;
		hex=0;
		wr=0;
		done_tick=0;
		wr_data=0;
		case(state_reg) 
			   idle: if(rx_done_tick) begin //wait for ps2_rx to finsih receiving a packet
							din_nxt=din;
							state_nxt=hex0;
						end
			   hex0: begin  //extract first hex of din then convert to ascii to be transmitted via UART
							hex=din_reg[8:5];
							wr_data=ascii;
							wr=1;
							state_nxt=hex1;
						end
			   hex1: begin  //extract second hex of din then convert to ascii to be transmitted via UART
							hex=din_reg[4:1];
							wr_data=ascii;
							wr=1;
							state_nxt=done;
						end
			   done: begin
							wr_data=8'h20; //space for more organized output
							wr=1;
							done_tick=1;
							state_nxt=idle;
						end
			default: state_nxt=idle;
		endcase
	end
	//convert hex to ascii
	always @* begin
		ascii=0;
		case(hex)
			4'h0: ascii=8'h30;
			4'h1: ascii=8'h31;
			4'h2: ascii=8'h32;
			4'h3: ascii=8'h33;
			4'h4: ascii=8'h34;
			4'h5: ascii=8'h35;
			4'h6: ascii=8'h36;
			4'h7: ascii=8'h37;
			4'h8: ascii=8'h38;
			4'h9: ascii=8'h39;
			4'ha: ascii=8'h41; //A
			4'hb: ascii=8'h42; //B
			4'hc: ascii=8'h43; //C
			4'hd: ascii=8'h44; //D
			4'he: ascii=8'h45; //E
			4'hf: ascii=8'h46; //F	
			default: ascii=8'h47; //for debugging
		endcase
	end

endmodule
module ascii_conv( //converts the real data from kb module to ASCII
	input[8:0] rd_data,
	output reg[7:0] ascii
    );
 always @* begin
		ascii=0;
		case(rd_data)
			{1'b0,8'h45}: ascii = 8'h30; //0
			{1'b0,8'h16}: ascii = 8'h31; //1
			{1'b0,8'h1e}: ascii = 8'h32; //2
			{1'b0,8'h26}: ascii = 8'h33; //3
			{1'b0,8'h25}: ascii = 8'h34; //4
			{1'b0,8'h2e}: ascii = 8'h35; //5
			{1'b0,8'h36}: ascii = 8'h36; //6
			{1'b0,8'h3d}: ascii = 8'h37; //7
			{1'b0,8'h3e}: ascii = 8'h38; //8
			{1'b0,8'h46}: ascii = 8'h39; //9
			
			{1'b1,8'h1c}: ascii = 8'h41; //A
			{1'b1,8'h32}: ascii = 8'h42; //B
			{1'b1,8'h21}: ascii = 8'h43; //C
			{1'b1,8'h23}: ascii = 8'h44; //D
			{1'b1,8'h24}: ascii = 8'h45; //E
			{1'b1,8'h2b}: ascii = 8'h46; //F
			{1'b1,8'h34}: ascii = 8'h47; //G
			{1'b1,8'h33}: ascii = 8'h48; //H
			{1'b1,8'h43}: ascii = 8'h49; //I
			{1'b1,8'h3b}: ascii = 8'h4a; //J
			{1'b1,8'h42}: ascii = 8'h4b; //K
			{1'b1,8'h4b}: ascii = 8'h4c; //L
			{1'b1,8'h3a}: ascii = 8'h4d; //M
			{1'b1,8'h31}: ascii = 8'h4e; //N
			{1'b1,8'h44}: ascii = 8'h4f; //O
			{1'b1,8'h4d}: ascii = 8'h50; //P
			{1'b1,8'h15}: ascii = 8'h51; //Q
			{1'b1,8'h2d}: ascii = 8'h52; //R
			{1'b1,8'h1b}: ascii = 8'h53; //S
			{1'b1,8'h2c}: ascii = 8'h54; //T
			{1'b1,8'h3c}: ascii = 8'h55; //U
			{1'b1,8'h2a}: ascii = 8'h56; //V
			{1'b1,8'h1d}: ascii = 8'h57; //W
			{1'b1,8'h22}: ascii = 8'h58; //X
			{1'b1,8'h35}: ascii = 8'h59; //Y
			{1'b1,8'h1a}: ascii = 8'h5a; //Z
			
			{1'b0,8'h1c}: ascii = 8'h61; //a
			{1'b0,8'h32}: ascii = 8'h62; //b
			{1'b0,8'h21}: ascii = 8'h63; //c
			{1'b0,8'h23}: ascii = 8'h64; //d
			{1'b0,8'h24}: ascii = 8'h65; //e
			{1'b0,8'h2b}: ascii = 8'h66; //f
			{1'b0,8'h34}: ascii = 8'h67; //g
			{1'b0,8'h33}: ascii = 8'h68; //h
			{1'b0,8'h43}: ascii = 8'h69; //i
			{1'b0,8'h3b}: ascii = 8'h6a; //j
			{1'b0,8'h42}: ascii = 8'h6b; //k
			{1'b0,8'h4b}: ascii = 8'h6c; //l
			{1'b0,8'h3a}: ascii = 8'h6d; //m
			{1'b0,8'h31}: ascii = 8'h6e; //n
			{1'b0,8'h44}: ascii = 8'h6f; //o
			{1'b0,8'h4d}: ascii = 8'h70; //p
			{1'b0,8'h15}: ascii = 8'h71; //q
			{1'b0,8'h2d}: ascii = 8'h72; //r
			{1'b0,8'h1b}: ascii = 8'h73; //s
			{1'b0,8'h2c}: ascii = 8'h74; //t
			{1'b0,8'h3c}: ascii = 8'h75; //u
			{1'b0,8'h2a}: ascii = 8'h76; //v
			{1'b0,8'h1d}: ascii = 8'h77; //w
			{1'b0,8'h22}: ascii = 8'h78; //x
			{1'b0,8'h35}: ascii = 8'h79; //y
			{1'b0,8'h1a}: ascii = 8'h7a; //z
			
			
			{1'b0,8'h0e}: ascii = 8'h60; // `
			{1'b0,8'h4e}: ascii = 8'h2d; // - 
			{1'b0,8'h55}: ascii = 8'h3d; // =
			{1'b0,8'h54}: ascii = 8'h5b; // [
			{1'b0,8'h5b}: ascii = 8'h5d; // ]
			{1'b0,8'h5d}: ascii = 8'h5c; // \
			{1'b0,8'h4c}: ascii = 8'h3b; // ;
			{1'b0,8'h52}: ascii = 8'h27; // '
			{1'b0,8'h41}: ascii = 8'h2c; // ,
			{1'b0,8'h49}: ascii = 8'h2e; // .
			{1'b0,8'h4a}: ascii = 8'h2f; // /
			
			{1'b0,8'h29}: ascii = 8'h20; //space
			{1'b0,8'h5a}: ascii = 8'h0d; //enter
			{1'b0,8'h66}: ascii = 8'h08; //backspace
			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 [8:0] rd_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
module kb_test(
	input clk,rst_n,
	input ps2d,ps2c,
	output tx
    );
	 wire rd_fifo;
	 wire[8:0] rd_data;
	 wire[7:0] ascii;
	 wire fifo_empty;
	 kb m0 //extract only the real bytes(only the makecode,no breakcode) 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[8:0] wr_data //9th bit is asserted if shift is pressed(for capital letters)
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							scan=2'd1,
							breakcode=2'd3;
	 reg[1:0] state_reg;
	 reg shift_reg=0;
	 //FSM register operations
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			shift_reg<=0;
		end
		
		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; //break code
							else begin
								if(din==8'h12 || din==8'h59) begin//shift key 
									shift_reg<=1;
									state_reg<=scan;
								end
								else begin//non-shift key
									wr_data={shift_reg,din};
									wr=1;
									state_reg<=scan;
								end
							end							
						 end
				scan: if(rx_done_tick) begin 
							if(din==8'hf0) state_reg<=breakcode; //break code
							else begin
								if(din==8'h12 || din==8'h59) shift_reg<=1; //shift key
								else begin //non-shift key
									wr_data={shift_reg,din};
									wr=1;
								end
							end
						end
		 breakcode: if(rx_done_tick) begin
							if(din==8'h12 || din==8'h59) shift_reg<=0; //end of shift key
							state_reg<=idle;	//skip the makecode after the breakcode 8'hf0 	
						end
			default: state_reg<=idle;
			endcase
		end
	 end
	 


endmodule
module ps2_rx(
	input clk,rst_n,
	input rx_en,
	input ps2d,ps2c,
	output[10:0] dout,
	output reg rx_done_tick
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							scan=2'd1,
							done=2'd2;
	 reg[1:0] state_reg,state_nxt;
	 reg[10:0] data_reg,data_nxt;
	 reg[3:0] n_reg,n_nxt;
	 reg[7:0] filter_reg,filter_nxt;
	 reg ps2c_f_reg,ps2c_f_nxt;
	 reg ps2c_reg;
	 wire ps2c_edg;
	 //FSM register operations
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=0;
			data_reg<=0;
			n_reg<=0;
			filter_reg<=0;
			ps2c_f_reg<=0;
			ps2c_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			data_reg<=data_nxt;
			n_reg<=n_nxt;
			filter_reg<=filter_nxt;
			ps2c_f_reg<=ps2c_f_nxt;
			ps2c_reg<=ps2c_f_reg;
		end
	 end
	 
	 //FSM next-state logic
	 always @* begin
		state_nxt=state_reg;
		data_nxt=data_reg;
		n_nxt=n_reg;
		rx_done_tick=0;
		case(state_reg)
			   idle: if(ps2c_edg && rx_en) begin //wait for the falling edge of the start bit
							data_nxt={ps2d,data_reg[10:1]};
							n_nxt=0;
							state_nxt=scan;
						end						
			   scan: if(ps2c_edg) begin //wait to finish receiving all data bits(bit0-9,paritybit,then stopbit)
							data_nxt={ps2d,data_reg[10:1]};
							if(n_reg==9) state_nxt=done;
							else n_nxt=n_reg+1;
						end
			   done: begin //finish
							rx_done_tick=1;
							state_nxt=idle;
						end
			default: state_nxt=idle;	
		endcase
	 end
	 //ps2c filter logic. The ps2c_f_reg is the filtered output.
	 always @* begin 
		filter_nxt={ps2c,filter_reg[7:1]}; 
		if(filter_reg==8'b1111_1111) ps2c_f_nxt=1;  //Any glitches shorter than 8 turns will be ignored
		else if(filter_reg==8'b0000_0000) ps2c_f_nxt=0; 
		else ps2c_f_nxt=ps2c_f_reg;
	 end
	 //falling edge detection for ps2c_f_reg
	 assign ps2c_edg=(ps2c_reg && !ps2c_f_reg)?1:0;
	assign dout=data_reg;
endmodule
module dual_edge_detector_MOORE(
	input clk,rst_n,
	input level, //active high
	output reg edg
    );
	 
	 //FSM declarations
	 localparam[1:0] zero=2'd0,
						  r_edg=2'd1,
						  one=2'd2,
						  f_edg=2'd3;
	 reg[1:0] state_reg,state_nxt;
	 
	 //FSM register operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) state_reg<=zero;
		else state_reg<=state_nxt;
	 end
	 
	 //FSM next-state and output logic
	 always @* begin
		state_nxt=state_reg;
		edg=0;
		case(state_reg) 
			zero: if(level) state_nxt=r_edg;
			r_edg: begin
						edg=1;
						if(level) state_nxt=one;
						else state_nxt=zero;
					 end
			one: if(!level) state_nxt=f_edg;
			f_edg: begin
						edg=1;
						state_nxt=zero;
					 end
			default: state_nxt=zero;
		endcase
	 end


endmodule
module dual_edge_detector_MEALY(
	input clk,rst_n,
	input level, //active-high
	output reg edg
    );
	 //FSM declarations
	 localparam zero=1'b0,
					one=1'b1;
	reg state_reg,state_nxt;
	
	//FSM register operation
	always @(posedge clk,negedge rst_n) begin
		if(!rst_n) state_reg<=zero;
		else state_reg<=state_nxt;
	end
	//FSM next-state and output logic
	always @* begin
		state_nxt=state_reg;
		edg=0;
			case(state_reg)
			zero: if(level) begin
						edg=1;
						state_nxt=one;
					end
			one: if(!level) begin
						edg=1;
						state_nxt=zero;
					end
			default: state_nxt=zero;
			endcase	
	end

endmodule
module dual_edge_detector_simpler(
	input clk,rst_n,
	input level,
	output edg
    );
	 reg level_reg=0;
	 always @(posedge clk,negedge rst_n)
	 if(!rst_n) level_reg<=0;
	 else level_reg<=level;
	 assign edg=level^level_reg;
endmodule
module dual_edge_detector_TB;

	// Inputs
	reg clk;
	reg rst_n;
	reg level;

	// Outputs
	wire edg_1,edg_2,edg_3;

	// Instantiate the Unit Under Test (UUT)
	dual_edge_detector_MOORE uut1 (
		.clk(clk), 
		.rst_n(rst_n), 
		.level(level), 
		.edg(edg_1)
	);
	dual_edge_detector_MEALY uut2(
		.clk(clk), 
		.rst_n(rst_n), 
		.level(level), 
		.edg(edg_2)
	);
	dual_edge_detector_simpler uut3(
		.clk(clk), 
		.rst_n(rst_n), 
		.level(level), 
		.edg(edg_3)
	);
	
	
	
	always begin
		clk=1'b0;
		#5;
		clk=1'b1;
		#5;
	end

	initial begin
		// Initialize Inputs

		rst_n = 1;
		level = 0;
		//reset
		//@(negedge clk) rst_n=0;
		@(negedge clk) rst_n=1;
		
		//1 clk on, 1 tick
		level=1;
		@(negedge clk) level=0;
		repeat(5) @(negedge clk);
		
		//2 clk on, 2 ticks
		level=1;
		repeat(2) @(negedge clk);
		level=0;
		repeat(5) @(negedge clk);
		
		//10 clk on,2 ticks
		level=1;
		repeat(10) @(posedge clk);
		level=0;
		repeat(5) @(negedge clk);
		$stop;

	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 tick_db,tick_sw;
	 wire sw_1;
	 assign sw_1=!sw; //dual_edge_detector_MEALY  only accepts active high inputs so reverse the active-low button first
	 //debounce module instantiation
	debouncing_button debounce_module
	(
	.clk(clk),
	.rst_n(rst_n),
	.sw_low(sw), //active low
	.db(db) //active high output
    );
	 
	 
	 //dual edge detector
	 dual_edge_detector_MEALY mealy_m0(
	.clk(clk),
	.rst_n(rst_n),
	.level(db), //active-high
	.edg(tick_db)
    );
	 
	 dual_edge_detector_MEALY mealy_m1(
	.clk(clk),
	.rst_n(rst_n),
	.level(sw_1), //active-high
	.edg(tick_sw)
    );
	 
	 
	 // 10-mod-counter circuit
	 always@(posedge clk,negedge rst_n) begin
		if(!rst_n) begin 
			counter_db<=0;
			counter_sw<=0;	
		end
		else begin
			counter_db<=counter_db_nxt;
			counter_sw<=counter_sw_nxt;
		end
	 end
	 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