dakies/OSS_Verilog huggingface dataset:
module ACC(
	output [7:0] acc_out1,
	output [7:0] acc_out2,
	input [7:0] acc_in,
	input la_,
	input clk,
	input clr_
	);
	
	reg [7:0] q;
	
	always @(posedge clk)
		if (~clr_) q <= 8'b0;
		else if(~la_) q <= acc_in;	
	
	assign acc_out1 = q;
	assign acc_out2 = q;
	
endmodule
module ROM(
	output reg [7:0] rom_out,
	input [3:0] rom_in
	);
	
	always @(*)
	begin
		rom_out = 8'bx;
		case(rom_in)
			4'b0000: rom_out = 8'b0000_1001; //LDA
			4'b0001: rom_out = 8'b0001_1010; //ADD
			4'b0010: rom_out = 8'b0001_1011; //ADD
			4'b0011: rom_out = 8'b0010_1100; //SUB
			4'b0100: rom_out = 8'b1110_xxxx; //OUT
			4'b0101: rom_out = 8'b1111_xxxx; //HLT
			4'b0110: rom_out = 8'bxxxx_xxxx;
			4'b0111: rom_out = 8'bxxxx_xxxx;
			4'b1000: rom_out = 8'bxxxx_xxxx;
			4'b1001: rom_out = 8'b0001_0000;
			4'b1010: rom_out = 8'b0001_0100;
			4'b1011: rom_out = 8'b0001_1000;
			4'b1100: rom_out = 8'b0010_0000;	
		endcase
	end
	
endmodule
module BRegister(
	output reg [7:0] BRegister_out,
	input [7:0] BRegister_in,
	input lb_,
	input clk,
	input clr_
	);

	always @(posedge clk)
		if(~clr_) BRegister_out <= 8'b0;
		else if(~lb_) BRegister_out <= BRegister_in;	

endmodule
module ADDSUB(
	output [7:0] ADDSUB_out,
	input [7:0] ADDSUB_in1,
	input [7:0] ADDSUB_in2,
	input su
	);

	wire [7:0] d;
	
	assign d = su ? ADDSUB_in1 - ADDSUB_in2 : ADDSUB_in1 + ADDSUB_in2;
	assign ADDSUB_out = d;
	
endmodule
module SAPone(
	output wire [7:0] SAP_out,
	output wire [11:0] con,
	output reg [7:0] bus,
	input clk,
	input clr_
	);
	
	wire cp, ep, lm_, ce_, li_, ei_, la_, ea, su, eu, lb_, lo_;
	wire [7:0] acc_out2, BRegister_out, OutputRegister_out;
	wire [3:0] IR_out, mar_out;
	wire [4:0] bus_sel;
	wire [3:0] pc_out, oprand;
	wire [7:0] rom_out, acc_out1, ADDSUB_out;
	
	assign {cp, ep, lm_, ce_, li_, ei_, la_, ea, su, eu, lb_, lo_} = con;
	assign bus_sel = {ep, ce_, ei_, ea, eu};
	
	always@(*)
	begin
		case(bus_sel)
			5'b11100: bus[3:0] = pc_out;
			5'b00100: bus[7:0] = rom_out;
			5'b01000: bus[3:0] = oprand;
			5'b01110: bus[7:0] = acc_out1;
			5'b01101: bus[7:0] = ADDSUB_out;
			default:  bus[7:0] = 8'bx;
		endcase
	end
	
	PC pc1(
		.pc_out(pc_out),
		.cp(cp),
		.clk(clk),
		.clr_(clr_)
		);
		
	MAR mar1(
		.mar_out(mar_out),
		.mar_in(bus[3:0]),
		.lm_(lm_),
		.clk(clk),
		.clr_(clr_)
		);
		
	ROM roml(
		.rom_out(rom_out),
		.rom_in(mar_out)
		);
	
	IR ir1(
		.opcode(IR_out),
		.oprand(oprand),
		.IR_in(bus[7:0]),
		.li_(li_),
		.clk(clk),
		.clr_(clr_)
		);
	
	Controller cont1(
		.control_signals(con),
		.opcode(IR_out),
		.clk(clk),
		.clr_(clr_)
		); 

	ACC acc1(
		.acc_out1(acc_out1),
		.acc_out2(acc_out2),
		.acc_in(bus[7:0]),
		.la_(la_),
		.clk(clk),
		.clr_(clr_)
		);
			
	ADDSUB addsub1(
		.ADDSUB_out(ADDSUB_out),
		.ADDSUB_in1(acc_out2),
		.ADDSUB_in2(BRegister_out),
		.su(su)
		);
		
	BRegister bregister1(
		.BRegister_out(BRegister_out),
		.BRegister_in(bus[7:0]),
		.lb_(lb_),
		.clk(clk),
		.clr_(clr_)
		);
		
	OutputRegister outputregister1(
		.OutputRegister_out(SAP_out),
		.OutputRegister_in(bus[7:0]),
		.lo_(lo_),
		.clk(clk),
		.clr_(clr_)
		);			


endmodule
module IR(
	output [7:4] opcode,
	output [3:0] oprand,
	input wire [7:0] IR_in,
	input li_,
	input clk,
	input clr_
	);
	
	reg [7:0] q;

	always @(posedge clk)
	begin
		if(~clr_) q <=8'b0;
		else if(~li_) q <= IR_in;
	end
	
	assign opcode = q[7:4];
	assign oprand = q[3:0];

endmodule
module MAR(
	output reg [3:0] mar_out,
	input wire [3:0] mar_in,
	input lm_,
	input clk,
	input clr_
	);
	
	always @(posedge clk)
		if(~clr_) mar_out <= 4'b0;
		else if(~lm_) mar_out <= mar_in;	

endmodule
module Controller(
	output reg [11:0] control_signals,
	input [3:0] opcode,
	input clk,
	input clr_
	); 
	
	reg [3:0] ps, ns;
	
	always @(posedge clk)
	begin
		if(~clr_) ps <= 4'd0;
		else ps <= ns;
	end
	
	always @(*)
	begin
		case(ps)
			0:
			begin
				control_signals = 12'h3e3;
				ns = 4'd1;		
			end
			
			1: //T1
			begin
				control_signals = 12'h5e3;
				ns = 4'd2;	
			end
			
			2: //T2
			begin
//				control_signals = 12'hbe3;
				control_signals = 12'h863;
				ns = 4'd3;	
			end
			
			3: //T3
			begin
//				control_signals = 12'h263;
				control_signals = 12'h3e3;
				if(opcode == 4'd0) //LDA
					ns = 4'd4;
				else if(opcode == 4'd1) //ADD
					ns = 4'd6;
				else if(opcode == 4'd2) //SUB
					ns = 4'd9;
				else if(opcode == 4'd14) //OUT
					ns = 4'd12;
				else if(opcode == 4'd15) //HLT
					ns = 4'd13;
			end
			
			4: //LDA
			begin
				control_signals = 12'h1a3;
				ns = 4'd5;	
			end
			
			5: //LDA
			begin
				control_signals = 12'h2c3;
				ns = 4'd1;	
			end
			
			6: //ADD
			begin
				control_signals = 12'h1a3;
				ns = 4'd7;	
			end
			
			7: //ADD
			begin
				control_signals = 12'h2e1;
				ns = 4'd8;	
			end
			
			8: //ADD
			begin
				control_signals = 12'h3c7;
				ns = 4'd1;	
			end
			
			9: //SUB
			begin
				control_signals = 12'h1a3;
				ns = 4'd10;	
			end
			
			10: //SUB
			begin
				control_signals = 12'h2e1;
				ns = 4'd11;	
			end
			
			11: //SUB
			begin
				control_signals = 12'h3cf;
				ns = 4'd1;	
			end
			
			12: //OUT
			begin
				control_signals = 12'h3f2;
				ns = 4'd1;	
			end
			
			13: //HLT
				ns = 4'd13;	
			
			default: 
			begin
				ns = 4'd0;
				control_signals = 12'h3e3;
			end
		
		endcase
	end	
endmodule
module PC(
	output reg [3:0] pc_out,
	input cp,
	input clk,
	input clr_
	);
	
	always @(posedge clk)
	begin
		if(~clr_) pc_out <= 0;
		else if (cp) pc_out <= pc_out + 1;
	end
			
endmodule
module adder_4(cout, sum, a, b, cin);
parameter size = 4;  /* declare a parameter. default required */
output cout;
output [size-1:0] sum; 	 // sum uses the size parameter
input cin;
input [size-1:0] a, b;  // 'a' and 'b' use the size parameter

assign {cout, sum} = a + b + cin;

endmodule
module adder_6(cout, sum, a, b, cin);
parameter size = 6;  /* declare a parameter. default required */
output cout;
output [size-1:0] sum; 	 // sum uses the size parameter
input cin;
input [size-1:0] a, b;  // 'a' and 'b' use the size parameter

assign {cout, sum} = a + b + cin;

endmodule
module adder_16(cout, sum, a, b, cin);
parameter size = 6;  /* declare a parameter. default required */
output cout;
output [size-1:0] sum; 	 // sum uses the size parameter
input cin;
input [size-1:0] a, b;  // 'a' and 'b' use the size parameter

assign {cout, sum} = a + b + cin;

endmodule
module adder_8(cout, sum, a, b, cin);
parameter size = 8;  /* declare a parameter. default required */
output cout;
output [size-1:0] sum; 	 // sum uses the size parameter
input cin;
input [size-1:0] a, b;  // 'a' and 'b' use the size parameter

assign {cout, sum} = a + b + cin;

endmodule
module counter (
	clk,
	reset,
	result
);

	input clk;
	input reset;
	output [127:0] result;

	reg [127:0] result;

    initial begin
      result <= 0;
    end

	always @(posedge clk or posedge reset)
	begin
		if (reset) 
			result = 0;		
		else 
			result = result + 1;
	end
endmodule
module counter_tb;

  reg clk, reset;
  wire [127:0] result;

  counter DUT(
    .clk(clk), 
    .reset(reset), 
    .result(result)
  );
  
  initial begin
    #0 reset = 1'b1; clk = 1'b0;
    #100 reset = 1'b0;
  end

  always begin
    #10 clk = ~clk;
  end
  
  initial begin
    #5000 $stop;
  end

endmodule
module counter (
	clk,
	resetb,
	result
);

	input clk;
	input resetb;
	output [127:0] result;

	reg [127:0] result;

    initial begin
      result <= 0;
    end

	always @(posedge clk or negedge resetb)
	begin
		if (~resetb) 
			result = 0;		
		else 
			result = result + 1;
	end
endmodule
module counter(clk_counter, q_counter, rst_counter);

    input clk_counter;
    input rst_counter;
    output [7:0] q_counter;
    reg [7:0] q_counter;

    initial begin
      q_counter <= 0;
    end

    always @ (posedge clk_counter)
    begin
        if(rst_counter)
		q_counter <= 8'b00000000;
	else
		q_counter <= q_counter + 1;
    end

endmodule
module counter (
	clk,
	resetb,
	result
);

	input clk;
	input resetb;
	output [7:0] result;

	reg [7:0] result;

    initial begin
      result <= 0;
    end

	always @(posedge clk or negedge resetb)
	begin
		if (!resetb) 
			result = 0;		
		else 
			result = result + 1;
	end
endmodule
module counter_tb;

  reg clk, resetb;
  wire [7:0] result;

  counter DUT(
    .clk(clk), 
    .resetb(resetb), 
    .result(result)
  );
  
  initial begin
    #0 resetb = 1'b0; clk = 1'b0;
    #100 resetb = 1'b1;
  end

  always begin
    #10 clk = ~clk;
  end
  
  initial begin
    #5000 $stop;
  end

endmodule
module counter (
	clkn,
	reset,
	result
);

	input clkn;
	input reset;
	output [7:0] result;

	reg [7:0] result;

    initial begin
      result <= 0;
    end

	always @(negedge clkn or posedge reset)
	begin
		if (reset) 
			result = 0;		
		else 
			result = result + 1;
	end
endmodule
module counter_tb;

  reg clk, reset;
  wire [7:0] result;

  counter DUT(
    .clkn(clk), 
    .reset(reset), 
    .result(result)
  );
  
  initial begin
    #0 reset = 1'b1; clk = 1'b0;
    #100 reset = 1'b0;
  end

  always begin
    #10 clk = ~clk;
  end
  
  initial begin
    #5000 $stop;
  end

endmodule
module counter_4bit_2clock(clk0, rst, clk1, q0, q1);

    input clk0;
    input rst;
    output [3:0] q0;
    reg [3:0] q0;

    input clk1;
    output [3:0] q1;
    reg [3:0] q1;

    initial begin
      q0 <= 0;
      q1 <= 0;
    end

    always @ (posedge clk0)
    begin
        if(rst)
		q0 <= 4'b0000;
	else
		q0 <= q0 + 1;
    end

    always @ (posedge clk1)
    begin
        if(rst)
		q1 <= 4'b0000;
	else
		q1 <= q1 + 1;
    end

endmodule
module counter (
	clk,
	reset,
	result
);

	input clk;
	input reset;
	output [7:0] result;

	reg [7:0] result;

    initial begin
      result <= 0;
    end

	always @(posedge clk or posedge reset)
	begin
		if (reset) 
			result = 0;		
		else 
			result = result + 1;
	end
endmodule
module counter_tb;

  reg clk, reset;
  wire [7:0] result;

  counter DUT(
    .clk(clk), 
    .reset(reset), 
    .result(result)
  );
  
  initial begin
    #0 reset = 1'b1; clk = 1'b0;
    #100 reset = 1'b0;
  end

  always begin
    #10 clk = ~clk;
  end
  
  initial begin
    #5000 $stop;
  end

endmodule
module sync_dual_port_ram
		#( parameter ADDRESS_WIDTH = 4, // number of words in ram
                     DATA_WIDTH    =  4  // number of bits in word
	 )
	
	// IO ports
	(
		input wire clk,                                             // clk for synchronous read/write 
		input wire write_en,                                        // signal to enable synchronous write
		input wire [ADDRESS_WIDTH-1:0] read_address, write_address, // inputs for dual port addresses
		input wire [DATA_WIDTH-1:0] write_data_in,                  // input for data to write to ram
		output wire [DATA_WIDTH-1:0] read_data_out, write_data_out  // outputs for dual data ports
	);
	
	// internal signal declarations
	reg [DATA_WIDTH-1:0] ram [2**ADDRESS_WIDTH-1:0];             // ADDRESS_WIDTH x DATA_WIDTH RAM declaration
	reg [ADDRESS_WIDTH-1:0] read_address_reg, write_address_reg; // dual port address declarations
	
	// synchronous write and address update
	always @(posedge clk)
		begin
		if (write_en)  							 // if write enabled
		   ram[write_address] <= write_data_in; // write data to ram and write_address 
		    
                read_address_reg  <= read_address;      // store read_address to reg
	        write_address_reg <= write_address;     // store write_address to reg
	        end
	
	// assignments for two data out ports
	assign read_data_out  = ram[read_address_reg];
	assign write_data_out = ram[write_address_reg];
endmodule
module mac_8(a, b, c, out);
parameter DATA_WIDTH = 8;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_18(a, b, c, out);
parameter DATA_WIDTH = 18;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_20(a, b, c, out);
parameter DATA_WIDTH = 20;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_8_9(a, b, c, out);
parameter DATA_WIDTH = 18;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out[8:0] = a[8:0] * b[8:0] + c[8:0];
assign out[17:9] = a[17:9] * b[17:9] + c[17:9];

endmodule
module mac_6(a, b, c, out);
parameter DATA_WIDTH = 6;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_36(a, b, c, out);
parameter DATA_WIDTH = 4;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_2(a, b, c, out);
parameter DATA_WIDTH = 2;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_12(a, b, c, out);
parameter DATA_WIDTH = 12;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_16(a, b, c, out);
parameter DATA_WIDTH = 16;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_9(a, b, c, out);
parameter DATA_WIDTH = 9;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_32(a, b, c, out);
parameter DATA_WIDTH = 32;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module mac_4(a, b, c, out);
parameter DATA_WIDTH = 4;  /* declare a parameter. default required */
input [DATA_WIDTH - 1 : 0] a, b, c;
output [DATA_WIDTH - 1 : 0] out;

assign out = a * b + c;

endmodule
module s298 ( clock, 
    G0, G1, G2,
    G117, G132, G66, G118, G133, G67  );
  input  G0, G1, G2, clock;
  output G117, G132, G66, G118, G133, G67;
  reg G10, G11, G12, G13, G14, G15, G16, G17, G18, G19, G20, G21, G22, G23;
  wire n57, n59, n64, n66, n21_1, n26_1, n31_1, n36_1, n41_1, n46_1, n51_1,
    n56_1, n61_1, n66_2, n71_1, n76_1, n81_1, n86_1;
  assign n21_1 = ~G0 & ~G10;
  assign n26_1 = ~G0 & (G10 ? (~G11 & (G12 | ~G13)) : G11);
  assign n31_1 = ~G0 & ((G12 & (~G10 | ~G11)) | (G10 & G11 & ~G12));
  assign n36_1 = ~G0 & ((G11 & ((~G12 & G13) | (G10 & G12 & ~G13))) | (G13 & (~G10 | (~G11 & G12))));
  assign n41_1 = ~G0 & (G14 ^ (G23 | (G10 & G13 & n57)));
  assign n57 = ~G11 & ~G12;
  assign n46_1 = ~G0 & ~n59;
  assign n59 = (G11 & (~G15 | (~G12 & G13 & ~G14 & ~G22))) | (~G15 & (G12 | ~G13 | G14 | ~G22));
  assign n51_1 = n59 & ((G13 & (~G14 | G16)) | (G12 & G14 & G16));
  assign n56_1 = n59 & ((~G13 & (G11 ? ~G12 : ~G14)) | (G14 & G17 & (G12 | G13)));
  assign n61_1 = n59 & ((G14 & G18 & (G12 | G13)) | (~G13 & (~G14 | (G11 & ~G12))));
  assign n66_2 = n59 ? n64 : ~G10;
  assign n64 = (G13 & (~G14 | G19)) | (G14 & ((~G11 & ~G12 & ~G13) | (G12 & G19)));
  assign n71_1 = n59 ? (n66 & (G20 | (~G12 & ~G13))) : ~G10;
  assign n66 = G14 & (~G11 | G12 | G13);
  assign n76_1 = n59 & ((G12 & ((G11 & ~G13 & ~G14) | (G14 & G21))) | (G13 & G14 & G21));
  assign n81_1 = ~G0 & (G2 ^ G22);
  assign n86_1 = ~G0 & (G1 ^ G23);
  assign G117 = G18;
  assign G132 = G20;
  assign G66 = G16;
  assign G118 = G19;
  assign G133 = G21;
  assign G67 = G17;
  always @ (posedge clock) begin
    G10 <= n21_1;
    G11 <= n26_1;
    G12 <= n31_1;
    G13 <= n36_1;
    G14 <= n41_1;
    G15 <= n46_1;
    G16 <= n51_1;
    G17 <= n56_1;
    G18 <= n61_1;
    G19 <= n66_2;
    G20 <= n71_1;
    G21 <= n76_1;
    G22 <= n81_1;
    G23 <= n86_1;
  end
  initial begin
    G10 <= 1'b0;
    G11 <= 1'b0;
    G12 <= 1'b0;
    G13 <= 1'b0;
    G14 <= 1'b0;
    G15 <= 1'b0;
    G16 <= 1'b0;
    G17 <= 1'b0;
    G18 <= 1'b0;
    G19 <= 1'b0;
    G20 <= 1'b0;
    G21 <= 1'b0;
    G22 <= 1'b0;
    G23 <= 1'b0;
  end
endmodule
module ADDF(
  input [0:0] A, // Input a
  input [0:0] B, // Input b
  input [0:0] CI, // Input cin
  output [0:0] CO, // Output carry
  output [0:0] SUM // Output sum
);
  assign SUM = A ^ B ^ CI;
  assign CO = (A & B) | (A & CI) | (B & CI); 
endmodule
module dpram_512x32 (
	input clk,
	input wen,
	input ren,
	input[0:8] waddr,
	input[0:8] raddr,
	input[0:31] d_in,
	output[0:31] d_out );

		dpram_512x32_core memory_0 (
			.wclk		(clk),
			.wen		(wen),
			.waddr		(waddr),
			.data_in	(d_in),
			.rclk		(clk),
			.ren		(ren),
			.raddr		(raddr),
			.d_out		(d_out) );

endmodule
module dpram_512x32_core (
	input wclk,
	input wen,
	input[0:8] waddr,
	input[0:31] data_in,
	input rclk,
	input ren,
	input[0:8] raddr,
	output[0:31] d_out );

	reg[0:31] ram[0:511];
	reg[0:31] internal;

	assign d_out = internal;

	always @(posedge wclk) begin
		if(wen) begin
			ram[waddr] <= data_in;
		end
	end

	always @(posedge rclk) begin
		if(ren) begin
			internal <= ram[raddr];
		end
	end

endmodule
module tap_buf4(in,
                out);
//----- INPUT PORTS -----
input [0:0] in;
//----- OUTPUT PORTS -----
output [0:0] out;

//----- BEGIN wire-connection ports -----
//----- END wire-connection ports -----


//----- BEGIN Registered ports -----
//----- END Registered ports -----

// ----- Verilog codes of a regular inverter -----
  //assign out = (in === 1'bz)? $random : ~in;
  assign out = ~in;

`ifdef ENABLE_TIMING
// ------ BEGIN Pin-to-pin Timing constraints -----
  specify
    (in[0] => out[0]) = (0.01, 0.01);
  endspecify
// ------ END Pin-to-pin Timing constraints -----
`endif
endmodule
module MUX2(
    // iVerilog is buggy on the 'input A' declaration when deposit initial
    // values 
	input [0:0] A,   // Data input 0
	input [0:0] B,   // Data input 1
	input [0:0] S0, // Select port
	output [0:0] Y  // Data output
	);
  
	assign Y = S0 ? B : A;

// Note: 
//	 MUX2 appears will appear in LUTs, routing multiplexers,
//   being a component in combinational loops
//   To help convergence in simulation 
//   i.e., to avoid the X (undetermined) signals,
//   the following timing constraints and signal initialization 
//   has to be added!

`ifdef ENABLE_TIMING
// ------ BEGIN Pin-to-pin Timing constraints -----
	specify
		(A => Y) = (0.001, 0.001);
		(B => Y) = (0.001, 0.001);
		(S0 => Y) = (0.001, 0.001);
	endspecify
// ------ END Pin-to-pin Timing constraints -----
`endif

`ifdef ENABLE_SIGNAL_INITIALIZATION
// ------ BEGIN driver initialization -----
	initial begin
	`ifdef ENABLE_FORMAL_VERIFICATION
		$deposit(A, 1'b0);
		$deposit(B, 1'b0);
		$deposit(S0, 1'b0);
	`else
		$deposit(A, $random);
		$deposit(B, $random);
		$deposit(S0, $random);
	`endif

	end
// ------ END driver initialization -----
`endif

endmodule
module CARRY_MUX2(
	input [0:0] A0,   // Data input 0
	input [0:0] A1,   // Data input 1
	input [0:0] S, // Select port
	output [0:0] Y  // Data output
	);
  
	assign Y = S ? A1 : A0;

// Note: 
//	 MUX2 appears in the datapath logic driven by carry-in and LUT outputs
//	 where initial values and signal deposit are not required

endmodule
module spram_4x1 (
	input	 	clk,
	input[1:0]	addr,
	input		d_in,
	input		wr_en,
	output		d_out );

	reg[3:0]	mem;

	assign d_out = mem[addr];

	always @(posedge clk) begin
		if(wr_en) begin
			mem[addr] <= d_in;
		end
	end

endmodule
module mult_36x36 (
	input [0:35] a,
	input [0:35] b,
	output [0:71] out,
    input [0:1] mode);

    reg [0:71] out_reg;

    always @(mode, a, b) begin 
       if (2'b01 == mode) begin
         out_reg[0:17] <= a[0:8] * b[0:8];
         out_reg[18:35] <= a[9:17] * b[9:17];
         out_reg[36:53] <= a[18:26] * b[18:26];
         out_reg[54:71] <= a[27:35] * b[27:35];
       end else if (2'b10 == mode) begin
         out_reg[0:35] <= a[0:17] * b[0:17];
         out_reg[36:71] <= a[18:35] * b[18:35];
       end else begin
         out_reg <= a * b;
       end
    end

    assign out = out_reg;

endmodule
module DFFQ (
  input CK, // Clock Input
  input D, // Data Input
  output Q // Q output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (posedge CK) begin 
  q_reg <= D;
end

assign Q = q_reg;

endmodule //End Of Module
module DFF (
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (posedge CK) begin 
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q // Q output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= D;
end

assign Q = q_reg;

endmodule //End Of Module
module DFFR (
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFRN (
  input RSTN, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or negedge RSTN)
if (~RSTN) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFS (
  input SET, // Set input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge SET)
if (SET) begin
  q_reg <= 1'b1;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFSN (
  input SETN, // Set input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or negedge SETN)
if (~SETN) begin
  q_reg <= 1'b1;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFSR (
  input SET, // set input
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  output QN // QB output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST or posedge SET)
if (RST) begin
  q_reg <= 1'b0;
end else if (SET) begin
  q_reg <= 1'b1;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = ~q_reg;

endmodule //End Of Module
module DFFSRQ (
  input SET, // set input
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q // Q output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST or posedge SET)
if (RST) begin
  q_reg <= 1'b0;
end else if (SET) begin
  q_reg <= 1'b1;
end else begin
  q_reg <= D;
end

assign Q = q_reg;

endmodule //End Of Module
module MULTI_MODE_DFFSRQ (
  input SET, // Set input
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  input [0:1] mode // mode-selection bits: bit0 for reset polarity; bit1 for set polarity
);

wire post_set = mode[1] ? ~SET : SET;
wire post_rst = mode[0] ? ~RST : RST;

DFFSRQ FF_CORE (.SET(post_set),
                .RST(post_rst),
                .CK(CK),
                .D(D),
                .Q(Q)
               );

endmodule //End Of Module
module MULTI_MODE_DFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  input mode // mode-selection bits: bit0 for reset polarity; bit1 for set polarity
);

wire post_rst = mode ? ~RST : RST;

DFFRQ FF_CORE (.RST(post_rst),
               .CK(CK),
               .D(D),
               .Q(Q)
               );

endmodule //End Of Module
module MULTI_MODE_DFFNRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input D, // Data Input
  output Q, // Q output
  input [0:1] mode // mode-selection bits: bit0 for reset polarity; bit1 for set polarity
);

wire post_rst = mode[0] ? ~RST : RST;
wire post_clk = mode[1] ? ~CK : CK;

DFFRQ FF_CORE (.RST(post_rst),
               .CK(post_clk),
               .D(D),
               .Q(Q)
               );

endmodule //End Of Module
module SDFFSR (
  input SET, // Set input
  input RST, // Reset input
  input CK, // Clock Input
  input SE, // Scan-chain Enable
  input D, // Data Input
  input SI, // Scan-chain input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST or posedge SET)
if (RST) begin
  q_reg <= 1'b0;
end else if (SET) begin
  q_reg <= 1'b1;
end else if (SE) begin
  q_reg <= SI;
end else begin
  q_reg <= D;
end

assign Q = q_reg;
assign QN = !Q;

endmodule //End Of Module
module SDFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input SE, // Scan-chain Enable
  input D, // Data Input
  input SI, // Scan-chain input
  output Q // Q output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else if (SE) begin
  q_reg <= SI;
end else begin
  q_reg <= D;
end

assign Q = q_reg;

endmodule //End Of Module
module SDFFSRQ (
  input SET, // Set input
  input RST, // Reset input
  input CK, // Clock Input
  input SE, // Scan-chain Enable
  input D, // Data Input
  input SI, // Scan-chain input
  output Q // Q output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST or posedge SET)
if (RST) begin
  q_reg <= 1'b0;
end else if (SET) begin
  q_reg <= 1'b1;
end else if (SE) begin
  q_reg <= SI;
end else begin
  q_reg <= D;
end

assign Q = q_reg;

endmodule //End Of Module
module CFGSDFFR (
  input RST, // Reset input
  input CK, // Clock Input
  input SE, // Scan-chain Enable
  input D, // Data Input
  input SI, // Scan-chain input
  input CFGE, // Configure enable
  output Q, // Regular Q output
  output CFGQ, // Data Q output which is released when configure enable is activated
  output CFGQN // Data Qb output which is released when configure enable is activated
);
//------------Internal Variables--------
reg q_reg;
wire QN;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else if (SE) begin
  q_reg <= SI;
end else begin
  q_reg <= D;
end

assign CFGQ = CFGE ? Q : 1'b0;
assign CFGQN = CFGE ? QN : 1'b1;

assign Q = q_reg;
assign QN = !Q;

endmodule //End Of Module
module CFGDSDFFR (
  input RST, // Reset input
  input CK, // Clock Input
  input SE, // Scan-chain Enable
  input D, // Data Input
  input SI, // Scan-chain input
  input CFGE, // Configure enable
  input CFG_DONE, // Configure done
  output Q, // Regular Q output
  output CFGQ, // Data Q output which is released when configure enable is activated
  output CFGQN // Data Qb output which is released when configure enable is activated
);
//------------Internal Variables--------
reg q_reg;
wire QN;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else if (SE) begin
  q_reg <= SI;
end else begin
  q_reg <= D;
end

assign CFGQ = CFGE ? Q : 1'b0;
assign CFGQN = CFGE ? QN : 1'b1;

assign Q = CFG_DONE ? q_reg : 1'b0;
assign QN = CFG_DONE ? !Q : 1'b1;

endmodule //End Of Module
module BL_DFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input SIN, // Data Input
  output SOUT, // Q output
  output BL // BL output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= SIN;
end

assign SOUT = q_reg;
assign BL = q_reg;

endmodule //End Of Module
module WL_DFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input SIN, // Data Input
  input WEN, // Write-enable
  output SOUT, // Q output
  output WLW // Drive WL write signals
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= SIN;
end

assign SOUT = q_reg;
assign WLW = WEN ? q_reg : 1'b0;

endmodule //End Of Module
module WLR_DFFRQ (
  input RST, // Reset input
  input CK, // Clock Input
  input SIN, // Data Input
  input WEN, // Write-enable
  output SOUT, // Q output
  output WLW, // Drive WL write signals
  output WLR // Drive WL read signals
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ ( posedge CK or posedge RST)
if (RST) begin
  q_reg <= 1'b0;
end else begin
  q_reg <= SIN;
end

assign SOUT = q_reg;
assign WLW = WEN ? q_reg : 1'b0;
assign WLR = 1'b0; // Use a constant output just for simple testing

endmodule //End Of Module
module frac_mult_16x16 (
	input [0:15] a,
	input [0:15] b,
	output [0:31] out,
    input [0:0] mode);

    reg [0:31] out_reg;

    always @(mode, a, b) begin 
       if (1'b1 == mode) begin
         out_reg[0:15] <= a[0:7] * b[0:7];
         out_reg[16:31] <= a[8:15] * b[8:15];
       end else begin
         out_reg <= a * b;
       end
    end

    assign out = out_reg;

endmodule
module LATCH (
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (WE or D) begin
  if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHR (
  input RST, // Reset signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (RST or WE or D) begin
  if (RST) begin
    q_reg <= 1'b0;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHRN (
  input RSTN, // Reset signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (RSTN or WE or D) begin
  if (~RSTN) begin
    q_reg <= 1'b0;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHS (
  input SET, // Set signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (SET or WE or D) begin
  if (SET) begin
    q_reg <= 1'b1;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHSN (
  input SETN, // Set signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (SETN or WE or D) begin
  if (~SETN) begin
    q_reg <= 1'b1;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHSR (
  input RST, // Reset signal
  input SET, // Set signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (RST or SET or WE or D) begin
  if (RST) begin
    q_reg <= 1'b0;
  end else if (SET) begin
    q_reg <= 1'b1;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module LATCHSNRN (
  input RSTN, // Reset signal
  input SETN, // Set signal
  input WE, // Write enable
  input D, // Data input
  output Q, // Q output
  output QN // Q negative output
);
//------------Internal Variables--------
reg q_reg;

//-------------Code Starts Here---------
always @ (RSTN or SETN or WE or D) begin
  if (~RSTN) begin
    q_reg <= 1'b0;
  end else if (~SETN) begin
    q_reg <= 1'b1;
  end else if (1'b1 == WE) begin
    q_reg <= D;
  end
end

// Wire q_reg to Q
`ifndef ENABLE_FORMAL_VERIFICATION
  assign Q = q_reg;
  assign QN = ~q_reg;
`else
  assign Q = 1'bZ;
  assign QN = !Q;
`endif

endmodule
module frac_mult_36x36 
(
	input   wire [0:35] a,
	input   wire [0:35] b,
	output  wire [0:71] out,
  input   wire [0:1]  mode  
);

wire [0:35] mult_ll_out;
wire [0:35] mult_lh_out;
wire [0:35] mult_hl_out;
wire [0:35] mult_hh_out;

wire [0:36] sub_result1; // carry included
wire [0:35] sub_result2;
wire [0:71] result;

  assign sub_result1 = mult_lh_out + mult_hl_out + {18'd0, mult_ll_out[0:17]};
  assign sub_result2 = mult_hh_out + {17'd0, sub_result1[0:18]};

  assign result[54:71]   = mult_ll_out[18:35];
  assign result[36:53]  = sub_result1[19:36];
  assign result[0:35]  = sub_result2;

  assign out[36:71] = (mode[0] == 1'b1) ? mult_ll_out : result[36:71];
  assign out[0:35]  = (mode[0] == 1'b1) ? mult_hh_out : result[0:35];                              

  frac_mult_18x18 mult_ll (.a(a[18:35]), .b(b[18:35]), .out(mult_ll_out), .mode(mode[1]) ); // A_low*B_low
  frac_mult_18x18 mult_lh (.a(a[18:35]), .b(b[0:17]), .out(mult_lh_out), .mode(1'b0) ); // A_low*B_high
  frac_mult_18x18 mult_hl (.a(a[0:17]), .b(b[18:35]), .out(mult_hl_out), .mode(1'b0) ); // A_high*B_low
  frac_mult_18x18 mult_hh (.a(a[0:17]), .b(b[0:17]),  .out(mult_hh_out), .mode(mode[1])); // A_high*B_high

endmodule
module frac_mult_18x18
(
	input   wire [0:17] a,
	input   wire [0:17] b,
	output  wire [0:35] out,
  input   wire [0:0]  mode  
);

wire [0:17] mult_ll_out;
wire [0:17] mult_lh_out;
wire [0:17] mult_hl_out;
wire [0:17] mult_hh_out;

wire [0:18] sub_result1;  // carry included
wire [0:17] sub_result2;
wire [0:35] result;

  assign sub_result1 = mult_lh_out + mult_hl_out + {9'd0, mult_ll_out[0:8]};
  assign sub_result2 = mult_hh_out + {8'd0, sub_result1[0:9]};

  assign result[27:35] = mult_ll_out[9:17];
  assign result[18:26] = sub_result1[10:18];
  assign result[0:17]  = sub_result2;

  assign out[18:35] = (mode == 1'b1) ? mult_ll_out : result[18:35];
  assign out[0:17]  = (mode == 1'b1) ? mult_hh_out : result[0:17];

  multiplier #(9) mult_ll (.a(a[9:17]), .b(b[9:17]), .out(mult_ll_out) ); // A_low*B_low
  multiplier #(9) mult_lh (.a(a[9:17]), .b(b[0:8]), .out(mult_lh_out) ); // A_low*B_high
  multiplier #(9) mult_hl (.a(a[0:8]), .b(b[9:17]), .out(mult_hl_out) ); // A_high*B_low
  multiplier #(9) mult_hh (.a(a[0:8]), .b(b[0:8]), .out(mult_hh_out) ); // A_high*B_high

endmodule
module multiplier
#( parameter WIDTH = 9 )
(
	input   wire [0:WIDTH-1] a,
	input   wire [0:WIDTH-1] b,
	output  wire [0:2*WIDTH-1] out 
);

  assign  out = a * b;

endmodule
module OR2(a,
           b,
           out);
//----- INPUT PORTS -----
input [0:0] a;
//----- INPUT PORTS -----
input [0:0] b;
//----- OUTPUT PORTS -----
output [0:0] out;

//----- BEGIN wire-connection ports -----
//----- END wire-connection ports -----


//----- BEGIN Registered ports -----
//----- END Registered ports -----

// ----- Verilog codes of a 2-input 1-output AND gate -----
	assign out[0] = a[0] | b[0];

`ifdef ENABLE_TIMING
// ------ BEGIN Pin-to-pin Timing constraints -----
	specify
		(a[0] => out[0]) = (0.01, 0.01);
		(b[0] => out[0]) = (0.005, 0.005);
	endspecify
// ------ END Pin-to-pin Timing constraints -----
`endif
endmodule
module mult_32x32 (
	input [0:31] a,
	input [0:31] b,
	output [0:63] out,
    input [0:1] mode);

    reg [0:63] out_reg;

    always @(mode, a, b) begin 
       if (2'b01 == mode) begin
         out_reg[0:15] <= a[0:7] * b[0:7];
         out_reg[16:31] <= a[8:15] * b[8:15];
         out_reg[32:47] <= a[16:23] * b[16:23];
         out_reg[48:63] <= a[24:31] * b[24:31];
       end else if (2'b10 == mode) begin
         out_reg[0:31] <= a[0:15] * b[0:15];
         out_reg[32:63] <= a[16:31] * b[16:31];
       end else begin
         out_reg <= a * b;
       end
    end

    assign out = out_reg;

endmodule
module dpram_128x8 (
	input clk,
	input wen,
	input ren,
	input[0:6] waddr,
	input[0:6] raddr,
	input[0:7] d_in,
	output[0:7] d_out );

		dpram_128x8_core memory_0 (
			.wclk		(clk),
			.wen		(wen),
			.waddr		(waddr),
			.data_in	(d_in),
			.rclk		(clk),
			.ren		(ren),
			.raddr		(raddr),
			.d_out		(d_out) );

endmodule
module dpram_128x8_core (
	input wclk,
	input wen,
	input[0:6] waddr,
	input[0:7] data_in,
	input rclk,
	input ren,
	input[0:6] raddr,
	output[0:7] d_out );

	reg[0:7] ram[0:127];
	reg[0:7] internal;

	assign d_out = internal;

	always @(posedge wclk) begin
		if(wen) begin
			ram[waddr] <= data_in;
		end
	end

	always @(posedge rclk) begin
		if(ren) begin
			internal <= ram[raddr];
		end
	end

endmodule
module INVTX1(in, out);
  input [0:0] in;
  output [0:0] out;

  assign out = ~in;

endmodule
module GPIO (
  input A, // Data output
  output Y, // Data input
  inout PAD, // bi-directional pad
  input DIR // direction control
);
  //----- when direction enabled, the signal is propagated from PAD to data input
  assign Y = DIR ? PAD : 1'bz;
  //----- when direction is disabled, the signal is propagated from data out to pad
  assign PAD = DIR ? 1'bz : A;
endmodule
module GPIO_CFGD (
  input CONFIG_DONE, // Control signal to block signals
  input A, // Data output
  output Y, // Data input
  inout PAD, // bi-directional pad
  input DIR // direction control
);
  //----- when direction enabled, the signal is propagated from PAD to data input
  assign Y = CONFIG_DONE ? (DIR ? PAD : 1'bz) : 1'bz;
  //----- when direction is disabled, the signal is propagated from data out to pad
  assign PAD = CONFIG_DONE ? (DIR ? 1'bz : A) : 1'bz;
endmodule
module GPIN (
  inout A, // External PAD signal
  output Y // Data input
);
  assign Y = A;
endmodule
module GPOUT (
  inout Y, // External PAD signal
  input A // Data output
);
  assign Y = A;
endmodule
module EMBEDDED_IO (
  input SOC_IN, // Input to drive the inpad signal
  output SOC_OUT, // Output the outpad signal
  output SOC_DIR, // Output the directionality
  output FPGA_IN, // Input data to FPGA
  input FPGA_OUT, // Output data from FPGA
  input FPGA_DIR // direction control 
);

  assign FPGA_IN = SOC_IN;
  assign SOC_OUT = FPGA_OUT;
  assign SOC_DIR = FPGA_DIR;
endmodule
module EMBEDDED_IO_ISOLN (
  input SOC_IN, // Input to drive the inpad signal
  output SOC_OUT, // Output the outpad signal
  output SOC_DIR, // Output the directionality
  output FPGA_IN, // Input data to FPGA
  input FPGA_OUT, // Output data from FPGA
  input FPGA_DIR, // direction control 
  input IO_ISOL_N // Active-low signal to set the I/O in input mode
);

  assign FPGA_IN = IO_ISOL_N ? SOC_IN : 1'bz;
  assign SOC_OUT = IO_ISOL_N ? FPGA_OUT : 1'bz;
  // Direction signal is set to logic '0' when in input mode 
  assign SOC_DIR = IO_ISOL_N ? FPGA_DIR : 1'b0;
endmodule
module AIB (
	input TX_CLK,
	input RX_CLK,
	inout[0:79] PAD,
	input[0:79] TX_DATA,
	output[0:79] RX_DATA);

// May add the logic function of a real AIB
// Refer to the offical AIB github
//   https://github.com/intel/aib-phy-hardware

endmodule
module mult_8x8 (
  input [0:7] A,
  input [0:7] B,
  output [0:15] Y
);

  assign Y = A * B;

endmodule
module buf4(in,
            out);
//----- INPUT PORTS -----
input [0:0] in;
//----- OUTPUT PORTS -----
output [0:0] out;

//----- BEGIN wire-connection ports -----
//----- END wire-connection ports -----


//----- BEGIN Registered ports -----
//----- END Registered ports -----

// ----- Verilog codes of a regular inverter -----
  //assign out = (in === 1'bz)? $random : in;
  assign out = in;

`ifdef ENABLE_TIMING
// ------ BEGIN Pin-to-pin Timing constraints -----
  specify
    (in[0] => out[0]) = (0.01, 0.01);
  endspecify
// ------ END Pin-to-pin Timing constraints -----
`endif
endmodule
module dpram_1024x8 (
  input clk,
  input wen,
  input ren,
  input[0:9] waddr,
  input[0:9] raddr,
  input[0:7] data_in,
  output[0:7] data_out );

    dpram_1024x8_core memory_0 (
      .wclk      (clk),
      .wen       (wen),
      .waddr     (waddr),
      .data_in   (data_in),
      .rclk      (clk),
      .ren       (ren),
      .raddr     (raddr),
      .data_out  (data_out) );

endmodule
module dpram_1024x8_core (
  input wclk,
  input wen,
  input [0:9] waddr,
  input [0:7] data_in,
  input rclk,
  input ren,
  input [0:9] raddr,
  output [0:7] data_out );

  reg[0:7] ram[0:1023];
  reg[0:7] internal;

  assign data_out = internal;

  always @(posedge wclk) begin
    if(wen) begin
      ram[waddr] <= data_in;
    end
  end

  always @(posedge rclk) begin
    if(ren) begin
      internal <= ram[raddr];
    end
  end

endmodule
module frac_lut4_arith (
input [0:3] in,
input [0:0] cin,
output [0:1] lut3_out,
output [0:0] lut4_out,
output [0:0] cout,
input [0:15] sram,
input [0:1] mode);

//----- BEGIN wire-connection ports -----
wire [0:3] in;
wire [0:0] cin;
wire [0:1] lut2_out;
wire [0:1] lut3_out;
wire [0:0] lut4_out;
wire [0:0] cout;
wire [0:0] arith_in2;
//----- END wire-connection ports -----


//----- BEGIN Registered ports -----
//----- END Registered ports -----


wire [0:0] sky130_fd_sc_hd__buf_2_0_X;
wire [0:0] sky130_fd_sc_hd__buf_2_1_X;
wire [0:0] sky130_fd_sc_hd__buf_2_2_X;
wire [0:0] sky130_fd_sc_hd__buf_2_3_X;
wire [0:0] sky130_fd_sc_hd__inv_1_0_Y;
wire [0:0] sky130_fd_sc_hd__inv_1_1_Y;
wire [0:0] sky130_fd_sc_hd__inv_1_2_Y;
wire [0:0] sky130_fd_sc_hd__inv_1_3_Y;
wire [0:0] sky130_fd_sc_hd__or2_1_0_X;

// ----- BEGIN Local short connections -----
// ----- END Local short connections -----
// ----- BEGIN Local output short connections -----
// ----- END Local output short connections -----

	sky130_fd_sc_hd__or2_1 sky130_fd_sc_hd__or2_1_0_ (
		.A(mode[1]),
		.B(in[3]),
		.X(sky130_fd_sc_hd__or2_1_0_X[0]));

	sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_0_ (
		.A(in[0]),
		.Y(sky130_fd_sc_hd__inv_1_0_Y[0]));

	sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_1_ (
		.A(in[1]),
		.Y(sky130_fd_sc_hd__inv_1_1_Y[0]));

  assign arith_in2 = mode[0] ? cin : in[2];

	sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_2_ (
		.A(arith_in2),
		.Y(sky130_fd_sc_hd__inv_1_2_Y[0]));

	sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_1_3_ (
		.A(sky130_fd_sc_hd__or2_1_0_X[0]),
		.Y(sky130_fd_sc_hd__inv_1_3_Y[0]));

	sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_0_ (
		.A(in[0]),
		.X(sky130_fd_sc_hd__buf_2_0_X[0]));

	sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_1_ (
		.A(in[1]),
		.X(sky130_fd_sc_hd__buf_2_1_X[0]));

	sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_2_ (
		.A(arith_in2),
		.X(sky130_fd_sc_hd__buf_2_2_X[0]));

	sky130_fd_sc_hd__buf_2 sky130_fd_sc_hd__buf_2_3_ (
		.A(sky130_fd_sc_hd__or2_1_0_X[0]),
		.X(sky130_fd_sc_hd__buf_2_3_X[0]));

	frac_lut4_mux frac_lut4_mux_0_ (
		.in(sram[0:15]),
		.sram({sky130_fd_sc_hd__buf_2_0_X[0], sky130_fd_sc_hd__buf_2_1_X[0], sky130_fd_sc_hd__buf_2_2_X[0], sky130_fd_sc_hd__buf_2_3_X[0]}),
		.sram_inv({sky130_fd_sc_hd__inv_1_0_Y[0], sky130_fd_sc_hd__inv_1_1_Y[0], sky130_fd_sc_hd__inv_1_2_Y[0], sky130_fd_sc_hd__inv_1_3_Y[0]}),
		.lut2_out(lut2_out[0:1]),
		.lut3_out(lut3_out[0:1]),
		.lut4_out(lut4_out[0]));
 
    assign cout = lut2_out[0] ? cin : lut2_out[1];

endmodule
module lut6 (
input [5:0] in,
output out,
input [63:0] sram,
input [63:0] sram_inv);

  assign out = sram[in];

endmodule
module dpram (
	input clk,
	input wen,
	input ren,
	input[0:9] waddr,
	input[0:9] raddr,
	input[0:31] d_in,
	output[0:31] d_out );

		dpram_1024x32_core memory_0 (
			.wclk		(clk),
			.wen		(wen),
			.waddr		(waddr),
			.data_in	(d_in),
			.rclk		(clk),
			.ren		(ren),
			.raddr		(raddr),
			.d_out		(d_out) );

endmodule
module dpram_1024x32_core (
	input wclk,
	input wen,
	input[0:9] waddr,
	input[0:31] data_in,
	input rclk,
	input ren,
	input[0:9] raddr,
	output[0:31] d_out );

	reg[0:31] ram[0:1023];
	reg[0:31] internal;

	assign d_out = internal;

	always @(posedge wclk) begin
		if(wen) begin
			ram[waddr] <= data_in;
		end
	end

	always @(posedge rclk) begin
		if(ren) begin
			internal <= ram[raddr];
		end
	end

endmodule
module dpram_2048x8 (
  input clk,
  input wen,
  input ren,
  input[0:10] waddr,
  input[0:10] raddr,
  input[0:7] data_in,
  output[0:7] data_out );

    dpram_2048x8_core memory_0 (
      .wclk    (clk),
      .wen    (wen),
      .waddr    (waddr),
      .data_in  (data_in),
      .rclk    (clk),
      .ren    (ren),
      .raddr    (raddr),
      .data_out    (data_out) );

endmodule
module dpram_2048x8_core (
  input wclk,
  input wen,
  input[0:10] waddr,
  input[0:7] data_in,
  input rclk,
  input ren,
  input[0:10] raddr,
  output[0:7] data_out );

  reg[0:7] ram[0:2047];
  reg[0:7] internal;

  assign data_out = internal;

  always @(posedge wclk) begin
    if(wen) begin
      ram[waddr] <= data_in;
    end
  end

  always @(posedge rclk) begin
    if(ren) begin
      internal <= ram[raddr];
    end
  end

endmodule
module dpram_tb ();
	reg clk;
	reg wen;
	reg ren;
	reg[0:9] waddr;
	reg[0:9] raddr;
	reg[0:31] d_in;
	wire[0:31] d_out;

	integer count;
	integer lim_max = 1023;

		dpram memory_0 (
			.clk		(clk),
			.wen		(wen),
			.waddr		(waddr),
			.d_in		(d_in),
			.ren		(ren),
			.raddr		(raddr),
			.d_out		(d_out) );

	initial begin
		clk <= 1'b0;
		ren <= 1'b0;
		wen <= 1'b0;
		raddr <= 10'h000;
		waddr <= 10'h000;
		d_in <= 32'h00000000;
		for(count = 0; count < lim_max; count = count +1) begin
			#5
			wen <= 1'b1;
			clk <= !clk;
			if(clk) begin
				waddr <= waddr + 1;
			end
		end	
		wen <= 1'b0;
		for(count = 0; count < lim_max; count = count +1) begin
			#5
			ren <= 1'b1;
			clk <= !clk;
			if(clk) begin
				raddr <= raddr + 1;
			end
		end	
		$finish;
	end

	always@(negedge clk) begin
		d_in <= $random;
	end

endmodule
module cmos_mux2level_tb;
// Parameters
parameter SIZE_OF_MUX = 50; //---- MUX input size 
parameter SIZE_OF_SRAM = 16; //---- MUX input size 
parameter op_clk_period = 1; // [ns] half clock period
parameter operating_period =  SIZE_OF_MUX * 2 * op_clk_period; // [ns] One full clock period

// voltage sources
wire [0:SIZE_OF_MUX-1] in;
wire out;
wire [0:SIZE_OF_SRAM-1] sram;
wire [0:SIZE_OF_SRAM-1] sram_inv; 
// clocks
wire op_clock;
// registered ports 
reg op_clock_reg;
reg [0:SIZE_OF_MUX-1] in_reg;
reg [0:SIZE_OF_SRAM-1] sram_reg;
reg [0:SIZE_OF_SRAM-1] sram_inv_reg;
// Config done signal;
reg config_done;
// Temp register for rotating shift
reg temp;

// Unit Under Test
mux_2level_size50 U0 (in, out, sram, sram_inv);

// Task: assign inputs
task op_mux_input;
  begin
    @(posedge op_clock);
    temp = in_reg[SIZE_OF_MUX-1];
    in_reg[1:SIZE_OF_MUX-1] = in_reg[0:SIZE_OF_MUX-2];
    in_reg[0] = temp;
  end 
endtask

// Configuration done signal
initial
begin
  config_done = 1'b1;
end

// Operating clocks
initial 
begin
  op_clock_reg = 1'b0;
end
always
begin
  #op_clk_period op_clock_reg = ~op_clock_reg; 
end

// Programming and Operating clocks 
assign op_clock = op_clock_reg & config_done;

// Operating Phase
initial
begin
  in_reg = {SIZE_OF_MUX {1'b0}}; 
  in_reg[0] = 1'b1; // Last bit is 1 initially
end
always wait (config_done) // Only invoked when config_done is 1
begin
  /* Update inputs */
  op_mux_input;
end

// Wire ports
assign in = in_reg;
assign sram[0:7] = 8'b00010000;
assign sram[8:15] = 8'b00010000;
assign sram_inv = ~sram;

endmodule