dakies/OSS_Verilog huggingface dataset:
module switch_2to2(
		inT,
		inB,
		cT,
      cB,
		outT,
		outB
	);
	
	input  inT;              // Upper input signal 
	input  inB;              // lower input signal
	input  cT;               // Control input
	input  cB;               // Control input
	output outT;             // Upper output signal
	output outB;             // Lower output signal
	
	(*LOCK_PINS = "all"*)
    mux_n21 #(.nCTRL(1)) MUXU(
        .ins({inB,inT}),
        .ctrls(cT),
        .out(outT)
    );
    
    (*LOCK_PINS = "all"*)
    mux_n21 #(.nCTRL(1)) MUXL(
        .ins({inT,inB}),
        .ctrls(cB),
        .out(outB)
    );
    
endmodule
module apufClassic #(parameter nStage = 64)(
	clk, 
	tigSignal, 
	vcc,
	c,
	respReady, 
	respBit
	);
	
	input clk;
	input tigSignal;
	input vcc;
	input [nStage-1:0] c;    // Challenge 
	output respReady;            
	output respBit;
	
	wire pathT;
	wire pathB;
	reg tigReg;

	
	// status of response
	assign respReady = (pathT & pathB);
	
	// Latch the trigger signal to reduce the bias in trigger siganl
	always@(posedge clk) begin 
	 if(tigSignal)
		 tigReg <= vcc; 
	 else 
		 tigReg <= 1'b0; 
	end 

	 // Chain of switches 
	 (*KEEP_HIERARCHY = "TRUE"*)
	 switchChain  #(.nStage(nStage) ) SWITCH_CHAIN( 
		 .inT(tigReg), 
		 .inB(tigReg), 
		 .c(c),
		 .outT(pathT),      // to arbiter 
		 .outB(pathB)       // to arbiter  
	 );

	 // Arbiter 
	 //(*KEEP_HIERARCHY = "TRUE"*)
	/* dflop ARBITER( 
		 .din(pathT), 
		 .clk(pathB), 
		 .dout(respBit) 
	 );
   */
	
   (*KEEP_HIERARCHY = "TRUE"*)
	nandLatch ARBITER(
		.s(pathT),
		.r(pathB),
		.q(respBit),
		.qbar()
	 );
	 
	
endmodule
module iXOR_APUF_64_DOLUT_wrapper(clk,rx,tx);

	localparam CLOCK_FRE = 100000000;  		// Frequency in Hz
	localparam BAUD_RATE = 19200;      		// Baud rate for RS232 communication   
   
	localparam N = 64;     // Challenge length
	localparam K = 8;     	// No. of APUF
	
	(* CLOCK_SIGNAL = "yes" *)
	input  clk;
	input  rx;
	output tx;

	wire tigSig_t, tigSig_b;
	wire respReady, respReady_t;
	wire [K-1:0] respBitA;
	wire respBit;
	reg [N-1:0] challenge;
	
	///////////////////////////////////////////////////////////////////////
   //   PUF INSTANTIATION
	///////////////////////////////////////////////////////////////////////


    //XOR PUF
	(*KEEP_HIERARCHY="TRUE"*)
	xor_apuf #(.N(N),.K(K)) XAPUF(
	   .clk(clk),
		.tigSignal(tigSig_t),
		.c(challenge),
		.respReady(respReady),
		.respBitA(respBitA),
		.respBit(respBit)
	);
	
	/////////////////////////////////////////////////////////////////////////////
	// CHALLENGE PREPARATION
	/////////////////////////////////////////////////////////////////////////////
	
	wire [63:0] dataIn_64;
	wire [7:0] chal_1,chal_2,chal_3,chal_4,chal_5,chal_6,chal_7,chal_8,chal_9;
	wire chalEn;

	assign dataIn_64 = {chal_2,chal_3,chal_4,chal_5,chal_6,chal_7,chal_8,chal_9};

	wire wrEn;
	wire [1:0] inId;             // Change this accordingly
	assign inId = chal_1; 

	// Receive challenges
	always@(posedge clk) begin
	  if(~chalEn) begin
		 challenge <= 0;
	  end else begin
			if (wrEn) begin
				 case(inId)
					  //3: challenge[63:0] <= dataIn_64;
						  
					  //2: challenge[127:64] <= dataIn_64;
						  
					  //1: challenge[63:0] <= dataIn_64;
								
					  0: challenge[63:0] <= dataIn_64;

				 endcase
			  end else begin
					challenge <= challenge;
			  end // else wrEn
	  end // else chalEn
	end // always
   
	 
	///////////////////////////////////////////////////////////////////////
   //   PICBLAZE MICRO-CONTROLLER (8-Bit)
	///////////////////////////////////////////////////////////////////////
	
	(* KEEP_HIERARCHY = "TRUE" *)
	puf_controller #(.CLOCK_FRE(CLOCK_FRE), .BAUD_RATE(BAUD_RATE)) PUF_CU (
        .clk(clk),
        .response_ready(respReady),
        .RESP_1_PORT(respBit),
        .RESP_2_PORT(respBitA[7:0]),
        .RESP_3_PORT(),
        .RESP_4_PORT(),
        .RESP_5_PORT(),
        .RESP_6_PORT(),
        .RESP_7_PORT(),
        .RESP_8_PORT(),
        .RESP_9_PORT(),
        .RESP_10_PORT(),
        .RESP_11_PORT(),
        .RESP_12_PORT(),
        .RESP_13_PORT(),
        .RESP_14_PORT(),
        .RESP_15_PORT(),
        .RESP_16_PORT(),
        .rx(rx),
        .tx(tx),
        .CHAl_1_PORT(chal_1),
        .CHAl_2_PORT(chal_2),
        .CHAl_3_PORT(chal_3),
        .CHAl_4_PORT(chal_4),
        .CHAl_5_PORT(chal_5),
        .CHAl_6_PORT(chal_6),
        .CHAl_7_PORT(chal_7),
        .CHAl_8_PORT(chal_8),
        .CHAl_9_PORT(chal_9),
        .CHAl_10_PORT(tigSig_t),
        .CHAl_11_PORT(),
        .CHAl_12_PORT(),
        .CHAl_13_PORT(),
        .CHAl_14_PORT(),
        .CHAl_15_PORT(), // First byte in matlab program
        .CHAl_16_PORT(wrEn),
        .CHAL_EN_PORT(chalEn),
        .PUF_START_PORT()			
	);

endmodule
module switchChain #( parameter nStage = 16)(
      inT,
		inB,
		c,
		outT,
		outB
	);
	
	input inT,inB;
	input [nStage-1:0]  c;
	output outT;
	output outB;

	wire [nStage:0] netT;
	wire [nStage:0] netB;
	
	// Output signal from upper and lower paths
	assign outT = netT[nStage];
	assign outB = netB[nStage];
	
	// Input trigger signal for puf
	assign netT[0] = inT;
	assign netB[0] = inB;
	
	
	// Generate chain of switches
	genvar i;
	generate 
		for(i = 0; i < nStage; i = i + 1) begin:STAGE 
		
					//(*KEEP_HIERARCHY = "TRUE"*)				
					sw_dolut SW(
						.iT(netT[i]),
						.iB(netB[i]),
						.c(c[i]),
						.vcc(1'b1),
						.oT(netT[i+1]),
						.oB(netB[i+1])
					);
				
		end
	endgenerate
		
endmodule
module dflop(clk,din,dout);
	
	input clk;
	input din;
	output reg dout;
    
	always @(posedge clk) begin
		dout <= din;	
	end
	
endmodule
module nandLatch(s,r,q,qbar);

	input s,r;
	output q,qbar;
	
	
	(*KEEP_HIERARCHY = "TRUE"*)
    LUT2 #(.INIT(4'b0111)) X(
        .O(q), 
        .I0(s),
		  .I1(qbar)
    );
	 
	 (*KEEP_HIERARCHY = "TRUE"*)
    LUT2 #(.INIT(4'b0111)) Y(
        .O(qbar), 
        .I0(r),
		  .I1(q)
    );
	 
endmodule
module dcm_25MHz
 (// Clock in ports
  input         clk,
  // Clock out ports
  output        clk_out,
  // Status and control signals
  input         RESET,
  output        LOCKED
 );

  // Input buffering
  //------------------------------------
  assign clkin1 = clk;


  // Clocking primitive
  //------------------------------------

  // Instantiation of the DCM primitive
  //    * Unused inputs are tied off
  //    * Unused outputs are labeled unused
  wire        psdone_unused;
  wire        locked_int;
  wire [7:0]  status_int;
  wire clkfb;
  wire clk0;
  wire clkdv;

  DCM_SP
  #(.CLKDV_DIVIDE          (2.000),
    .CLKFX_DIVIDE          (1),
    .CLKFX_MULTIPLY        (4),
    .CLKIN_DIVIDE_BY_2     ("FALSE"),
    .CLKIN_PERIOD          (20.0),
    .CLKOUT_PHASE_SHIFT    ("NONE"),
    .CLK_FEEDBACK          ("1X"),
    .DESKEW_ADJUST         ("SYSTEM_SYNCHRONOUS"),
    .PHASE_SHIFT           (0),
    .STARTUP_WAIT          ("FALSE"))
  dcm_sp_inst
    // Input clock
   (.CLKIN                 (clkin1),
    .CLKFB                 (clkfb),
    // Output clocks
    .CLK0                  (clk0),
    .CLK90                 (),
    .CLK180                (),
    .CLK270                (),
    .CLK2X                 (),
    .CLK2X180              (),
    .CLKFX                 (),
    .CLKFX180              (),
    .CLKDV                 (clkdv),
    // Ports for dynamic phase shift
    .PSCLK                 (1'b0),
    .PSEN                  (1'b0),
    .PSINCDEC              (1'b0),
    .PSDONE                (),
    // Other control and status signals
    .LOCKED                (locked_int),
    .STATUS                (status_int),
 
    .RST                   (RESET),
    // Unused pin- tie low
    .DSSEN                 (1'b0));

    assign LOCKED = locked_int;

  // Output buffering
  //-----------------------------------
  BUFG clkf_buf
   (.O (clkfb),
    .I (clk0));

  BUFG clkout1_buf
   (.O   (clk_out),
    .I   (clkdv));




endmodule
module dual_port_sync
	#(
		parameter ADDR_WIDTH=11, //2k by 8 dual port synchronous ram(16k block ram)
					 DATA_WIDTH=8
	)
	(
		input clk_r,
		input clk_w,
		input we, 
		input[DATA_WIDTH-1:0] din,
		input[ADDR_WIDTH-1:0] addr_a,addr_b, //addr_a for write, addr_b for read
		output[DATA_WIDTH-1:0] dout
	);
	
	reg[DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
	reg[ADDR_WIDTH-1:0] addr_b_q;
	
	always @(posedge clk_w) begin
		if(we) ram[addr_a]<=din;
	end
	always @(posedge clk_r) begin
		addr_b_q<=addr_b;	
	end
	assign dout=ram[addr_b_q];
	
endmodule
module vga_interface(
	input wire clk,rst_n,
	input wire sobel,
	//asyn_fifo IO
	input wire empty_fifo,
	input wire[15:0] din,
	output wire clk_vga,
	output reg rd_en,
	input[7:0] threshold,
	//VGA output
	output reg[4:0] vga_out_r,
	output reg[5:0] vga_out_g,
	output reg[4:0] vga_out_b,
	output wire vga_out_vs,vga_out_hs
    );
	 //FSM state declarations
	 localparam delay=0,
					idle=1,
					display=2;
					
	 reg[1:0] state_q,state_d;
	 wire[11:0] pixel_x,pixel_y;

	 //register operations
	 always @(posedge clk_out,negedge rst_n) begin
		if(!rst_n) begin
			state_q<=delay;
		end
		else begin
			state_q<=state_d;
		end
	 end
	 
	 //FSM next-state logic
	 always @* begin
	 state_d=state_q;
	 rd_en=0;
	 vga_out_r=0;
	 vga_out_g=0;
	 vga_out_b=0;
			
		case(state_q)
		  delay: if(pixel_x==1 && pixel_y==1) state_d=idle; //delay of one frame(33ms) needed to start up the camera
			idle:  if(pixel_x==1 && pixel_y==0 && !empty_fifo) begin //wait for pixel-data coming from asyn_fifo 
							if(sobel) begin //display for sobel edge detection depends on the threshold value
								vga_out_r=(din>threshold)?5'b111_11:0;
								vga_out_g=(din>threshold)?6'b111_111:0;
								vga_out_b=(din>threshold)?5'b111_11:0;
							end
							else begin //normal raw video output
								vga_out_r=din[15:11];
								vga_out_g=din[10:5];
								vga_out_b=din[4:0];
							end
							rd_en=1;	
							state_d=display;
					end
		display: if(pixel_x>=1 && pixel_x<=640 && pixel_y<480) begin //we will continue to read the asyn_fifo as long as current pixel coordinate is inside the visible screen(640x480) 
							if(sobel) begin
								vga_out_r=(din>threshold)?5'b111_11:0;
								vga_out_g=(din>threshold)?6'b111_111:0;
								vga_out_b=(din>threshold)?5'b111_11:0;
							end
							else begin
								vga_out_r=din[15:11];
								vga_out_g=din[10:5];
								vga_out_b=din[4:0];
							end
							rd_en=1;	
					end
			idle: state_d=delay;
		endcase
	 end
 
	 
	assign clk_vga=clk_out;
	
	//module instantiations
	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(),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
	);	
	 dcm_25MHz m1 //clock for vga(620x480 60fps) 
   (// Clock in ports
    .clk(clk),      // IN
    // Clock out ports
    .clk_out(clk_out),     // OUT
    // Status and control signals
    .RESET(RESET),// IN
    .LOCKED(LOCKED));      // OUT
	 


endmodule
module debounce_explicit(
	input wire clk,rst_n,
	input wire 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 dcm_165MHz
 (// Clock in ports
  input         clk,
  // Clock out ports
  output        clk_sdram,
  // Status and control signals
  input         RESET,
  output        LOCKED
 );

  // Input buffering
  //------------------------------------
  assign clkin1 = clk;


  // Clocking primitive
  //------------------------------------

  // Instantiation of the DCM primitive
  //    * Unused inputs are tied off
  //    * Unused outputs are labeled unused
  wire        psdone_unused;
  wire        locked_int;
  wire [7:0]  status_int;
  wire clkfb;
  wire clk0;
  wire clkfx;

  DCM_SP
  #(.CLKDV_DIVIDE          (2.000),
    .CLKFX_DIVIDE          (1),
    .CLKFX_MULTIPLY        (3),
    .CLKIN_DIVIDE_BY_2     ("FALSE"),
    .CLKIN_PERIOD          (20.0),
    .CLKOUT_PHASE_SHIFT    ("NONE"),
    .CLK_FEEDBACK          ("1X"),
    .DESKEW_ADJUST         ("SYSTEM_SYNCHRONOUS"),
    .PHASE_SHIFT           (0),
    .STARTUP_WAIT          ("FALSE"))
  dcm_sp_inst
    // Input clock
   (.CLKIN                 (clkin1),
    .CLKFB                 (clkfb),
    // Output clocks
    .CLK0                  (clk0),
    .CLK90                 (),
    .CLK180                (),
    .CLK270                (),
    .CLK2X                 (),
    .CLK2X180              (),
    .CLKFX                 (clkfx),
    .CLKFX180              (),
    .CLKDV                 (),
    // Ports for dynamic phase shift
    .PSCLK                 (1'b0),
    .PSEN                  (1'b0),
    .PSINCDEC              (1'b0),
    .PSDONE                (),
    // Other control and status signals
    .LOCKED                (locked_int),
    .STATUS                (status_int),
 
    .RST                   (RESET),
    // Unused pin- tie low
    .DSSEN                 (1'b0));

    assign LOCKED = locked_int;

  // Output buffering
  //-----------------------------------
  BUFG clkf_buf
   (.O (clkfb),
    .I (clk0));

  BUFG clkout1_buf
   (.O   (clk_sdram),
    .I   (clkfx));




endmodule
module dcm_24MHz
 (// Clock in ports
  input         clk,
  // Clock out ports
  output        cmos_xclk,
  // Status and control signals
  input         RESET,
  output        LOCKED
 );

  // Input buffering
  //------------------------------------
  assign clkin1 = clk;


  // Clocking primitive
  //------------------------------------

  // Instantiation of the DCM primitive
  //    * Unused inputs are tied off
  //    * Unused outputs are labeled unused
  wire        psdone_unused;
  wire        locked_int;
  wire [7:0]  status_int;
  wire clkfb;
  wire clk0;
  wire clkfx;

  DCM_SP
  #(.CLKDV_DIVIDE          (2.000),
    .CLKFX_DIVIDE          (25),
    .CLKFX_MULTIPLY        (12),
    .CLKIN_DIVIDE_BY_2     ("FALSE"),
    .CLKIN_PERIOD          (20.0),
    .CLKOUT_PHASE_SHIFT    ("NONE"),
    .CLK_FEEDBACK          ("1X"),
    .DESKEW_ADJUST         ("SYSTEM_SYNCHRONOUS"),
    .PHASE_SHIFT           (0),
    .STARTUP_WAIT          ("FALSE"))
  dcm_sp_inst
    // Input clock
   (.CLKIN                 (clkin1),
    .CLKFB                 (clkfb),
    // Output clocks
    .CLK0                  (clk0),
    .CLK90                 (),
    .CLK180                (),
    .CLK270                (),
    .CLK2X                 (),
    .CLK2X180              (),
    .CLKFX                 (clkfx),
    .CLKFX180              (),
    .CLKDV                 (),
    // Ports for dynamic phase shift
    .PSCLK                 (1'b0),
    .PSEN                  (1'b0),
    .PSINCDEC              (1'b0),
    .PSDONE                (),
    // Other control and status signals
    .LOCKED                (locked_int),
    .STATUS                (status_int),
 
    .RST                   (RESET),
    // Unused pin- tie low
    .DSSEN                 (1'b0));

    assign LOCKED = locked_int;

  // Output buffering
  //-----------------------------------
  BUFG clkf_buf
   (.O (clkfb),
    .I (clk0));

  BUFG clkout1_buf
   (.O   (cmos_xclk),
    .I   (clkfx));




endmodule
module vga_core(
	input wire clk,rst_n, //clock must be 25MHz for 640x480 30fps
	output wire hsync,vsync,
	output reg video_on,
	output wire[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 vga_interface(
	input wire clk,rst_n,
	//asyn_fifo IO
	input wire empty_fifo,
	input wire[15:0] din,
	output wire clk_vga,
	output reg rd_en,
	input[7:0] threshold,
	//VGA output
	output reg[4:0] vga_out_r,
	output reg[5:0] vga_out_g,
	output reg[4:0] vga_out_b,
	output wire vga_out_vs,vga_out_hs
    );
	 //FSM state declarations
	 localparam delay=0,
					idle=1,
					display=2;
					
	 reg[1:0] state_q,state_d;
	 wire[11:0] pixel_x,pixel_y;

	 //register operations
	 always @(posedge clk_out,negedge rst_n) begin
		if(!rst_n) begin
			state_q<=delay;
		end
		else begin
			state_q<=state_d;
		end
	 end
	 
	 //FSM next-state logic
	 always @* begin
	 state_d=state_q;
	 rd_en=0;
	 vga_out_r=0;
	 vga_out_g=0;
	 vga_out_b=0;
			
		case(state_q)
		  delay: if(pixel_x==1 && pixel_y==1) state_d=idle; //delay of one frame(33ms) needed to start up the camera
			idle:  if(pixel_x==1 && pixel_y==0 && !empty_fifo) begin //wait for pixel-data coming from asyn_fifo 
							vga_out_r=(din>threshold)?5'b111_11:0;
							vga_out_g=(din>threshold)?6'b111_111:0;
							vga_out_b=(din>threshold)?5'b111_11:0;
							rd_en=1;	
							state_d=display;
					end
		display: if(pixel_x>=1 && pixel_x<=640 && pixel_y<480) begin //we will continue to read the asyn_fifo as long as current pixel coordinate is inside the visible screen(640x480) 
							vga_out_r=(din>threshold)?5'b111_11:0;
							vga_out_g=(din>threshold)?6'b111_111:0;
							vga_out_b=(din>threshold)?5'b111_11:0;
							rd_en=1;	
							
							/*vga_out_r=din[4:0]; //grayscale output
							vga_out_g=din[4:0]<<1;
							vga_out_b=din[4:0]*/
					end
			idle: state_d=delay;
		endcase
	 end
 
	 
	assign clk_vga=clk_out;
	
	//module instantiations
	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(),
		.pixel_x(pixel_x),
		.pixel_y(pixel_y)
	);	
	 dcm_25MHz m1 //clock for vga(620x480 60fps) 
   (// Clock in ports
    .clk(clk),      // IN
    // Clock out ports
    .clk_out(clk_out),     // OUT
    // Status and control signals
    .RESET(RESET),// IN
    .LOCKED(LOCKED));      // OUT
	 


endmodule
module baud_generator#(parameter N=163,N_width=8)
	(
	input clk,rst_n,
	output reg s_tick
    );
	 reg[N_width-1:0] counter=0;
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) counter<=0;
		else begin
			s_tick=0;
			if(counter==N-1) begin
				s_tick=1;
				counter<=0;
			end
			else begin
				counter<=counter+1;
			end
			
		end
	 end
	 
endmodule
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_done,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),
		.dout(rd_data)
    );
	 
	 
	 fifo #(.W(FIFO_W),.B(DBIT)) m2
	(
		.clk(clk),
		.rst_n(rst_n),
		.wr(),
		.rd(),
		.wr_data(),
		.rd_data(),
		.full(),
		.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 fifo
	#(parameter W=4,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
    );
	 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 uart_rx #(parameter DBIT=8,SB_TICK=16) //DBIT=data bits , SB_TICK=ticks for stop bit (16 for 1 bit ,32 for 2 bits)
	(
		input clk,rst_n,
		input rx,
		input s_tick,
		output reg rx_done_tick,
		output[7:0] dout
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'b00,
							start=2'b01,
							data=2'b10,
							stop=2'b11;
	 reg[1:0] state_reg,state_nxt;
	 reg[3:0] s_reg,s_nxt; //check if number of ticks is 7(middle of start bit), or 15(middle of a data bit)
	 reg[2:0] n_reg,n_nxt; //checks how many data bits is already passed(value is 7 for last bit)
	 reg[7:0] b_reg,b_nxt; //stores 8-bit binary value of received data bits
	 //FSM register operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			s_reg<=0;
			n_reg<=0;
			b_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			s_reg<=s_nxt;
			n_reg<=n_nxt;
			b_reg<=b_nxt;		
		end
	 end
	 //FSM next-state logic
	 always @* begin
		state_nxt=state_reg;
		s_nxt=s_reg;
		n_nxt=n_reg;
		b_nxt=b_reg;
		rx_done_tick=0;
		case(state_reg)
			 idle: if(rx==0) begin //wait for start bit(rx of zero)
						s_nxt=0;
						state_nxt=start;
					 end						
			start: if(s_tick==1) begin //wait for middle of start bit
						if(s_reg==7) begin
							s_nxt=0;
							n_nxt=0;
							state_nxt=data;
						end
						else s_nxt=s_reg+1;
					 end
		    data: if(s_tick==1) begin //wait to pass all middle points of every data bits
						if(s_reg==15) begin
							b_nxt={rx,b_reg[7:1]};
							s_nxt=0;
							if(n_reg==DBIT-1) state_nxt=stop;
							else n_nxt=n_reg+1;
						end
						else s_nxt=s_reg+1;
					 end
			 stop: if(s_tick==1) begin  //wait to pass the required stop bits
						if(s_reg==SB_TICK-1) begin
							rx_done_tick=1;
							state_nxt=idle;
						end
  						else s_nxt=s_reg+1;
					 end	
		 default: state_nxt=idle;
		endcase
	 end
	 assign dout=b_reg;
endmodule
module dcm_165MHz
 (// Clock in ports
  input         clk,
  // Clock out ports
  output        clk_sdram,
  // Status and control signals
  input         RESET,
  output        LOCKED
 );

  // Input buffering
  //------------------------------------
  assign clkin1 = clk;


  // Clocking primitive
  //------------------------------------

  // Instantiation of the DCM primitive
  //    * Unused inputs are tied off
  //    * Unused outputs are labeled unused
  wire        psdone_unused;
  wire        locked_int;
  wire [7:0]  status_int;
  wire clkfb;
  wire clk2x;

  DCM_SP
  #(.CLKDV_DIVIDE          (2.000),
    .CLKFX_DIVIDE          (1),
    .CLKFX_MULTIPLY        (4),
    .CLKIN_DIVIDE_BY_2     ("FALSE"),
    .CLKIN_PERIOD          (20.0),
    .CLKOUT_PHASE_SHIFT    ("NONE"),
    .CLK_FEEDBACK          ("2X"),
    .DESKEW_ADJUST         ("SYSTEM_SYNCHRONOUS"),
    .PHASE_SHIFT           (0),
    .STARTUP_WAIT          ("FALSE"))
  dcm_sp_inst
    // Input clock
   (.CLKIN                 (clkin1),
    .CLKFB                 (clkfb),
    // Output clocks
    .CLK0                  (),
    .CLK90                 (),
    .CLK180                (),
    .CLK270                (),
    .CLK2X                 (clk2x),
    .CLK2X180              (),
    .CLKFX                 (),
    .CLKFX180              (),
    .CLKDV                 (),
    // Ports for dynamic phase shift
    .PSCLK                 (1'b0),
    .PSEN                  (1'b0),
    .PSINCDEC              (1'b0),
    .PSDONE                (),
    // Other control and status signals
    .LOCKED                (locked_int),
    .STATUS                (status_int),
 
    .RST                   (RESET),
    // Unused pin- tie low
    .DSSEN                 (1'b0));

    assign LOCKED = locked_int;

  // Output buffering
  //-----------------------------------
  BUFG clkf_buf
   (.O (clkfb),
    .I (clk2x));

  BUFG clkout1_buf
   (.O   (clk_sdram),
    .I   (clk2x));




endmodule
module top_module(
	input wire clk,rst_n,
	input[1:0] key, //control threshold value
	input rx, //UART input
	//controller to sdram
	output wire sdram_clk,
	output wire sdram_cke, 
	output wire sdram_cs_n, sdram_ras_n, sdram_cas_n, sdram_we_n, 
	output wire[12:0] sdram_addr,
	output wire[1:0] sdram_ba, 
	output wire[1:0] sdram_dqm, 
	inout[15:0] sdram_dq,
	//VGA output
	output wire[4:0] vga_out_r,
	output wire[5:0] vga_out_g,
	output wire[4:0] vga_out_b,
	output wire vga_out_vs,vga_out_hs
    );
	 
	 wire f2s_data_valid;
	 wire[15:0] din;
	 wire[7:0] dout;
	 wire clk_sdram;
	 wire empty_fifo;
	 wire clk_vga;
	 wire state;
	 wire rd_en,rd_fifo,key1_tick,key2_tick,rx_empty;
	 reg[7:0] threshold=0;

	//threshold controller for sobel edge detection
	always @(posedge clk) begin
		if(!rst_n) threshold=0;
		else begin
			threshold=key1_tick? threshold+1:threshold;
			threshold=key2_tick? threshold-1:threshold;
		end
	end

	
	 //module instantiations
	 sdram_interface m1 //control logic for writing the pixel-data from edge detected image to sdram and reading pixel-data from sdram to vga
	 (
		.clk(clk_sdram),
		.rst_n(rst_n),
		.clk_vga(clk_vga),
		.rd_en(rd_en),
		//UART fifo IO
		.rx_done(rx_done),
		.din(dout),
		.rd_fifo(),
		//VGA fifo IO
		.empty_fifo(empty_fifo),
		.dout(din),
		//controller to sdram
		.sdram_cke(sdram_cke), 
		.sdram_cs_n(sdram_cs_n),
		.sdram_ras_n(sdram_ras_n),
		.sdram_cas_n(sdram_cas_n),
		.sdram_we_n(sdram_we_n), 
		.sdram_addr(sdram_addr),
		.sdram_ba(sdram_ba), 
		.sdram_dqm(sdram_dqm),
		.sdram_dq(sdram_dq)
    );
	 
	 vga_interface m2 //control logic for retrieving data from sdram, storing data to asyn_fifo, and sending data to vga
	 (
		.clk(clk),
		.rst_n(rst_n),
		//asyn_fifo IO
		.empty_fifo(empty_fifo),
		.din(din),
		.clk_vga(clk_vga),
		.rd_en(rd_en),
		.threshold(threshold),
		//VGA output
		.vga_out_r(vga_out_r),
		.vga_out_g(vga_out_g),
		.vga_out_b(vga_out_b),
		.vga_out_vs(vga_out_vs),
		.vga_out_hs(vga_out_hs)
    );
	 
	uart #(.DBIT(8),.SB_TICK(16),.DVSR(100),.DVSR_WIDTH(7),.FIFO_W(5)) m3 //Baud rate of 100_000(115_200 produce errors). Computation: DVSR=clk_freq/(16*BaudRate)
	(
		.clk(clk_sdram),
		.rst_n(rst_n),
		.rd_uart(),
		.wr_uart(),
		.wr_data(),
		.rx(rx),
		.tx(),
		.rd_data(dout),
		.rx_done(rx_done),
		.tx_full()
    );
	 
	debounce_explicit m4
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw({!key[0]}),
		.db_level(),
		.db_tick(key1_tick)
    );
	 
	 debounce_explicit m5
	(
		.clk(clk),
		.rst_n(rst_n),
		.sw({!key[1]}),
		.db_level(),
		.db_tick(key2_tick)
    );
	 
	 
	//SDRAM clock
	dcm_165MHz m6
   (// Clock in ports
    .clk(clk),      // IN
    // Clock out ports
    .clk_sdram(clk_sdram),     // OUT
    // Status and control signals
    .RESET(RESET),// IN
    .LOCKED(LOCKED));      // OUT





	//ERROR APPEARS IF ODDR2 IS ROUTED INSIDE THE FPGA INSTEAD OF BEING DIRECTLY CONNECTED TO OUTPUT (so we bring this outside)
	 ODDR2#(.DDR_ALIGNMENT("NONE"), .INIT(1'b0),.SRTYPE("SYNC")) oddr2_primitive
	 (
		.D0(1'b0),
		.D1(1'b1),
		.C0(clk_sdram),
		.C1(~clk_sdram),
		.CE(1'b1),
		.R(1'b0),
		.S(1'b0),
		.Q(sdram_clk)
	);
	
	

endmodule
module uart_tx #(parameter DBIT=8, SB_TICK=16)
	(
		input clk,rst_n,
		input s_tick, tx_start,
		input[7:0] din,
		output reg tx_done_tick,
		output tx
    );
	 //FSM state declarations
	 localparam[1:0] idle=2'd0,
							start=2'd1,
							data=2'd2,
							stop=2'd3;
	 reg[1:0] state_reg,state_nxt;
	 reg[3:0] s_reg,s_nxt; //count to 16 for every data bit
	 reg[2:0] n_reg,n_nxt; //count the number of data bits already transmitted
	 reg[7:0] din_reg,din_nxt; //stores the word to be transmitted
	 reg tx_reg,tx_nxt;
	 //FSM register operation
	 always @(posedge clk,negedge rst_n) begin
		if(!rst_n) begin
			state_reg<=idle;
			s_reg<=0;
			n_reg<=0;
			din_reg<=0;
			tx_reg<=0;
		end
		else begin
			state_reg<=state_nxt;
			s_reg<=s_nxt;
			n_reg<=n_nxt;
			din_reg<=din_nxt;
			tx_reg<=tx_nxt;
		end
	 end
	 //FSM next-state logic
	 always @* begin
		 state_nxt=state_reg;
		 s_nxt=s_reg;
		 n_nxt=n_reg;
		 din_nxt=din_reg;
		 tx_nxt=tx_reg;
		 tx_done_tick=0;
		 case(state_reg)
				idle: begin //wait for the buffer to have at least one word stored
							tx_nxt=1;
							if(tx_start==0) begin //tx_start is  connected to the inverted empty port of fifo buffer
								din_nxt=din;
								s_nxt=0;
								state_nxt=start;
							end
						end
			  start: begin   //wait to finish the start bit
							tx_nxt=0;
							if(s_tick==1) begin
								if(s_reg==15) begin
									s_nxt=0;
									n_nxt=0;
									state_nxt=data;
								end
								else s_nxt=s_reg+1;
							end
						end
				data: begin  //wait for all data bits to be transmitted serially
							tx_nxt=din_reg[0];
							if(s_tick==1) begin
								if(s_reg==15) begin
									din_nxt=din_reg>>1;
									s_nxt=0;
									if(n_reg==DBIT-1) state_nxt=stop;
									else n_nxt=n_reg+1;
								end
								else s_nxt=s_reg+1;
							end
						end
				stop: begin  //wait to finish the stop bit
							tx_nxt=1;
							if(s_tick==1) begin
								if(s_reg==SB_TICK-1) begin
									tx_done_tick=1;
									state_nxt=idle;
								end
								else s_nxt=s_reg+1;
							end
						end
			default: state_nxt=idle;
		 endcase
	 end
	 assign tx=tx_reg;
	 
	 
 


endmodule
module FloatingAddition #(parameter XLEN=32)
                        (input [XLEN-1:0]A,
                         input [XLEN-1:0]B,
                         input clk,
                         output overflow,
                         output underflow,
                         output exception,
                         output reg  [XLEN-1:0] result);

reg [23:0] A_Mantissa,B_Mantissa;
reg [23:0] Temp_Mantissa;
reg [22:0] Mantissa;
reg [7:0] Exponent;
reg Sign;
wire MSB;
reg [7:0] A_Exponent,B_Exponent,Temp_Exponent,diff_Exponent;
reg A_sign,B_sign,Temp_sign;
reg [32:0] Temp;
reg carry;
reg [2:0] one_hot;
reg comp;
reg [7:0] exp_adjust;
always @(*)
begin

comp =  (A[30:23] >= B[30:23])? 1'b1 : 1'b0;
  
A_Mantissa = comp ? {1'b1,A[22:0]} : {1'b1,B[22:0]};
A_Exponent = comp ? A[30:23] : B[30:23];
A_sign = comp ? A[31] : B[31];
  
B_Mantissa = comp ? {1'b1,B[22:0]} : {1'b1,A[22:0]};
B_Exponent = comp ? B[30:23] : A[30:23];
B_sign = comp ? B[31] : A[31];

diff_Exponent = A_Exponent-B_Exponent;
B_Mantissa = (B_Mantissa >> diff_Exponent);
{carry,Temp_Mantissa} =  (A_sign ~^ B_sign)? A_Mantissa + B_Mantissa : A_Mantissa-B_Mantissa ; 
exp_adjust = A_Exponent;
if(carry)
    begin
        Temp_Mantissa = Temp_Mantissa>>1;
        exp_adjust = exp_adjust+1'b1;
    end
else
    begin
    while(!Temp_Mantissa[23])
        begin
           Temp_Mantissa = Temp_Mantissa<<1;
           exp_adjust =  exp_adjust-1'b1;
        end
    end
Sign = A_sign;
Mantissa = Temp_Mantissa[22:0];
Exponent = exp_adjust;
result = {Sign,Exponent,Mantissa};
//Temp_Mantissa = (A_sign ~^ B_sign) ? (carry ? Temp_Mantissa>>1 : Temp_Mantissa) : (0); 
//Temp_Exponent = carry ? A_Exponent + 1'b1 : A_Exponent; 
//Temp_sign = A_sign;
//result = {Temp_sign,Temp_Exponent,Temp_Mantissa[22:0]};
end
endmodule
module FloatingMultiplication #(parameter XLEN=32)
                                (input [XLEN-1:0]A,
                                 input [XLEN-1:0]B,
                                 input clk,
                                 output overflow,
                                 output underflow,
                                 output exception,
                                 output reg  [XLEN-1:0] result);

reg [23:0] A_Mantissa,B_Mantissa;
reg [22:0] Mantissa;
reg [47:0] Temp_Mantissa;
reg [7:0] A_Exponent,B_Exponent,Temp_Exponent,diff_Exponent,Exponent;
reg A_sign,B_sign,Sign;
reg [32:0] Temp;
reg [6:0] exp_adjust;
always@(*)
begin
A_Mantissa = {1'b1,A[22:0]};
A_Exponent = A[30:23];
A_sign = A[31];
  
B_Mantissa = {1'b1,B[22:0]};
B_Exponent = B[30:23];
B_sign = B[31];

Temp_Exponent = A_Exponent+B_Exponent-127;
Temp_Mantissa = A_Mantissa*B_Mantissa;
Mantissa = Temp_Mantissa[47] ? Temp_Mantissa[46:24] : Temp_Mantissa[45:23];
Exponent = Temp_Mantissa[47] ? Temp_Exponent+1'b1 : Temp_Exponent;
Sign = A_sign^B_sign;
result = {Sign,Exponent,Mantissa};
end
endmodule
module FloatingDivision#(parameter XLEN=32)
                        (input [XLEN-1:0]A,
                         input [XLEN-1:0]B,
                         input clk,
                         output overflow,
                         output underflow,
                         output exception,
                         output [XLEN-1:0] result);
                         
reg [23:0] A_Mantissa,B_Mantissa;
reg [22:0] Mantissa;
wire [7:0] exp;
reg [23:0] Temp_Mantissa;
reg [7:0] A_Exponent,B_Exponent,Temp_Exponent,diff_Exponent;
wire [7:0] Exponent;
reg [7:0] A_adjust,B_adjust;
reg A_sign,B_sign,Sign;
reg [32:0] Temp;
wire [31:0] temp1,temp2,temp3,temp4,temp5,temp6,temp7,debug;
wire [31:0] reciprocal;
wire [31:0] x0,x1,x2,x3;
reg [6:0] exp_adjust;
reg [XLEN-1:0] B_scaled; 
reg en1,en2,en3,en4,en5;
reg dummy;
/*----Initial value----*/
FloatingMultiplication M1(.A({{1'b0,8'd126,B[22:0]}}),.B(32'h3ff0f0f1),.clk(clk),.result(temp1)); //verified
assign debug = {1'b1,temp1[30:0]};
FloatingAddition A1(.A(32'h4034b4b5),.B({1'b1,temp1[30:0]}),.result(x0));

/*----First Iteration----*/
FloatingMultiplication M2(.A({{1'b0,8'd126,B[22:0]}}),.B(x0),.clk(clk),.result(temp2));
FloatingAddition A2(.A(32'h40000000),.B({!temp2[31],temp2[30:0]}),.result(temp3));
FloatingMultiplication M3(.A(x0),.B(temp3),.clk(clk),.result(x1));

/*----Second Iteration----*/
FloatingMultiplication M4(.A({1'b0,8'd126,B[22:0]}),.B(x1),.clk(clk),.result(temp4));
FloatingAddition A3(.A(32'h40000000),.B({!temp4[31],temp4[30:0]}),.result(temp5));
FloatingMultiplication M5(.A(x1),.B(temp5),.clk(clk),.result(x2));

/*----Third Iteration----*/
FloatingMultiplication M6(.A({1'b0,8'd126,B[22:0]}),.B(x2),.clk(clk),.result(temp6));
FloatingAddition A4(.A(32'h40000000),.B({!temp6[31],temp6[30:0]}),.result(temp7));
FloatingMultiplication M7(.A(x2),.B(temp7),.clk(clk),.result(x3));

/*----Reciprocal : 1/B----*/
assign Exponent = x3[30:23]+8'd126-B[30:23];
assign reciprocal = {B[31],Exponent,x3[22:0]};

/*----Multiplication A*1/B----*/
FloatingMultiplication M8(.A(A),.B(reciprocal),.clk(clk),.result(result));
endmodule
module FloatSqrtTBmodule #(parameter XLEN = 32);   
reg [XLEN-1:0] A;
reg overflow, underflow, exception;
wire [XLEN-1:0] result;
real  value;
FloatingSqrt F_Mult (.A(A),.result(result));

initial  
begin
A = 32'h41c80000;  // 25
#20
A = 32'h42040000;  // 33
#20
A = 32'h42aa0000;  // 85
#20
A = 32'h42b80000;  // 92
end

initial
begin
#15
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",5.0,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",5.744562646538029,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",9.219544457292887,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",9.591663046625438,value);
$finish;
end

endmodule
module FloatAdditionTB #(parameter XLEN = 32);
reg [XLEN-1:0] A,B;
reg clk;
reg overflow, underflow, exception;
wire [XLEN-1:0] result;
real  value;
FloatingAddition F_Add (.clk(clk),.A(A),.B(B),.result(result));

initial  
begin
A = 32'b0_10000000_10011001100110011001100;  // 3.2
B = 32'b0_10000001_00001100110011001100110;  // 4.2
#20
A = 32'b0_01111110_01010001111010111000010;  // 0.66
B = 32'b0_01111110_00000101000111101011100;  // 0.51
#20
A = 32'b1_01111110_00000000000000000000000;  // -0.5
B = 32'b1_10000001_10011001100110011001100;  // -6.4
#20
A = 32'b1_01111110_00000000000000000000000;  // -0.5
B = 32'b0_10000001_10011001100110011001100;  //  6.4
#20
A = 32'h4034b4b5;
B = 32'hbf70f0f1;
end

initial
begin
#15
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",3.2+4.2,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",0.66+0.51,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",-0.5-6.4,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",-0.5+6.4,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",2.82-0.94,value);
$finish;
end
endmodule
module FloatMultiplicationTb #(parameter XLEN = 32);   
reg [XLEN-1:0] A,B;
reg clk;
reg overflow, underflow, exception;
wire [XLEN-1:0] result;
real  value;
FloatingMultiplication F_Mult (.clk(clk),.A(A),.B(B),.result(result));

initial  
begin
A = 32'b0_10000000_10011001100110011001100;  // 3.2
B = 32'b0_10000001_00001100110011001100110;  // 4.2
//#20
//A = 32'b0_01111110_01010001111010111000010;  // 0.66
//B = 32'b0_01111110_00000101000111101011100;  // 0.51
#20
A = 32'b1_01111110_00000000000000000000000;  // -0.5
B = 32'b1_10000001_10011001100110011001100;  // -6.4
#20
A = 32'b1_01111110_00000000000000000000000;  // -0.5
B = 32'b0_10000001_10011001100110011001100;  //  6.4
#20
A = 32'h4034b4b5;
B = 32'hbf70f0f1;
end

initial
begin
#15
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",3.2*4.2,value);
//#20
//value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
//$display("Expected Value : %f Result : %f",0.66*0.51,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",(-0.5)*(-6.4),value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",(-0.5)*(6.4),value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",2.82*(-0.94),value);
$finish;
end

endmodule
module FloatDivisionTB #(parameter XLEN = 32);
reg [XLEN-1:0] A,B;
reg clk;
reg overflow, underflow, exception;
wire [XLEN-1:0] result;
real  value;
FloatingDivision F_Div (.clk(clk),.A(A),.B(B),.result(result));

initial  
begin
A = 32'b0_10000001_00001100110011001100110;  // 4.2 
B = 32'b0_10000000_10011001100110011001100;  // 3.2
#20
A = 32'b0_01111110_01010001111010111000010;  // 0.66
B = 32'b0_01111110_00000101000111101011100;  // 0.51
#20
A = 32'b1_10000001_10011001100110011001100;  // -6.4 
B = 32'b1_01111110_00000000000000000000000;  // -0.5
#20
A = 32'b0_10000001_10011001100110011001100;  // 6.4
B = 32'b1_01111110_00000000000000000000000;  // -0.5
#20
A = 32'h4034b4b5; //2.82
B = 32'hbf70f0f1; //0.94
end

initial
begin
#15
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",4.2/3.2,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",0.66/0.51,value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",(-6.4)/(-0.5),value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",6.4/(-0.5),value);
#20
value =(2**(result[30:23]-127))*($itor({1'b1,result[22:0]})/2**23)*((-1)**(result[31]));
$display("Expected Value : %f Result : %f",2.82/0.94,value);
$finish;
end
endmodule
module BaudRateGenerator  #(
    parameter CLOCK_RATE = 100000000, // board internal clock (def == 100MHz)
    parameter BAUD_RATE = 9600
)(
    input wire clk, // board clock
    output reg rxClk, // baud rate for rx
    output reg txClk // baud rate for tx
);
parameter MAX_RATE_RX = CLOCK_RATE / (2 * BAUD_RATE * 16); // 16x oversample
parameter MAX_RATE_TX = CLOCK_RATE / (2 * BAUD_RATE);
parameter RX_CNT_WIDTH = $clog2(MAX_RATE_RX);
parameter TX_CNT_WIDTH = $clog2(MAX_RATE_TX);

reg [RX_CNT_WIDTH - 1:0] rxCounter = 0;
reg [TX_CNT_WIDTH - 1:0] txCounter = 0;

initial begin
    rxClk = 1'b0;
    txClk = 1'b0;
end

always @(posedge clk) begin
    // rx clock
    if (rxCounter == MAX_RATE_RX[RX_CNT_WIDTH-1:0]) begin
        rxCounter <= 0;
        rxClk <= ~rxClk;
    end else begin
        rxCounter <= rxCounter + 1'b1;
    end
    // tx clock
    if (txCounter == MAX_RATE_TX[TX_CNT_WIDTH-1:0]) begin
        txCounter <= 0;
        txClk <= ~txClk;
    end else begin
        txCounter <= txCounter + 1'b1;
    end
end

endmodule
module Uart8  #(
    parameter CLOCK_RATE = 100000000, // board internal clock
    parameter BAUD_RATE = 9600
)(
    input wire clk,

    // rx interface
    input wire rx,
    input wire rxEn,
    output wire [7:0] out,
    output wire rxDone,
    output wire rxBusy,
    output wire rxErr,

    // tx interface
    output wire tx,
    input wire txEn,
    input wire txStart,
    input wire [7:0] in,
    output wire txDone,
    output wire txBusy
);
wire rxClk;
wire txClk;

BaudRateGenerator #(
    .CLOCK_RATE(CLOCK_RATE),
    .BAUD_RATE(BAUD_RATE)
) generatorInst (
    .clk(clk),
    .rxClk(rxClk),
    .txClk(txClk)
);

Uart8Receiver rxInst (
    .clk(rxClk),
    .en(rxEn),
    .in(rx),
    .out(out),
    .done(rxDone),
    .busy(rxBusy),
    .err(rxErr)
);

Uart8Transmitter txInst (
    .clk(txClk),
    .en(txEn),
    .start(txStart),
    .in(in),
    .out(tx),
    .done(txDone),
    .busy(txBusy)
);

endmodule
module tcam_sdpram #(
	parameter ADDR_WIDTH = 8,
	parameter DATA_WIDTH = 8,
	parameter RAM_STYLE = "block"
)
(
	input wire clk,
	input wire rst,
	input wire [DATA_WIDTH-1:0]dina,
	input wire [ADDR_WIDTH-1:0]addra,
	input wire [ADDR_WIDTH-1:0]addrb,
	input wire wea,
	output wire [DATA_WIDTH-1:0]doutb
);

(* ram_style = RAM_STYLE *)
reg [DATA_WIDTH-1:0]ram[2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0]readb;
integer i;

assign doutb = readb;

initial begin
	for (i = 0; i < 2**ADDR_WIDTH; i = i + 1) begin
		ram[i] = 0;
	end
end

always @(posedge clk) begin
	if (wea) begin
		ram[addra] <= dina;
	end
	readb <= ram[addrb];
end

endmodule
module tcam_line_encoder #(
	parameter ADDR_WIDTH = 8
)
(
	input wire clk,
	input wire rst,
	input wire [2**ADDR_WIDTH-1:0]line_match,
	input wire line_valid,
	output wire [ADDR_WIDTH-1:0]addr,
	output wire addr_valid,
	output wire addr_null
);

reg encode;
reg [2**ADDR_WIDTH-1:0]line;
reg [ADDR_WIDTH-1:0]addr_out;
reg valid_out;
reg null_out;
integer i;

assign addr = addr_out;
assign addr_valid = valid_out;
assign addr_null = null_out;

always @(posedge clk) begin
	if (rst == 1'b1) begin
		encode <= 1'b0;
	end else begin
		if (encode == 1'b0) begin
			if (line_valid) begin
				line <= line_match;
				encode <= 1'b1;
			end
		end else begin
			if (line == 0) begin
				encode <= 1'b0;
			end else begin
				if ((line & ~(2**addr_out))) begin
					line[addr_out] <= 1'b0;
				end else begin
					encode <= 1'b0;
				end
			end
		end
	end
end

always @(*) begin
	addr_out = 0;
	valid_out = 1'b0;
	null_out = 1'b0;
	
	if (encode == 1'b1) begin
		if (line == 0) begin
			valid_out = 1'b1;
			null_out = 1'b1;
		end else begin
			for (i = 2**ADDR_WIDTH - 1; i >= 0; i = i - 1) begin
				if (line[i] == 1'b1) begin
					addr_out = i;
					valid_out = 1'b1;
				end
			end
		end
	end
end

endmodule