dakies/OSS_Verilog huggingface dataset:
module armstrong(
    input [8:0] number,
    output reg is_armstrong
    );
    parameter ARMSTRONG= 1'b1, Not_ARMSTRONG= 1'b0;
    always@(number)
        begin
            is_armstrong= check_armstrong(number);

            if(is_armstrong== 1'b1) $display("\t\t %d is a armstrong number", number);
            else $display("\t\t %d is not a armstrong number", number);
    end
    
    function check_armstrong;
    input [8:0]num;
            reg [8:0] temp_num;
            reg [8:0] remainder;
            reg [8:0] result;
    begin
            result= 9'd0;
            temp_num = num;
            while (temp_num != 0) begin
            remainder = temp_num % 10;
            result =  result + (remainder * remainder * remainder);
            temp_num = temp_num/ 10;
    end
    if (result == num) check_armstrong= ARMSTRONG;
    else check_armstrong= Not_ARMSTRONG;
end
endfunction
endmodule
module test_bench;
reg [8:0]number;
wire is_armstrong;

armstrong dut(number, is_armstrong);

always 
begin
number=9'd153;
#10;
number=9'd300;
#10;
number=9'd370;
#10;
number=9'd190;
#10;
number=9'd407;
#10;
number=9'd420;
#10;
end

initial #60 $finish;

endmodule
module SR_latch(
    input en, rst, S, R, 
    output reg Q
    ); 
    
    always@(*)
        begin 
            if(rst) Q<= 1'b0;
            else if(en) begin
                case({S,R})
                    2'b00 : Q<= Q;
                    2'b01 : Q<= 1'b0;
                    2'b10 : Q<= 1'b1;
                    default : Q<=2'bxx;
                endcase
                end    
        end
endmodule
module test_bench;
reg S, R, en, rst;
wire Q;

  SR_latch dut(en,rst,S,R,Q);

 initial begin
        rst=1;
        S = 0;
        R = 0;
        en = 0;
        #10;
        rst=0;
        en=1;
    end
    
    always begin
        S=0;
        R=0;
        #10;
        S=0;
        R=1;
        #10;
        S=1;
        R=0;
        #10;
        S=1;
        R=1;
        #10;

    end
  initial begin
  $monitor("\t en: %d  S: %d  R: %d  Q: %d", en,S,R,Q);
  #90 $finish;
  end
endmodule
module not_gate(
    input in,
    output out
    );
    supply0 gnd;
    supply1 vdd;
    
    pmos(out, vdd, in);
    nmos(out, gnd, in);
    
endmodule
module test_bench;
    reg in;
    wire out;
    not_gate dut(in, out);
    initial in= 1'b0;
    initial forever #50 in = ~in;
    initial #600 $finish;
endmodule
module decoder_3_8(
    input [2:0] in,
    output reg[7:0] out
    );
    always@(*)
        begin
            out=0;
            case(in)	
                3'b000 : out[0] = 1'b1;
                3'b001 : out[1] = 1'b1;
                3'b010 : out[2] = 1'b1;
                3'b011 : out[3] = 1'b1;
                3'b100 : out[4] = 1'b1;
                3'b101 : out[5] = 1'b1;
                3'b110 : out[6] = 1'b1;
                3'b111 : out[7] = 1'b1;
		default: out = 0;
            endcase
        end
endmodule
module test_bench;
    reg [2:0] in;
	wire [7:0] out;

	decoder_3_8 dut(in,out);
	initial
	begin
		in=3'b000;
		#10;
	end
	always begin
		#10 in=3'b000;
		#10 in=3'b001;
		#10 in=3'b010;
		#10 in=3'b011;
		#10 in=3'b100;
		#10 in=3'b101;
		#10 in=3'b110;
		#10 in=3'b111;	
	end	
	initial begin
	$monitor("in: %b  out: %b", in, out);
	#90 $finish;
	end
endmodule
module HCF #(parameter N= 8)
    ( input [N-1:0] in1,in2,
      output [N-1:0] HCF );

    reg [N-1:0] i1,i2;

    always@(*)
        begin
            i1=in1;
            i2=in2;
            while(i1 != i2)
              begin
                if(i1 > i2) i1= i1 - i2;
                else i2= i2 - i1;
              end
        end
    
    assign HCF = i1;
endmodule
module test_bench #(parameter N= 8);
    reg  [N-1:0] in1;
	reg  [N-1:0] in2;
	wire [N-1:0] HCF;

	HCF dut(in1, in2, HCF);

	initial begin
		in1 = 27; in2 = 45; #10;
		in1 = 56; in2 = 84; #10;
		in1 = 49; in2 = 77; #10;
		in1 = 108; in2 = 24; #10;
		in1 = 17; in2 = 103; #10;
		in1 = 100; in2 = 70; #10;
		$finish;
	end
	
	initial
	$monitor("\t 1st INPUT: %d   2nd INPUT: %d  Highest Common Factor: %d",in1,in2,HCF);
endmodule
module carry_look_ahead_gen(
    input [3:0] a, b,
    input cin,
    output [3:0] sum,
    output carry
    );
wire p0, g0, p1, g1, p2, g2, p3, g3;
wire [3:0]c;

and (g0, a[0], b[0]),
    (g1, a[1], b[1]),
    (g2, a[2], b[2]),
    (g3, a[3], b[3]);

xor (p0, a[0], b[0]),
    (p1, a[1], b[1]),
    (p2, a[2], b[2]),
    (p3, a[3], b[3]);
    
xor (sum[0], p0, cin),
    (sum[1], p1, c0),
    (sum[2], p2, c1),
    (sum[3], p3, c2);

assign  c[0] = g0 | (p0 & cin),
        c[1] = g1 | (p1 & g0) | (p1 & p0 & cin),
        c[2] = g2 | (p2 & g1) | (p2 & p1 & g0) | (p2 & p1 & p0 & cin),
        c[3] = g3 | (p3 & g2) | (p3 & p2 & g1) | (p3 & p2 & p1 & g0) |(p3 & p2 & p1 & p0 & cin);
        
assign carry = c[3];
endmodule
module test_bench;
    reg [3:0] a, b;
    reg cin;
    wire [3:0] sum;
    wire carry;
    carry_look_ahead_gen dut(a, b, cin, sum, carry);
    
    initial
        begin
            a = 4'b1000; b = 4'b0011; cin = 1'b0;
        #10 a = 4'b0001; b = 4'b1010; cin = 1'b1;
        #10 a = 4'b0110; b = 4'b0110; cin = 1'b0;
        #10 a = 4'b0111; b = 4'b1110; cin = 1'b0;
        #10 a = 4'b1001; b = 4'b0110; cin = 1'b1;
        #10 a = 4'b1001; b = 4'b0100; cin = 1'b0;
        #10 a = 4'b1111; b = 4'b1110; cin = 1'b1;
    end
    initial
    begin $monitor("a=%b b=%b cin=%b Sum=%b Carry=%b",a,b,cin,sum,carry);
    #70 $finish;
    end
endmodule
module D_flipflop(
    input clk, reset, d,
    output reg Q
    );
    
    always@(posedge clk)
          begin
            if({reset})
                Q<= 1'b0;
            else 
                Q <= d;
            end

endmodule
module test_bench;
reg clk,rst,d;
wire Q;

  D_flipflop dut(clk,rst,d,Q);
  
  initial begin 
  clk=0;
  d=0;
  forever #4 clk=~clk;
  end
  
  initial 
    begin
     rst=1;
     #10;  
     rst=0;
    forever #10 d= ~d;
    end 
    
    initial begin
    $monitor("\t clk: %d  D: %d  Q: %d", clk, d, Q);
    #80 $finish;
    end
endmodule
module prime(
    input  [7:0]number,
    output reg is_prime
    );
parameter PRIME= 1'b1, Not_PRIME= 1'b0;

    always@(number) begin
    is_prime= check_prime(number);

        if(is_prime== 1'b1) $display("\t\t %d is a prime number", number);
        else $display("\t\t %d is not a prime number", number);
end


function automatic integer check_prime;
input [7:0]num;
integer i;
integer count;
begin
count= 0;
 for (i = 2; i < num/2; i = i + 1) begin
        if (num % i == 0) begin
          count = count+1;
          end
 end
 if(count== 0) check_prime= PRIME;
 else check_prime= Not_PRIME;
 end
endfunction
endmodule
module test_bench;
reg [7:0] number;
wire is_prime;

prime dut(number, is_prime);

always begin
number=8'd36;
#10;
number=8'd71;
#10;
number=8'd49;
#10;
number=8'd11;
#10;
number=8'd3;
#10;
number=8'd91;
#10;
#10;
end

initial #60 $finish;
endmodule
module PWM(
    input clk, rst, 
    output reg dout
    );
 
parameter period = 10;
integer count;
integer ton;
reg ncyc;
 
always@(posedge clk)
begin
     if(rst == 1'b1)
        begin
         count <= 0;
         ton   <= 0;
         ncyc  <= 1'b0;
        end   
     else 
       begin
            if(count <= ton) 
              begin
                  count <= count + 1;
                  dout  <= 1'b1;
                  ncyc  <= 1'b0;
              end
            else if (count < period)
              begin
                  count <= count + 1;
                  dout <= 1'b0;
                  ncyc <= 1'b0;
              end
            else
               begin
                   ncyc  <= 1'b1;
                   count <= 0;
               end
       end
end
 
always@(posedge clk)
begin
     if(rst == 1'b0) 
     begin 
         if(ncyc == 1'b1)
            begin
                if(ton < period)
                   ton <= ton + 1;
                else
                   ton <= 0;
            end
     end   
end

endmodule
module demux_2_1(
  input sel,
  input i,
  output y0, y1
  );
  
  assign {y0,y1} = sel?{1'b0,i}: {i,1'b0};

endmodule
module dmux_1_8(
    input [2:0]sel,
    input  i,
    output y0, y1, y2, y3, y4, y5, y6, y7
    );
    
    wire [5:0]z;
    
    demux_2_1 d1(sel[2], i, z[0], z[1]);

    demux_2_1 d2(sel[1], z[0], z[2], z[3]);
    demux_2_1 d3(sel[1], z[1], z[4], z[5]);

    demux_2_1 d4(sel[0], z[2], y0, y1);
    demux_2_1 d5(sel[0], z[3], y2, y3);
    demux_2_1 d6(sel[0], z[4], y4, y5);  
    demux_2_1 d7(sel[0], z[5], y6, y7);
endmodule
module test_bench;
    reg [2:0]sel;
    reg  i;
    wire y0, y1, y2, y3, y4, y5, y6, y7;
  
    dmux_1_8 demux(sel, i, y0, y1, y2, y3, y4, y5, y6, y7);
    always begin
    sel= $random;
    i= 1'b1;
    #10;
    end
    initial 
     begin $monitor("sel: %b  i: %b  y0 = %0b  y1 = %0b  y2 = %0b  y3 = %0b  y4 = %0b  y5 = %0b  y6 = %0b  y7 = %0b", sel, i, y0, y1, y2, y3, y4, y5, y6, y7);
     #80 $finish;
     end
endmodule
module test_bench;
reg [3:0] n;
wire [31:0] result;
integer x;
factorial dut(n, result);

always for(x=0; x<11; x=x+1) #10 n=x;

initial begin 
$monitor("\t\t factorial of %d is %0d", n, result);
#120 $finish;
end
endmodule
module factorial( input [3:0]n, output reg [31:0] result);
  
  function automatic integer fact(input integer i);
    begin
        if (i > 1)    fact = i * fact(i - 1);
        else    fact = 1;
    end
  endfunction

    always@(n)  result = fact(n);
    
endmodule
module fifo #( parameter WIDTH = 8, DEPTH = 16 )
 ( input clk, rst, wr_en, rd_en,
   input [WIDTH-1:0] wr_data,
   output reg [WIDTH-1:0] rd_data,
   output reg empty, full 
  );

   reg [WIDTH-1:0] mem [0:DEPTH-1];
   reg [WIDTH-1:0] rd_ptr = 0;
   reg [WIDTH-1:0] wr_ptr = 0;
   reg [WIDTH-1:0] next_wr_ptr;
   reg [WIDTH-1:0] next_rd_ptr;
   reg [DEPTH-1:0] num_items = 0;

   always @(posedge clk) 
    begin
        if (rst) 
	      begin
	         rd_ptr <= 0;
	         wr_ptr <= 0;
	         next_rd_ptr <= 0;
	         next_wr_ptr <= 0;
	         num_items <= 0;
	         empty <= 1;
	         full <= 0;
	      end
        else 
          begin
	         rd_ptr <= next_rd_ptr;
	         wr_ptr <= next_wr_ptr;
	         empty <= (num_items == 0);
	         full <= (num_items == DEPTH);

	         if (wr_en && !full) 
	         begin
	            mem[wr_ptr] <= wr_data;
	            next_wr_ptr <= (wr_ptr + 1) % DEPTH;
	            num_items <= num_items + 1;
	         end

	         if (rd_en && !empty) 
	         begin
	            rd_data <= mem[rd_ptr];
	            next_rd_ptr <= (rd_ptr + 1) % DEPTH;
	            num_items <= num_items - 1;
	         end
	    end
    end

endmodule
module test_bench;

   localparam WIDTH = 8, DEPTH = 16;

   reg clk, rst, wr_en, rd_en;
   reg [WIDTH-1:0] wr_data;
   wire [WIDTH-1:0] rd_data;
   wire empty, full;

   fifo #(WIDTH,DEPTH) dut(clk,rst,wr_en,rd_en,wr_data,rd_data,empty,full);
   
   initial begin 
   clk= 0;
   forever #5 clk = ~clk;
   end
   
    initial begin
	      rst = 1;
	      wr_en = 0;
	      rd_en = 0;
	      wr_data = 0;
	      #10 rst = 0;
	      #10 wr_en = 1; wr_data = 1;
	      #10 wr_en = 1; wr_data = 2;
	      #10 wr_en = 1; wr_data = 3;
	      #10 rd_en = 1;
	      #10 rd_en = 1;
	      #10 wr_en = 1; wr_data = 4;
	      #10 wr_en = 1; wr_data = 5;
	      #80 $finish;
    end
    
   always @(posedge clk) begin
      $display("RD Data: %d, Empty: %d, Full: %d", rd_data, empty, full);
   end
endmodule
module jhonson_counter #(parameter N=4)
    (input clk, reset,
    output reg [3:0] counter);

always@(posedge clk)
    begin
        if(reset) 
            counter <= 0; 
        else 
            counter <= {~counter[0], counter[N-1:1]};  
    end 
endmodule
module test_bench;

parameter N=4;
reg clk, reset;
wire [N-1:0] counter;

jhonson_counter dut(clk, reset, counter);

initial begin
clk= 1'b0;
forever #5 clk= ~clk;
end

initial begin 
reset= 1'b1;
#10;
reset= 1'b0;
end

initial begin
$monitor("\t\t counter: %d", counter);
#95 $finish;
end
endmodule
module parallel_adder(
    input [3:0] A, B,
    input carry_in,
    output [3:0] sum,
    output carry
    );
    wire [2:0] c;
    full_adder fa1(A[0], B[0], carry_in, sum[0], c[0]);
    full_adder fa2(A[1], B[1], c[0], sum[1], c[1]);
    full_adder fa3(A[2], B[2], c[1], sum[2], c[2]);
    full_adder fa4(A[3], B[3], c[2], sum[3], carry);
    
endmodule
module test_bench;
    reg [3:0] a;
    reg [3:0] b;
    reg cin;
    wire [3:0] sum;
    wire carry;
    
    parallel_adder dut (a,b,cin,sum,carry);
    
    always begin        
        a= $random;
        b= $random;
        cin= $random;
        #10; 
    end
    initial
    begin $monitor("a= %b  b= %b  cin= %b  sum= %b  carry= %b",a, b, cin, sum, carry);
    #60 $finish;
    end
endmodule
module test_bench;
reg clk, reset;
wire clk_by5;

freq_div_by5 dut(clk, reset, clk_by5);

initial begin
clk= 1'b0;
forever #10 clk= ~clk;
end

initial begin
reset= 1'b1;
#20
reset= 1'b0;
#380 $finish;
end

endmodule
module mod_5_counter
       (input clk,reset, output reg [2:0] counter);
        
        always@(posedge clk)
        begin
            if(reset)
            counter <= 0;
            else
                if(counter == 4)
                counter <= 0;
                else
                counter <= counter + 1;
         end        
endmodule
module freq_div_by5(
    input clk, reset,
    output clk_by5
    );
    wire[2:0] q;
    wire temp; 
    
    mod_5_counter M5C(clk, reset, q);
    
    D_flipflop D(~clk, reset, q[1], temp);
    
    or(clk_by5, q[1], temp);
    
endmodule
module Palindrome(
    input [15:0] number,
    output reg is_palindrome
    );
    parameter PALINDROME= 1'b1, Not_PALINDROME= 1'b0;
    always@(number)
        begin
        is_palindrome= check_palindrome(number);

            if(is_palindrome== 1'b1) $display("\t\t %d is a palindrome number", number);
            else $display("\t\t %d is not a palindrome odd number", number);
    end
    
    function check_palindrome;
        input [15:0]num;
        reg [15:0]lastDigit; 
        reg [15:0]reverseNum;
        reg [15:0]temp_num;
        begin
        temp_num= num;
        reverseNum= 1'b0;
            while (temp_num > 0) begin
            lastDigit = temp_num % 10;
            reverseNum = (reverseNum * 10) + lastDigit;
            temp_num = temp_num / 10;
        end
        
        if (num == reverseNum) check_palindrome= PALINDROME;
        else check_palindrome= Not_PALINDROME;
        end
  endfunction
endmodule
module test_bench;
reg [15:0]number;
wire is_palindrome;

Palindrome dut(number, is_palindrome);

always 
begin
number=16'd18681;
#10;
number=16'd3453;
#10;
number=16'd14441;
#10;
number=16'd51125;
#10;
number=16'd12021;
#10;
number=16'd35153;
#10;
number=16'd8998;
#10;
number=16'd6196;
#10;
end

initial #80 $finish;
endmodule
module universal_shift_register (
    input clk, reset, shift_left, shift_right,
    input [7:0] parallel_in,
    output [7:0] parallel_out
    );

    reg [7:0] reg_data;

    always @(posedge clk) 
     begin
        if (reset)
            reg_data <= 8'b0;

        else if (shift_left)
            reg_data <= {reg_data[6:0], 1'b0};

        else if (shift_right)
            reg_data <= {1'b0, reg_data[7:1]};

        else
            reg_data <= parallel_in;
     end

    assign parallel_out = reg_data;

endmodule
module test_bench;
  reg clk, reset, shift_left, shift_right;
  reg [7:0] parallel_in;
  wire [7:0] parallel_out;
  
  universal_shift_register dut (clk, reset, shift_left, shift_right, parallel_in, parallel_out);

  initial begin
    clk = 1'b0;
    forever #5 clk= ~clk;
  end

  initial begin
    reset = 1'b1;
    shift_left = 1'b0;
    shift_right = 1'b0;
    parallel_in = 8'he5;
    #10;
    
    reset = 1'b0;
    #10;

    shift_left = 1'b1;
    shift_right = 1'b0;
    #10;

    shift_left = 1'b0;
    shift_right = 1'b1;
    #10;
        
    shift_left = 1'b1;
    shift_right = 1'b0;
    #10;
    
    shift_left = 1'b1;
    shift_right = 1'b0;
    #10;

    shift_left = 1'b0;
    shift_right = 1'b1;
  end
  
  initial begin
  $monitor("\t input: %b right shift: %b  left shift: %b  output: %b", parallel_in, shift_right, shift_left, parallel_out);
  #75 $finish;
  end
endmodule
module half_adder(
	input a,b,
	output sum,carry
	);
    assign sum=a^b;
    assign carry=a&b;
endmodule
module vedic_mul_2_2(
    input [1:0] a,b,
	output [3:0] out
	 );
wire [3:0] w;

    and m1(out[0],a[0],b[0]);
    and m2(w[0],a[0],b[1]);
    and m3(w[1],a[1],b[0]);
    and m4(w[2],a[1],b[1]);
    
    half_adder ha1(w[0],w[1],out[1],w[3]);
    half_adder ha2(w[3],w[2],out[2],out[3]);
    
endmodule
module adder_4bit(
		input [3:0] x,y,
		output [3:0] z
		);
    assign z=x+y;
endmodule
module adder_6bit(
		input [5:0] x,y,
		output [5:0] z
		);
    assign z=x+y;
endmodule
module vedic_mul_4_4(
	input [3:0] a,b,
	output [7:0] out
    );
    
    wire [3:0] w3,w2,w1,w0,w;
    wire [5:0] w4;
	 
    vedic_mul_2_2 m1(b[3:2],a[3:2],w3[3:0]);
    vedic_mul_2_2 m2(b[3:2],a[1:0],w2[3:0]);
    vedic_mul_2_2 m3(b[1:0],a[3:2],w1[3:0]);
    vedic_mul_2_2 m4(b[1:0],a[1:0],w0[3:0]);
    
    adder_6bit m5({w3[3:0],2'b00},{2'b00,w2[3:0]},w4);
    
    adder_4bit m6(w1[3:0],{2'b00,w0[3:2]},w);
    
    adder_6bit m7(w4,{2'b00,w[3:0]},out[7:2]);
    
    assign out[1:0]=w0[1:0];
    
endmodule
module test_bench;
reg [3:0] a,b;
wire [7:0] out;

vedic_mul_4_4 dut(a,b,out);

always begin
a=$random;
b=$random;
#10;
end

initial begin
$monitor("%d * %d = %d", a,b,out);
#60 $finish;
end
endmodule
module dual_port_ram 
     #(parameter data_width=8,
	   parameter addr_width=4,
	   parameter depth=16)
	   
      ( input clk,
        input wr_en, 
        input [data_width-1:0] data_in,
        input [addr_width-1:0] addr_in_0,   //address for port 0
        input [addr_width-1:0] addr_in_1,   //address for port 1
        input  port_en_0,                   //enable port 0.
        input  port_en_1,                   //enable port 1.
        output [data_width-1:0] data_out_0, //output data from port 0.
        output [data_width-1:0] data_out_1  //output data from port 1.
    );

reg [data_width-1:0] ram [0:depth-1];

always@(posedge clk)
begin
    if(port_en_0 == 1 && wr_en == 1)    
        ram[addr_in_0] <= data_in;
        
end

assign data_out_0 = port_en_0 ? ram[addr_in_0] : 'dZ;   
assign data_out_1 = port_en_1 ? ram[addr_in_1] : 'dZ;   

endmodule
module test_bench;

parameter data_width = 8;
parameter addr_width = 4;
parameter depth = 16;
integer i;

	reg clk;
	reg wr_en;
	reg [data_width-1:0] data_in;
	reg [addr_width-1:0] addr_in_0;
	reg [addr_width-1:0] addr_in_1;
	reg port_en_0;
	reg port_en_1;
	wire [data_width-1:0] data_out_0;
	wire [data_width-1:0] data_out_1;

	dual_port_ram dut(clk, wr_en, data_in, addr_in_0, addr_in_1, port_en_0, port_en_1, data_out_0, data_out_1);

 initial begin
    clk= 1'b1;
    forever #5 clk = ~clk;
 end

initial begin
    addr_in_1 = 0;
    port_en_0 = 0;
    port_en_1 = 0;
    wr_en = 0;
    data_in = 0;
    addr_in_0 = 0;  
    #20;
        
    port_en_0 = 1;  
    wr_en = 1;
        
      for(i=1; i <= 16; i = i + 1) begin
            data_in = i;
            addr_in_0 = i-1;
            #10;
        end
        
    wr_en = 0;
    port_en_0 = 0;  
    port_en_1 = 1;  
        
        for(i=1; i <= 16; i = i + 1) begin
            addr_in_1 = i-1;
            #10;
            
        end
        port_en_1 = 0;
    end
initial begin
$monitor("write enable: %d  input data: %d  address 0: %d  address 1: %d  output 0: %d  output 1: %d", wr_en, data_in, addr_in_0, addr_in_1, data_out_0, data_out_1);
#340 $finish;
end
endmodule
module complement_2s(
    input [3:0] data,
    output signed [3:0] out
    );
    wire [3:0]temp;
    assign temp= 4'b1111 - data;
    assign out= temp + 4'b0001; 
    
endmodule
module test_bench;
reg [3:0] data;
wire signed [3:0]out;

complement_2s dut(data, out);

initial begin
        data= 4'd0;
        #10;
        data= 4'd1;
        #10;
        data= 4'd2;
        #10;
        data= 4'd3;
        #10;
        data= 4'd4;
        #10;
        data= 4'd5;
        #10;
        data= 4'd6;
        #10;
        data= 4'd7;
        #10;
        data= 4'd8;
        #10;
        data= 4'd9;
        #10;
        data= 4'd10;
        #10;
        data= 4'd11;
        #10;
        data= 4'd12;
        #10;
        data= 4'd13;
        #10;
        data= 4'd14;
        #10;
        data= 4'd15;
    end

initial
    begin $monitor("input number: %d  2's Complement: %d", data, out);
    #160 $finish;
    end
endmodule
module test_bench;
reg sel, i;
wire [1:0]y;

demux_1_2 dut(sel, i, y);
initial begin
sel=0; i=0; 
#10;
sel=0; i=1; 
#10;
sel=1; i=0; 
#10;
sel=1; i=1; 
end
initial 
     begin $monitor("sel: %b  i: %b  y[0]: %b  y[1]: %b", sel, i, y[0], y[1]);
     #40 $finish;
     end
endmodule
module n_bit_square(num, result);
    parameter n=4;
    input [n-1:0] num;
    output reg [2*n-1:0] result;
    reg [2*n-1:0] tmp;
    
    always @(*) begin
        tmp = num * num;
        result = tmp;
    end
endmodule
module test_bench;
parameter n=4;
reg [n-1:0]num;
wire [2*n-1:0]result;
n_bit_square dut(num, result);
always begin
			num=$random;
            #10;
		end
    initial
    begin $monitor("%d^2 = %0d ",num, result);
    #80 $finish;
    end
endmodule
module pipo(
    input clk, reset, 
    input [2:0] parallel_in,
    output [2:0] parallel_out
    );

    D_flipflop D2(parallel_in[2], clk, reset, parallel_out[2]);
    D_flipflop D1(parallel_in[1], clk, reset, parallel_out[1]);
    D_flipflop D0(parallel_in[0], clk, reset, parallel_out[0]);
    
endmodule
module test_bench;
reg clk, reset;
reg [2:0] parallel_in;
wire [2:0] parallel_out;

pipo dut(clk, reset, parallel_in, parallel_out);

initial begin
    clk=1'b0;
    forever #5 clk=~clk;
    end
    
 initial begin
    reset= 1'b1;
    parallel_in= 3'b000;
    #10 reset= 1'b0;
    end
    
    always #10 parallel_in= $random;
    
 initial begin
    $monitor("\t\t clk: %d  reset: %d  parallel_in: %b  parallel_out: %b", clk, reset, parallel_in, parallel_out);
    #100 $finish;
    end
endmodule
module logic_gates(
    input a, b,
    output reg and_g,
    output reg or_g,
    output reg not_g,
    output reg nand_g,
    output reg nor_g,
    output reg xor_g,
    output reg xnor_g
    );
    always@(*)
        begin
            and_g = a&b;
            or_g = a|b;
            not_g = ~a;
            nand_g = ~(a&b);
            nor_g = ~(a|b);
            xor_g = a^b;
            xnor_g = ~(a^b);
        end
    
endmodule
module tb_nor;
    reg a, b;
    wire nor_out;
         
    decoder_nor dut(a, b, nor_out);
    initial begin
            a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  nor: %b ",a, b, nor_out);
     #40 $finish;
     end
endmodule
module decoder_nor(
    input a,b,
    output nor_g 
    );
    wire [3:0]w;
    decoder_2_4 norgate({a,b}, w);
    assign nor_g= w[0];
endmodule
module tb_nand;
    reg a, b;
    wire nand_out;
         
    decoder_nand dut(a, b, nand_out);
    initial begin
            a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  nand: %b ",a, b, nand_out);
     #40 $finish;
     end
endmodule
module decoder_nand(
    input a,b,
    output nand_g 
    );
    wire [3:0]w;
    decoder_2_4 nandgate({a,b}, w);
    assign nand_g= ~w[3];
endmodule
module decoder_and(
    input a,b,
    output and_g 
    );
    wire [3:0]w;
    decoder_2_4 andgate({a,b}, w);
    assign and_g= w[3];
endmodule
module tb_and;
 reg a, b;
    wire and_out;
         
    decoder_and dut(a, b, and_out);
    initial begin
        #0  a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  and: %b ",a, b, and_out);
     #40 $finish;
     end
endmodule
module tb_or;
    reg a, b;
    wire or_out;
         
    decoder_or dut(a, b, or_out);
    initial begin
        #0  a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  or: %b ",a, b, or_out);
     #40 $finish;
     end
endmodule
module decoder_or(
    input a,b,
    output or_g 
    );
    wire [3:0]w;
    decoder_2_4 orgate({a,b}, w);
    assign or_g= ~w[0];
endmodule
module decoder_not(
    input a,
    output not_g 
    );
    wire [3:0]w;
    decoder_2_4 notgate({a,1'b0}, w);
    assign not_g= w[0];
endmodule
module tb_not;
    reg a;
    wire not_out;
         
    decoder_not dut(a, not_out);
    initial begin
        #0  a= 1'b0;
        #10 a= 1'b1;

    end
    initial 
     begin $monitor("a: %b  not: %b ",a, not_out);
     #20 $finish;
     end
endmodule
module half_adder(
    input a, b,
    output sout, cout
    );
    
    assign sout = a^b;
    assign cout = a&b;
    
endmodule
module test_bench_ha;
reg a, b;
  wire sout, cout;
  reg clk;

  half_adder dut(a, b, sout, cout);

  always #5 clk = ~clk;

  initial begin
    clk = 0;
    a = 0; b = 0;
    #10;
    a = 0; b = 1;
    #10;
    a = 1; b = 0;
    #10;
    a = 1; b = 1;
    #10;
    $finish;
  end
  
  always @(posedge clk) begin
    $display("a = %b, b = %b, sum = %b, carry = %b", a, b, sout, cout);
  end
endmodule
module full_adder(
    input a, b, cin,
    output sout, cout
    );
    
    assign sout = a ^ b ^ cin;
    assign cout = (a&b) | cin&(a^b);
endmodule
module test_bench;
  reg a, b, cin;
  wire sout, cout;
  reg clk;

  full_adder dut(a, b, cin, sout, cout);

  always #5 clk = ~clk;

  initial begin
    clk = 0;
    a = 0; b = 0; cin = 0;
    #10;
    a = 0; b = 0; cin = 1;
    #10;
    a = 0; b = 1; cin = 0;
    #10;
    a = 0; b = 1; cin = 1;
    #10;
    a = 1; b = 0; cin = 0;
    #10;
    a = 1; b = 0; cin = 1;
    #10;
    a = 1; b = 1; cin = 0;
    #10;
    a = 1; b = 1; cin = 1;
    #10;
    $finish;
  end
  
  always @(posedge clk) begin
    $display("a = %b, b = %b, cin = %b, sum = %b, carry = %b", a, b, cin, sout, cout);
  end
endmodule
module SR_flipflop(
    input clk,reset,S,R, 
    output reg Q);
    
    always@(posedge clk)
          begin
            if(reset)
            Q <= 1'b0;
            else
                begin
                case({S,R})
                2'b00:Q<=Q;
                2'b01:Q<=1'b0;
                2'b10:Q<=1'b1;
                default: Q<= 2'bxx;
                endcase
                end          
         end

endmodule
module test_bench;
reg clk,rst,d;
wire Q_sr, Q_jk, Q_t;

  D_using_SR_JK_T dut(clk,rst,d,Q_sr, Q_jk, Q_t);
  
  initial begin 
  clk=0;
  d=0;
  forever #4 clk=~clk;
  end
  
  initial 
    begin
     rst=1;
     #10;  
     rst=0;
    forever #10 d= ~d;
    end 
    
    initial begin
    $monitor("\t clk: %d  D: %d  Q_sr: %d  Q_jk: %d  Q_t: %d", clk, d, Q_sr, Q_jk, Q_t);
    #80 $finish;
    end
endmodule
module D_using_SR_JK_T(
    input clk, reset, D,
    output Q_sr, Q_jk, Q_t
    );
    wire w;
    
    SR_flipflop SR(clk, reset, D, ~D, Q_sr);
    
    JK_flipflop JK(D, ~D, clk, reset, Q_jk);

    assign w= D ^ Q_t;
    T_flipflop T(w, clk, reset, Q_t);
    
endmodule
module even_parity_generator (
  input wire [7:0] data_in,
  output wire parity
);

assign parity = ^data_in;

endmodule
module even_parity_checker(
  input wire [7:0] data_in,
  input wire parity_in,
  output wire error
);

assign error = ^({parity_in, data_in});

endmodule
module test_bench_pg;
  reg [7:0] data_in;
  wire parity;
  reg clk;

  even_parity_generator dut(data_in, parity);

  always #5 clk = ~clk;
  
  initial begin
    clk = 0;
    data_in = 8'b00000000;
    #10;
    data_in = 8'b00000001;
    #10;
    data_in = 8'b00000011;
    #10;
    data_in = 8'b10000000;
    #10;
    data_in = 8'b11011111;
    #10;
    data_in = 8'b01010101;
    #10;
    data_in = 8'b10101010;
    #10;
    $finish;
  end

  always @(posedge clk) begin
    $display("Data: %b, Parity: %b", data_in, parity);
  end
endmodule
module test_bench_pc;
  reg [7:0] data_in;
  reg parity_in;
  reg clk;
  wire error;

  even_parity_checker dut(data_in, parity_in, error);

  always #5 clk = ~clk;

  initial begin
    clk = 0;
    data_in = 8'b00000000;
    parity_in = 1;
    #10;
    data_in = 8'b00000001;
    parity_in = 0;
    #10;
    data_in = 8'b00000011;
    parity_in = 1;
    #10;
    data_in = 8'b10000000;
    parity_in = 0;
    #10;
    data_in = 8'b11011111;
    parity_in = 1;
    #10;
    data_in = 8'b01010101;
    parity_in = 0;
    #10;
    data_in = 8'b10101010;
    parity_in = 1;
    #10;
    $finish;
  end

  always @(posedge clk) begin
    $display("Data: %b, Parity: %b, Error: %b", data_in, parity_in, error);
  end
endmodule
module mod_3_counter
       (input clk,reset, output reg [1:0] counter);
        
        always@(posedge clk)
        begin
            if(reset)
            counter <= 0;
            else
                if(counter == 2)
                counter <= 0;
                else
                counter <= counter + 1;
         end        
endmodule
module freq_div_by3(
    input clk, reset,
    output clk_by3
    );
    wire[1:0] q;
    wire temp; 
    
    mod_3_counter M3C(clk, reset, q);
    
    D_flipflop D(~clk, reset, q[1], temp);
    
    or(clk_by3, q[1], temp);
    
endmodule
module freq_div(
    input clk, reset,
    output new_clk
    );
    wire t1, t2;
    
    freq_div_by3 FD3(clk, reset, t1);
    
    dual_edge_trig_ff DETF(clk, reset, t1, t2);
    
    xor(new_clk, t1, t2);
endmodule
module test_bench;
reg clk, reset;
wire new_clk;

freq_div dut(clk, reset, new_clk);

initial begin
clk= 1'b0;
forever #10 clk= ~clk;
end
initial begin
reset= 1'b1;
#20
reset= 1'b0;
#200 $finish;
end
endmodule
module JK_using_SR_D_T(
    input J, K, clk, reset,
    output Q_sr, Q_d, Q_t
    );
    wire w1, w2, w3, w4, w5, w6, w7, w8;
    
    assign w1= J & (~Q_sr);
    assign w2= K & Q_sr;
    SR_flipflop SR(clk, reset, w1, w2, Q_sr);
    
    assign w3= J & (~Q_d);
    assign w4= (~K) & Q_d;
    assign w5= w3 | w4;
    D_flipflop D(w5, clk, reset, Q_d);
    
    assign w6= J & (~Q_t);
    assign w7= K & Q_t;
    assign w8= w6 | w7;
    T_flipflop T(w8, clk, reset, Q_t);
    
endmodule
module D_flipflop(
    input clk, reset, d,
    output reg Q
    );
    
    always@(posedge clk)
          begin
            if({reset})
            Q<= 1'b0;
            else 
            Q <= d;
            end

endmodule
module test_bench;
reg clk,rst,J,K;
wire Q_sr, Q_d, Q_t;

  JK_using_SR_D_T dut(J, K, clk, rst, Q_sr, Q_d, Q_t);
initial begin 
        clk = 0;
       forever #5 clk = ~clk;
       end 
       
 initial begin
        rst=1;
        J = 0;
        K = 0;
        #10;
        rst=0;
    end
    
    always begin
        J=0;
        K=0;
        #10;
        J=0;
        K=1;
        #10;
        J=1;
        K=0;
        #10;
        J=1;
        K=1;
        #10;

    end
  initial begin
  $monitor("\t clk: %d  J: %d  K: %d  Q_sr: %d  Q_d: %d  Q_t:%d", clk,J,K,Q_sr, Q_d, Q_t);
  #90 $finish;
  end
endmodule
module SR_using_JK_D_T(
    input S, R, clk, rst,
    output Q_jk, Q_d, Q_t
    );
    wire w1, w2, w3, w4, w5;

    JK_flipflop JK(S, R, clk, rst, Q_jk);
    
    assign w1= ~R & Q_d;
    assign w2= S | w1;
    D_flipflop D(w2, clk, rst, Q_d);
   
    assign w3= S & ~Q_t;
    assign w4= R & Q_t;
    assign w5= w3 | w4;
    T_flipflop T(w5, clk, rst, Q_t);

endmodule
module JK_flipflop(
    input j,k,clk,reset,
    output reg Q
    );
    always@(posedge clk)
          begin
            if({reset})
            Q <= 1'b0;
            else
                begin
                	case({j,k})
                	2'b00:Q<=Q;
               	2'b01:Q<=1'b0;
                	2'b10:Q<=1'b1;
                	2'b11:Q<=~Q;
                	endcase
                end          
         end
endmodule
module test_bench;
reg S, R, clk, rst;
wire Q_jk, Q_d, Q_t;

  SR_using_JK_D_T dut(S, R, clk, rst, Q_jk, Q_d, Q_t);
initial begin 
        clk = 0;
       forever #5 clk = ~clk;
       end 
       
 initial begin
        rst=1;
        S = 0;
        R = 0;
        #10;
        rst=0;
    end
    
    always begin
        S=0;
        R=0;
        #10;
        S=0;
        R=1;
        #10;
        S=1;
        R=0;
        #10;
        S=1;
        R=1;
        #10;

    end
  initial begin
  $monitor("\t clk: %d  S: %d  R: %d  Q_jk: %d  Q_d: %d  Q_t:%d", clk,S,R,Q_jk, Q_d, Q_t);
  #90 $finish;
  end
endmodule
module mux(o,i1,i2,s);                  //2x1 MUX
input i1,i2,s;
output o;
wire x1,x2,sc;
not(sc,s);
and(x1,i1,sc);
and(x2,i2,s);
or(o,x1,x2);
endmodule
module sine_wave_generator(o,t);
input [9:0]t;
output [15:0]o;
reg [15:0] i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,i50,i51,i52,i53,i54,i55,i56,i57,i58,i59,i60,i61,i62,i63,i64;
mux_16_64 mux_1(o,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,i50,i51,i52,i53,i54,i55,i56,i57,i58,i59,i60,i61,i62,i63,i64,t);
initial
begin
i1=1000;               //1000*sin(t*360/64)+1000 values recorded in order
i2=1098;
i3=1195;
i4=1290;
i5=1383;
i6=1471;
i7=1556;
i8=1634;
i9=1707;
i10=1773;
i11=1831;
i12=1882;
i13=1924;
i14=1957;
i15=1981;
i16=1995;
i17=2000;
i18=1995;
i19=1981;
i20=1957;
i21=1924;
i22=1882;
i23=1831;
i24=1773;
i25=1707;
i26=1634;
i27=1556;
i28=1471;
i29=1383;
i30=1290;
i31=1195;
i32=1098;
i33=1000;
i34=902;
i35=805;
i36=710;
i37=617;
i38=529;
i39=444;
i40=366;
i41=293;
i42=227;
i43=169;
i44=118;
i45=76;
i46=43;
i47=19;
i48=5;
i49=0;
i50=5;
i51=19;
i52=43;
i53=76;
i54=118;
i55=169;
i56=227;
i57=293;
i58=366;
i59=444;
i60=529;
i61=617;
i62=710;
i63=805;
i64=902;
end
endmodule
module mux_16_64(o,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,i50,i51,i52,i53,i54,i55,i56,i57,i58,i59,i60,i61,i62,i63,i64,s);
input [15:0]i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i26,i27,i28,i29,i30,i31,i32,i33,i34,i35,i36,i37,i38,i39,i40,i41,i42,i43,i44,i45,i46,i47,i48,i49,i50,i51,i52,i53,i54,i55,i56,i57,i58,i59,i60,i61,i62,i63,i64;
input [5:0]s;
output [15:0]o;
wire [15:0]x1,x2,x3,x4,x5,x6,x7,x8;

mux_16_8 mux_16_8_1(x1,i1,i2,i3,i4,i5,i6,i7,i8,s[2:0]);
mux_16_8 mux_16_8_2(x2,i9,i10,i11,i12,i13,i14,i15,i16,s[2:0]);
mux_16_8 mux_16_8_3(x3,i17,i18,i19,i20,i21,i22,i23,i24,s[2:0]);
mux_16_8 mux_16_8_4(x4,i25,i26,i27,i28,i29,i30,i31,i32,s[2:0]);
mux_16_8 mux_16_8_5(x5,i33,i34,i35,i36,i37,i38,i39,i40,s[2:0]);
mux_16_8 mux_16_8_6(x6,i41,i42,i43,i44,i45,i46,i47,i48,s[2:0]);
mux_16_8 mux_16_8_7(x7,i49,i50,i51,i52,i53,i54,i55,i56,s[2:0]);
mux_16_8 mux_16_8_8(x8,i57,i58,i59,i60,i61,i62,i63,i64,s[2:0]);

mux_16_8 mux_16_8_9(o,x1,x2,x3,x4,x5,x6,x7,x8,s[5:3]);
endmodule
module mux_16(o,i1,i2,s);           //2x1 MUX with 16-bit I/O
input [15:0]i1,i2;
input s;
output [15:0]o;
mux mux_1[15:0](o,i1,i2,s);
endmodule
module TB_SWG;
reg [9:0]t;
wire [15:0]o;
sine_wave_generator SWG(o,t);
integer i;
initial
begin
$monitor("o=%d",o);
    #5 t=0;
     for(i=0;i<1024;i=i+1)
    begin
        #5 t=i;
    end
end
endmodule
module mux_16_8(o,i1,i2,i3,i4,i5,i6,i7,i8,s);  //8x1 MUX with 16-bit I/O
input [15:0]i1,i2,i3,i4,i5,i6,i7,i8;
input [2:0]s;
output [15:0]o;
wire [15:0]x1,x2,x3,x4;
wire [15:0]y1,y2;

mux_16 mux_16_1(x1,i1,i2,s[0]);
mux_16 mux_16_2(x2,i3,i4,s[0]);
mux_16 mux_16_3(x3,i5,i6,s[0]);
mux_16 mux_16_4(x4,i7,i8,s[0]);

mux_16 mux_16_5(y1,x1,x2,s[1]);
mux_16 mux_16_6(y2,x3,x4,s[1]);

mux_16 mux_16_7(o,y1,y2,s[2]);

endmodule
module test_bench_fs;
reg a, b, bin;
  wire diff, bout;
  reg clk;

  fs_nand dut(a, b, bin, diff, bout);
  
  always #5 clk = ~clk;
  
  initial begin
    clk = 0;
    a = 0; b = 0; bin = 0;
    #10;
    a = 0; b = 0; bin = 1;
    #10;
    a = 0; b = 1; bin = 0;
    #10;
    a = 0; b = 1; bin = 1;
    #10;
    a = 1; b = 0; bin = 0;
    #10;
    a = 1; b = 0; bin = 1;
    #10;
    a = 1; b = 1; bin = 0;
    #10;
    a = 1; b = 1; bin = 1;
    #10;
    $finish;
  end

  always @(posedge clk) begin
    $display("a: %b, b: %b, bin: %b, difference: %b, borrow: %b", a, b, bin, diff, bout);
  end
endmodule
module test_bench_ha;
  reg a, b;
  wire sout, cout;
  reg clk;

  ha_nand dut(a, b, sout, cout);

  always #5 clk = ~clk;

  initial begin
    clk = 0;
    a = 0; b = 0;
    #10;
    a = 0; b = 1;
    #10;
    a = 1; b = 0;
    #10;
    a = 1; b = 1;
    #10;
    $finish;
  end
  
  always @(posedge clk) begin
    $display("a = %b, b = %b, sum = %b, carry = %b", a, b, sout, cout);
  end
endmodule
module fa_nand(
  input a, b, cin,
  output sout, cout
    );
    wire [6:0]w;
    nand n0(w[0], a, b);
    nand n1(w[1], a, w[0]);
    nand n2(w[2], b, w[0]);
    nand n3(w[3], w[1], w[2]);
    nand n4(w[4], w[3], cin);
    nand n5(w[5], w[3], w[4]);
    nand n6(w[6], w[4], cin);
    nand n7(sout, w[5], w[6]);
    nand n8(cout, w[0], w[4]);

endmodule
module test_bench_hs;
reg a, b;
  wire diff, bout;
  reg clk;

  hs_nand dut(a, b, diff, bout);
  
  always #5 clk = ~clk;
  
  initial begin
    clk = 0;
    a = 0; b = 0;
    #10;
    a = 0; b = 1;
    #10;
    a = 1; b = 0;
    #10;
    a = 1; b = 1;
    #10
    $finish;
  end

  always @(posedge clk) begin
    $display("a: %b, b: %b, difference: %b, borrow: %b", a, b, diff, bout);
  end
endmodule
module hs_nand(
input a, b,
  output sout, cout
    );
    wire [2:0]w;
    nand n0(w[0], a, b);
    nand n1(w[1], a, w[0]);
    nand n2(w[2], b, w[0]);
    nand n3(sout, w[1], w[2]);
    nand n4(cout, w[2], w[2]);
endmodule
module fs_nand(
  input a, b, bin,
  output sout, cout
    );
    wire [6:0]w;
    nand n0(w[0], a, b);
    nand n1(w[1], a, w[0]);
    nand n2(w[2], b, w[0]);
    nand n3(w[3], w[1], w[2]);
    nand n4(w[4], w[3], bin);
    nand n5(w[5], w[3], w[4]);
    nand n6(w[6], w[4], bin);
    nand n7(sout, w[5], w[6]);
    nand n8(cout, w[2], w[6]);

endmodule
module test_bench_fa;
reg a, b, cin;
  wire sout, cout;
  reg clk;

  fa_nand dut(a, b, cin, sout, cout);

  always #5 clk = ~clk;

  initial begin
    clk = 0;
    a = 0; b = 0; cin = 0;
    #10;
    a = 0; b = 0; cin = 1;
    #10;
    a = 0; b = 1; cin = 0;
    #10;
    a = 0; b = 1; cin = 1;
    #10;
    a = 1; b = 0; cin = 0;
    #10;
    a = 1; b = 0; cin = 1;
    #10;
    a = 1; b = 1; cin = 0;
    #10;
    a = 1; b = 1; cin = 1;
    #10;
    $finish;
  end
  
  always @(posedge clk) begin
    $display("a = %b, b = %b, cin = %b, sum = %b, carry = %b", a, b, cin, sout, cout);
  end
endmodule
module ha_nand(
  input a, b,
  output sout, cout
    );
    wire [2:0]w;
    nand n0(w[0], a, b);
    nand n1(w[1], a, w[0]);
    nand n2(w[2], b, w[0]);
    nand n3(sout, w[1], w[2]);
    nand n4(cout, w[0], w[0]);
endmodule
module nor_gate(
    input Vin1, Vin2,
    output Vout
    );
    supply0 gnd;
    supply1 vdd;
    wire temp;
    pmos (temp, vdd, Vin1);
    pmos (Vout, temp, Vin2);
    nmos (Vout, gnd, Vin1);
    nmos (Vout, gnd, Vin2);
endmodule
module tb_nand;
    reg Vin1, Vin2;
    wire Vout;
    nand_gate dut(Vin1, Vin2, Vout);
    initial Vin1= 1'b0;
    initial Vin2= 1'b0;
    initial forever #50 Vin1 = ~Vin1;
    initial forever #100 Vin2 = ~Vin2;
    initial #600 $finish;
endmodule
module nand_gate(
    input Vin1, Vin2,
    output Vout
    );
    supply0 gnd;
    supply1 vdd;
    wire temp;
    pmos (Vout, vdd, Vin1);
    pmos (Vout, vdd, Vin2);
    nmos (temp, gnd, Vin2);
    nmos (Vout, temp, Vin1);
endmodule
module tb_nor;
    reg Vin1, Vin2;
    wire Vout;
    nor_gate dut(Vin1, Vin2, Vout);
    initial Vin1= 1'b0;
    initial Vin2= 1'b0;
    initial forever #50 Vin1 = ~Vin1;
    initial forever #100 Vin2 = ~Vin2;
    initial #600 $finish;
endmodule
module test_bench;
reg clk,rst,t;
wire Q_sr, Q_jk, Q_d;
  T_using_SR_JK_D dut(clk, rst, t, Q_sr, Q_jk, Q_d);
  
  initial 
  begin 
       clk=0;
       t=0;
       forever #4 clk=~clk;
  end
    
  initial 
      begin
          rst=1;
          #10;
          rst=0;
          forever
          begin   
          #10 t = 1'b1;
          #20  t = 1'b0; 
          end
      end
    initial begin
    $monitor("\t clock: %b  T: %b  Q_sr: %d  Q_jk: %d  Q_d: %b",clk,t,Q_sr, Q_jk, Q_d);
    #100$finish;
    end
endmodule
module T_using_SR_JK_D(
    input clk, reset, T,
    output Q_sr, Q_jk, Q_d
    );
    wire w1, w2, w3;
    
    assign w1= T & (~Q_sr);
    assign w2= T & Q_sr;
    SR_flipflop SR(clk, reset, w1, w2, Q_sr);
    
    JK_flipflop JK(T, T, clk, reset, Q_jk);
    
    assign w3= T ^ Q_d;
    D_flipflop D(w3, clk, reset, Q_d);
    
endmodule
module test_decoder;
    reg [6:0] ham_data_encoder;
    wire [2:0]error_position;
    wire is_error; 
    wire [3:0]data;
    
    
    hamming_decoder dut(ham_data_encoder,data,error_position,is_error);
    
    initial begin   
     ham_data_encoder= 7'b0110011;//error input at  0th position
    
    #20 ham_data_encoder= 7'b1110011;//error input at  7th position
    
    #20 ham_data_encoder= 7'b0110111;//error input at  3rd position

    end
    
    initial begin
    $monitor("\t\t Decoded Data: %b  Is there an Error=%b  Error is at Position: %d  \n",   data,is_error,error_position);
    #60 $finish;
    end
endmodule
module test_encoder;
    reg [3:0]data;
    wire [6:0] ham_data_encoder;
    
    hamming_encoder dut(data, ham_data_encoder);
    
    initial begin
     data=4'b0110;	
     #2 $display("\n \t Output of Hamming Encoder: %b \n",ham_data_encoder);
    #10 $stop;  //we will get output=1010101, please check in console after run the simulation
    end
    endmodule
module hamming_encoder(
    input [3:0]data,
    output [6:0] ham_data_encoder
    );
    
    assign ham_data_encoder[0]=data[0]^data[1]^data[3]; // P1= 1 xor 3 xor 5 xor 7
    
    assign ham_data_encoder[1]=data[0]^data[2]^data[3]; // P2= 2 xor 3 xor 6 xor 7
    
    assign ham_data_encoder[2]=data[0];
    
    assign ham_data_encoder[3]=data[1]^data[2]^data[3]; // P3= 4 xor 5 xor 6 xor 7
    
    assign ham_data_encoder[4]=data[1];
    
    assign ham_data_encoder[5]=data[2];
    
    assign ham_data_encoder[6]=data[3];
    
endmodule
module hamming_decoder(
    input [6:0] ham_data_encoder,
    output [3:0] data,
    output [2:0] error_position,
    output is_error
    ); 
    
    assign data[0]= ham_data_encoder[2];
    assign data[1]= ham_data_encoder[4];
    assign data[2]= ham_data_encoder[5];
    assign data[3]= ham_data_encoder[6];
    
    assign c1= ham_data_encoder[0]^ham_data_encoder[2]^ham_data_encoder[4]^ham_data_encoder[6]; // C1= 1 xor 3 xor 5 xor 7
     
    assign c2= ham_data_encoder[1]^ham_data_encoder[2]^ham_data_encoder[5]^ham_data_encoder[6]; // C2= 2 xor 3 xor 6 xor 7
    
    assign c3= ham_data_encoder[3]^ham_data_encoder[4]^ham_data_encoder[5]^ham_data_encoder[6]; // C3= 4 xor 5 xor 6 xor 7
    
    assign error_position= {c3,c2,c1};//position of error, 

    assign is_error = c3 |c2 | c1;//or (any '1'=>is_error=1)
  
endmodule
module spi_state(
    input    wire  clk,           // System clock
    input    wire  reset,         // Asynchronous system reset
    input    wire  [15:0] datain, // Binary input vector
    output   wire  spi_cs_l,      //SPI Active-low chip select
    output   wire  spi_sclk,      // SPI bus clock
    output   wire  spi_data,      // SPI bus data
    output [4:0]counter
    );

    reg [15:0] MOSI;     // SPI shift register
    reg [4:0] count;     // Control counter
    reg cs_l;            // SPI chip select (active-low)
    reg sclk; 
    reg [2:0]state;
    
    always@(posedge clk or posedge reset)
        if(reset) begin
            MOSI <= 16'b0;
            count<= 5'd16;
            cs_l <= 1'b1;
            sclk <= 1'b0;
        end		
    
        else begin
            case (state)
            	
                0: begin
                    sclk <= 1'b0;
                    cs_l <= 1'b1;
                    state<=1;
                end
    
                1: begin
                    sclk <= 1'b0;
                    cs_l <= 1'b0;
                    MOSI <=datain[count-1];
                    count <=count-1;
                    state <=2;
                end
    
                2: begin
                    sclk <= 1'b1;
                    if(count > 0)
                        state<=1;
                    else begin
                        count<=16;
                        state<=0;
                    end
                end
    
                default:state<=0;
    
            endcase
        end

    assign spi_cs_l = cs_l;
    assign spi_sclk = sclk;
    assign spi_data = MOSI; 
    assign counter=count;
    
endmodule
module test_bench;
	reg clk;
	reg reset;
	reg [15:0]datain;
	wire spi_cs_l;
	wire spi_sclk;
	wire spi_data;
	wire [4:0]counter;

	spi_state dut(clk, reset, datain, spi_cs_l, spi_sclk, spi_data, counter);

	initial begin
		clk = 0;
		reset = 1;
		datain = 0;
	end

	always #5 clk=~clk;

    initial begin
    
    #10 reset=1'b0;
    
    #10  datain=16'h0412;
    #335 datain=16'h4839;
    #335 datain=16'habeb;

    end
endmodule
module test_bench_fs;
  reg a, b, bin;
  wire diff, bout;
  reg clk;

  full_subtractor dut(a, b, bin, diff, bout);
  
  always #5 clk = ~clk;
  
  initial begin
    clk = 0;
    a = 0; b = 0; bin = 0;
    #10;
    a = 0; b = 0; bin = 1;
    #10;
    a = 0; b = 1; bin = 0;
    #10;
    a = 0; b = 1; bin = 1;
    #10;
    a = 1; b = 0; bin = 0;
    #10;
    a = 1; b = 0; bin = 1;
    #10;
    a = 1; b = 1; bin = 0;
    #10;
    a = 1; b = 1; bin = 1;
    #10;
    $finish;
  end

  always @(posedge clk) begin
    $display("a: %b, b: %b, bin: %b, difference: %b, borrow: %b", a, b, bin, diff, bout);
  end
endmodule
module test_bench_hs;
  reg a, b;
  wire diff, bout;
  reg clk;

  half_subtractor dut(a, b, diff, bout);
  
  always #5 clk = ~clk;
  
  initial begin
    clk = 0;
    a = 0; b = 0;
    #10;
    a = 0; b = 1;
    #10;
    a = 1; b = 0;
    #10;
    a = 1; b = 1;
    #10
    $finish;
  end

  always @(posedge clk) begin
    $display("a: %b, b: %b, difference: %b, borrow: %b", a, b, diff, bout);
  end
endmodule
module half_subtractor(
  input a, b,
  output diff, bout
);

  assign diff = a ^ b;
  assign bout = ~a & b;
  
endmodule
module full_subtractor(
  input a, b, bin,
  output diff, bout
);

  assign diff = a ^ b ^ bin;
  assign bout = (~a & (b^bin)) | (b & bin) ;
endmodule
module demux_and_gate(
    input a, b,
    output and_g
    );
    wire w;
    
    demux_1_2 andgate(b, a, w, and_g);
endmodule
module tb_and;
    reg a, b;
    wire and_out;
         
    demux_and_gate dut(a, b, and_out);
    initial begin
            a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  and: %b ",a, b, and_out);
     #40 $finish;
     end
endmodule
module tb_or;
    reg a, b;
    wire or_out;
         
    demux_or_gate dut(a, b, or_out);
    initial begin
            a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  or: %b ",a, b, or_out);
     #40 $finish;
     end
endmodule
module demux_or_gate(
    input a, b,
    output or_g
    );
        wire w0, w1, w2;
        
    demux_1_2 gate(b, ~a, w0, w1);
    demux_1_2 not_t(w0, 1'b1, or_g, w2);
endmodule
module demux_not_gate(
    input a,
    output not_g
    );
        wire w;

    demux_1_2 notgate(a, 1'b1, not_g, w);
endmodule
module tb_not;
    reg a;
    wire not_out;
         
    demux_not_gate dut(a, not_out);
    initial begin
            a= 1'b0;
        #10 a= 1'b1;

    end
    initial 
     begin $monitor("a: %b  not: %b ",a, not_out);
     #20 $finish;
     end
endmodule
module tb_nor;
    reg a, b;
    wire nor_out;
         
    demux_nor dut(a, b, nor_out);
    initial begin
            a= 1'b0; b= 1'b0;
        #10 a= 1'b0; b= 1'b1;
        #10 a= 1'b1; b= 1'b0;
        #10 a= 1'b1; b= 1'b1;
    end
    initial 
     begin $monitor("a: %b  b: %b  nor: %b ",a, b, nor_out);
     #40 $finish;
     end
endmodule
module demux_nor(
    input a, b,
    output nor_g
    );
        wire w;
        
    demux_1_2 norgate(b, ~a, nor_g, w);
endmodule
module demux_nand(
    input a, b,
    output nand_g
    );
    wire w0, w1, w2;
    
    demux_1_2 nandgate(b, a, w0, w1);
    demux_1_2 not_t(w1, 1'b1, nand_g, w2);
endmodule