dakies/OSS_Verilog huggingface dataset:
module adder_4(x,y,c0,c4,F,Gm,Pm);
      input [4:1] x;
      input [4:1] y;
      input c0;
      output c4,Gm,Pm;
      output [4:1] F;

      wire p1,p2,p3,p4,g1,g2,g3,g4;
      wire c1,c2,c3;
      adder adder1(
                 .X(x[1]),
                     .Y(y[1]),
                     .Cin(c0),
                     .F(F[1]),
                     .Cout()
                );

      adder adder2(
                 .X(x[2]),
                     .Y(y[2]),
                     .Cin(c1),
                     .F(F[2]),
                     .Cout()
                );  

      adder adder3(
                 .X(x[3]),
                     .Y(y[3]),
                     .Cin(c2),
                     .F(F[3]),
                     .Cout()
                );

      adder adder4(
                 .X(x[4]),
                     .Y(y[4]),
                     .Cin(c3),
                     .F(F[4]),
                     .Cout()
                );      

        CLA CLA(
            .c0(c0),
            .c1(c1),
            .c2(c2),
            .c3(c3),
            .c4(c4),
            .p1(p1),
            .p2(p2),
            .p3(p3),
            .p4(p4),
            .g1(g1),
            .g2(g2),
            .g3(g3),
            .g4(g4)
        );



  assign   p1 = x[1] ^ y[1],      
           p2 = x[2] ^ y[2],
           p3 = x[3] ^ y[3],
           p4 = x[4] ^ y[4];

  assign   g1 = x[1] & y[1],
           g2 = x[2] & y[2],
           g3 = x[3] & y[3],
           g4 = x[4] & y[4];

  assign Pm = p1 & p2 & p3 & p4,
         Gm = g4 ^ (p4 & g3) ^ (p4 & p3 & g2) ^ (p4 & p3 & p2 & g1);
endmodule
module CLA(c0,c1,c2,c3,c4,p1,p2,p3,p4,g1,g2,g3,g4);

     input c0,g1,g2,g3,g4,p1,p2,p3,p4;
     output c1,c2,c3,c4;

     assign c1 = g1 ^ (p1 & c0),
            c2 = g2 ^ (p2 & g1) ^ (p2 & p1 & c0),
            c3 = g3 ^ (p3 & g2) ^ (p3 & p2 & g1) ^ (p3 & p2 & p1 & c0),
            c4 = g4^(p4&g3)^(p4&p3&g2)^(p4&p3&p2&g1)^(p4&p3&p2&p1&c0);
endmodule
module adder(X,Y,Cin,F,Cout);

  input X,Y,Cin;
  output F,Cout;

  assign F = X ^ Y ^ Cin;
  assign Cout = (X ^ Y) & Cin | X & Y;
endmodule
module adder32_tb;
  
  reg [31:0] A;
  reg [31:0] B;
  wire [31:0] S;
  wire C32;
  
  integer i; 
  integer error = 0; 
  reg [33:0] expected_sum; 
  
  // Instantiate the module
  adder_32bit uut (
    .A(A), 
    .B(B), 
    .S(S), 
    .C32(C32)
  );
  
  // Randomize inputs and check output
  initial begin
    for (i = 0; i < 100; i = i + 1) begin
      A = $random;
      B = $random;
      #10; 
      // Calculate expected sum and carry out
      expected_sum = A + B;
      error = (S !== expected_sum[31:0] || C32 !== expected_sum[32]) ? error+1 : error; 
    end
    if (error == 0) begin
            $display("===========Your Design Passed===========");
    end
    else begin
    $display("===========Test completed with %d /100 failures===========", error);
    end
  end

endmodule
module tb_multi_16bit;
  
  reg clk;
  reg rst_n;
  reg start;
  reg [15:0] ain;
  reg [15:0] bin;
  wire [31:0] yout;
  wire done;

  integer i; // Declare the loop variable here
  integer fail_count = 0; // Declare a variable to count the failures
  integer timeout; // Declare a timeout counter here
  reg [31:0] expected_product; // Declare a variable to store the expected product

  // Instantiate the module
  multi_16bit uut (
    .clk(clk), 
    .rst_n(rst_n),
    .start(start),
    .ain(ain), 
    .bin(bin), 
    .yout(yout),
    .done(done)
  );
  
  // Clock generation
  always begin
    #5 clk = ~clk;
  end

  // Randomize inputs and check output
  initial begin
    clk = 0; // Initialize clock
    rst_n = 1; // De-assert reset
    start = 0; // Initialize start

    // Perform reset
    rst_n = 0;
    for (i = 0; i < 100; i = i + 1) begin
      #100;
      rst_n = 1;
      #50;
      ain = $random;
      bin = $random;
      #50;
      start = 1; // Start the operation
      while(done !== 1) begin
        #10;
      end
      expected_product = ain * bin;
      
      if (done == 1) begin
        fail_count = (yout == expected_product)? fail_count:fail_count+1;
      end
      start = 0; // Stop the operation
      rst_n = 0;
      #100;
    end
    
    if (fail_count == 0) begin
        $display("===========Your Design Passed===========");
    end
    else begin
    $display("===========Test completed with %d / 100 failures===========", fail_count);
    end
    $finish;
  end

  initial begin
    #50000;
    $finish;
  end

endmodule
module verified_multi_16bit(
    input clk,          // Chip clock signal.
    input rst_n,        // Active-low reset signal. Defined as 0 for chip reset; defined as 1 for reset signal inactive.
    input start,        // Chip enable signal. 
    input [15:0] ain,   // Input a (multiplicand) with a data width of 16 bits.
    input [15:0] bin,   // Input b (multiplier) with a data width of 16 bits.

    output [31:0] yout, // Product output with a data width of 32 bits.
    output done         // Chip output flag signal. Defined as 1 indicates multiplication operation completion.
);

reg [15:0] areg;    // Multiplicand a register.
reg [15:0] breg;    // Multiplier b register.
reg [31:0] yout_r;  // Product register.
reg done_r;
reg [4:0] i;        // Shift count register.


//------------------------------------------------
// Data bit control
always @(posedge clk or negedge rst_n)
    if (!rst_n) i <= 5'd0;
    else if (start && i < 5'd17) i <= i + 1'b1; 
    else if (!start) i <= 5'd0;

//------------------------------------------------
// Multiplication completion flag generation
always @(posedge clk or negedge rst_n)
    if (!rst_n) done_r <= 1'b0;
    else if (i == 5'd16) done_r <= 1'b1; // Multiplication completion flag
    else if (i == 5'd17) done_r <= 1'b0; // Flag reset

assign done = done_r;

//------------------------------------------------
// Dedicated register for shift and accumulate operation
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin 
        areg <= 16'h0000;
        breg <= 16'h0000;
        yout_r <= 32'h00000000;
    end
    else if (start) begin // Start operation
        if (i == 5'd0) begin // Store multiplicand and multiplier
            areg <= ain;
            breg <= bin;
        end
        else if (i > 5'd0 && i < 5'd17) begin
            if (areg[i-1]) 
            yout_r <= yout_r + ({16'h0000, breg} << (i-1)); // Accumulate and shift
        end
    end
end

assign yout = yout_r;

endmodule
module verified_parallel2serial(
	input wire clk  ,
	input wire rst_n  ,
	input wire [3:0]d ,
	output wire valid_out ,
	output wire dout
	);


reg [3:0] data = 'd0;
reg [1:0]cnt;
reg valid;
assign dout = data[3];
assign valid_out =valid;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        data<= 'd0;
        cnt <= 'd0;
        valid <= 'd0;
    end
    else  begin
                
		if (cnt == 'd3) begin
			data <= d;
			cnt <= 'd0;
			valid <= 1;
		end
		else begin
			cnt <= cnt + 'd1;
			valid <= 0;
			data  <= {data[2:0],data[3]};
		end
    end
		
end


endmodule
module parallel2serial_tb;
  reg clk;
  reg rst_n;
  reg [3:0] d;
  wire valid_out;
  wire dout;

  // Instantiate the DUT (Design Under Test)
  parallel2serial dut (
    .clk(clk),
    .rst_n(rst_n),
    .d(d),
    .valid_out(valid_out),
    .dout(dout)
  );

  // Generate clock
  always #5 clk = ~clk;
  integer error = 0;
  integer failcase = 0;
  integer i = 0;
  initial begin
    for (i=0; i<100; i=i+1) begin
        error = 0;
        // Initialize inputs
        clk = 0;
        rst_n = 0;
        d = 4'b0;

        #10;
        rst_n = 1;
        #10;
        d = $random;
        while (valid_out == 0) begin
            @(posedge clk); // Wait for one clock cycle
        end
        // $display("dout = %b, valid_out = %b", dout, valid_out);
        error = (dout == d[3] && valid_out==1) ? error : error+1;
        #10;
        // $display("dout = %b, valid_out = %b", dout, valid_out);
        error = (dout == d[2] && valid_out==0) ? error : error+1;
        #10;
        // $display("dout = %b, valid_out = %b", dout, valid_out);
        error = (dout == d[1] && valid_out==0) ? error : error+1;
        #10;
        // $display("dout = %b, valid_out = %b", dout, valid_out);
        error = (dout == d[0] && valid_out==0) ? error : error+1;
        #10;
        // $display("dout = %b, valid_out = %b", dout, valid_out);
        error = (valid_out==1) ? error : error+1;
        #10;
        failcase = (error==0)? failcase :failcase+1;

    end
    if(failcase==0) begin
      $display("===========Your Design Passed===========");
    end
    else begin
      $display("===========Test completed with %d /100 failures===========", failcase);
    end
    $finish; 
  end

endmodule
module tb_adder64();

  parameter DATA_WIDTH = 64;
  parameter STG_WIDTH = 16;

  reg CLK;
  reg RST;
  reg i_en;
  wire o_en;
  reg [DATA_WIDTH-1:0] PLUS_A;
  reg [DATA_WIDTH-1:0] PLUS_B;
  wire [DATA_WIDTH:0] SUM_OUT;
  wire [DATA_WIDTH:0] sum_out_golden;
  reg [DATA_WIDTH:0] sum_out_golden_ff1;
  reg [DATA_WIDTH:0] sum_out_golden_ff2;
  reg [DATA_WIDTH:0] sum_out_golden_ff3;
  reg [DATA_WIDTH:0] sum_out_golden_ff4;

  assign {sum_out_golden} = PLUS_A + PLUS_B;

  always #2 CLK = ~CLK;

  integer error = 0;
  initial begin
    CLK = 0;
    repeat (100) begin
      RST = 0;
      i_en = 0;
      #8 RST = 1;
      i_en = 1'b1;
      PLUS_A = $random * $random;
      PLUS_B = $random * $random;
      while(o_en==0) begin
        @(negedge CLK);
      end
        error = ((PLUS_A + PLUS_B) == SUM_OUT && o_en ==1 ) ? error : error + 1;
      @(negedge CLK);
    end

    if (error == 0) begin
      $display("=========== Your Design Passed ===========");
    end
    else begin
      $display("=========== Test completed with %d / 100 failures ===========", error);
    end

    $finish;
  end

  always @(posedge CLK, negedge RST) begin
    if (!RST) begin
      sum_out_golden_ff1 <= 'd0;
      sum_out_golden_ff2 <= 'd0;
      sum_out_golden_ff3 <= 'd0;
      sum_out_golden_ff4 <= 'd0;
    end
    else begin
      sum_out_golden_ff1 <= sum_out_golden;
      sum_out_golden_ff2 <= sum_out_golden_ff1;
      sum_out_golden_ff3 <= sum_out_golden_ff2;
      sum_out_golden_ff4 <= sum_out_golden_ff3;
    end
  end

  adder_pipe_64bit #(
    .DATA_WIDTH(DATA_WIDTH),
    .STG_WIDTH(STG_WIDTH)
  )
  u_pip_add64 (
    .clk (CLK),
    .rst_n (RST),
    .i_en (i_en),
    .adda (PLUS_A),
    .addb (PLUS_B),
    .result (SUM_OUT),
    .o_en (o_en)
  );

endmodule
module verified_RAM (
	input clk,
	input rst_n,
	
	input write_en,
	input [7:0]write_addr,
	input [5:0]write_data,
	
	input read_en,
	input [7:0]read_addr,
	output reg [5:0]read_data
);
    
    //defination
    reg [7 : 0] RAM [11:0];

    //output 
    integer i;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) begin
               for(i = 0; i < 8; i = i + 1) begin
                   RAM[i] <= 'd0;
               end
        end
        else if(write_en) 
            RAM[write_addr] <= write_data;
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) 
            read_data <= 'd0;
        else if(read_en) 
            read_data <= RAM[read_addr];
        else 
            read_data <= 'd0;
    end
endmodule
module tb_RAM;

    // Parameters
    parameter CLK_PERIOD = 10; // Clock period in simulation time units
    
    // Inputs
    reg clk;
    reg rst_n;
    reg write_en;
    reg [7:0] write_addr;
    reg [5:0] write_data;
    reg read_en;
    reg [7:0] read_addr;
    
    // Outputs
    wire [5:0] read_data;

    // Instantiate the module
    RAM uut (
        .clk(clk),
        .rst_n(rst_n),
        .write_en(write_en),
        .write_addr(write_addr),
        .write_data(write_data),
        .read_en(read_en),
        .read_addr(read_addr),
        .read_data(read_data)
    );
    
    // Clock generation
    always #((CLK_PERIOD)/2) clk = ~clk;

    integer error = 0;
    // Initial block for stimulus generation
    initial begin
        // Initialize inputs
        clk = 0;
        rst_n = 1;
        repeat(100) begin
            write_en = 0;
            write_addr = 0;
            write_data = 0;
            read_en = 0;
            read_addr = 0;
            // Wait for a few clock cycles
            #((CLK_PERIOD) * 5);
            // Release reset
            rst_n = 0;
            #((CLK_PERIOD) * 2);
            rst_n = 1;
            // Write operation
            write_en = 1;
            write_addr = 3'b000;
            write_data = $random;
            #((CLK_PERIOD) * 1);
            write_en = 0;
            #((CLK_PERIOD) * 1);
            
            // Read operation
            read_en = 1;
            read_addr = 3'b000;
            #((CLK_PERIOD) * 1);
            // $display("read_data = %b", read_data); 
            error = (read_data == write_data) ? error : error+1;
            read_en = 0;
            #((CLK_PERIOD) * 1);
            // $display("read_data = %b", read_data); 
            error = (read_data == 0) ? error : error+1;
        end
        if (error == 0) begin
            $display("===========Your Design Passed===========");
        end
        else begin
        $display("===========Error===========", error);
        end
        // Finish simulation
        $finish;
    end

endmodule
module tb_multi_pipe();
 
     reg [7:0] mul_a;
     reg [7:0] mul_b;
     reg mul_en_in;
 
     reg clk;
     reg rst_n;
 
     wire mul_en_out;
     wire [15:0] mul_out;

     reg [15:0] expected_product;
 
 multi_pipe_8bit u1(
          .clk(clk),      
          .rst_n(rst_n),       
          .mul_a(mul_a),       
          .mul_b(mul_b),
          .mul_en_in(mul_en_in),       
           
          .mul_en_out(mul_en_out),
          .mul_out(mul_out)    
);
 
 
 
initial clk = 1;
always # 10 clk = ~clk; 
integer error = 0; 
 
initial begin
     rst_n = 0;
     mul_a = 0;
     mul_b = 0;
     mul_en_in = 0;
 
     #(`clk_period*200+1);
 
     rst_n = 1;
     
     #(`clk_period*10);
 
     mul_a = 'd35;
     mul_b = 'd20;
     mul_en_in = 'd1;
     repeat (100) begin
          mul_en_in = 0;
          #(`clk_period*20);
          rst_n = 1;
          #(`clk_period*10);
          mul_a = $random;
          mul_b = $random;

          mul_en_in = 'd1;
          #(`clk_period);
          expected_product = mul_a * mul_b;
          #(`clk_period);
          error = ((mul_en_out==1) && (mul_out == expected_product)) ? error+1 : error;
          while (mul_en_out == 0) begin
                @(posedge clk); // Wait for one clock cycle
          end
          // //========it can be changed depending on your pipelining processing latency
          // #(`clk_period*4);
          // //========it can be changed depending on your pipelining processing latency
          error = (mul_out != expected_product) ? error+1 : error;
          // $display("mul_a = %d, mul_b = %d, mul_out = %d, expected = %d", mul_a, mul_b, mul_out, expected_product);
     end

     if (error == 0) begin
            $display("===========Your Design Passed===========");
     end
     else begin
     $display("===========Test completed with %d /100 failures===========", error);
     end
    
     $finish; 
   
end
 
endmodule
module verified_multi_pipe_8bit#(
    parameter size = 8
)(
          clk,      
          rst_n,       
          mul_a,       
          mul_b, 
          mul_en_in,
 
          mul_en_out,      
          mul_out    
);
 
   input clk;           
   input rst_n; 
   input mul_en_in;      
   input [size-1:0] mul_a;       
   input [size-1:0] mul_b;       
 
   output reg mul_en_out;  
   output reg [size*2-1:0] mul_out;    
 
            
   reg [2:0] mul_en_out_reg;
 always@(posedge clk or negedge rst_n)
       if(!rst_n)begin
            mul_en_out_reg <= 'd0;             
            mul_en_out     <= 'd0;                           
       end
       else begin
            mul_en_out_reg <= {mul_en_out_reg[1:0],mul_en_in};            
            mul_en_out     <= mul_en_out_reg[2];                  
       end
 
 
    reg [7:0] mul_a_reg;
    reg [7:0] mul_b_reg;
  always @(posedge clk or negedge rst_n)
         if(!rst_n) begin
              mul_a_reg <= 'd0;
              mul_a_reg <= 'd0;
         end
         else begin
              mul_a_reg <= mul_en_in ? mul_a :'d0;
              mul_b_reg <= mul_en_in ? mul_b :'d0;
         end
 
  
     wire [15:0] temp [size-1:0];
  assign temp[0] = mul_b_reg[0]? {8'b0,mul_a_reg} : 'd0;
  assign temp[1] = mul_b_reg[1]? {7'b0,mul_a_reg,1'b0} : 'd0;
  assign temp[2] = mul_b_reg[2]? {6'b0,mul_a_reg,2'b0} : 'd0;
  assign temp[3] = mul_b_reg[3]? {5'b0,mul_a_reg,3'b0} : 'd0;
  assign temp[4] = mul_b_reg[4]? {4'b0,mul_a_reg,4'b0} : 'd0;
  assign temp[5] = mul_b_reg[5]? {3'b0,mul_a_reg,5'b0} : 'd0;
  assign temp[6] = mul_b_reg[6]? {2'b0,mul_a_reg,6'b0} : 'd0;
  assign temp[7] = mul_b_reg[7]? {1'b0,mul_a_reg,7'b0} : 'd0; 
 
 
     reg [15:0] sum [3:0];//[size/2-1:1]
 always @(posedge clk or negedge rst_n) 
       if(!rst_n) begin
          sum[0]  <= 'd0;
          sum[1]  <= 'd0;
          sum[2]  <= 'd0;
          sum[3]  <= 'd0;
       end 
       else begin
          sum[0] <= temp[0] + temp[1];
          sum[1] <= temp[2] + temp[3];
          sum[2] <= temp[4] + temp[5];
          sum[3] <= temp[6] + temp[7];
       end
 
     reg [15:0] mul_out_reg;
 always @(posedge clk or negedge rst_n) 
       if(!rst_n)
          mul_out_reg <= 'd0;
       else 
          mul_out_reg <= sum[0] + sum[1] + sum[2] + sum[3];
 
 
 always @(posedge clk or negedge rst_n) 
       if(!rst_n)
          mul_out <= 'd0;
       else if(mul_en_out_reg[2])
          mul_out <= mul_out_reg;
       else
          mul_out <= 'd0;
 
          
endmodule
module tb();
	reg clk,rst_n;
	reg din_serial,din_valid;
	wire dout_valid;
	wire[7:0]dout_parallel;
 
	always #5 clk = ~clk;
  integer error = 0;
	initial begin
		clk  <= 1'b0;
		rst_n <= 1'b0;
		#12
		rst_n <= 1'b1;
		din_valid  <= 1'b1;

		din_serial <= 1'b1; #10;
		din_serial <= 1'b1; #10;
		din_serial <= 1'b1; #10;
		din_serial <= 1'b1; #10;
    error = (dout_valid == 0) ?error:error+1;
		din_serial <= 1'b0; #10;
    din_serial <= 1'b0; #10;
    din_serial <= 1'b0; #10;
    din_serial <= 1'b0; #10;
    while(dout_valid == 0) begin
      #5;
    end
    // $display("%b",dout_parallel);
    error = (dout_parallel == 8'b11110000) ?error:error+1;
    
    din_valid  <= 1'b0; 
		#30;
		din_valid  <= 1'b1;

    din_serial <= 1'b1; #10
    din_serial <= 1'b1; #10
    din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
    error = (dout_valid == 0) ?error:error+1;
		din_serial <= 1'b0; #10
		din_serial <= 1'b0; #10
		din_serial <= 1'b1; #10
		din_serial <= 1'b1; #20
		din_valid  <= 1'b0;
    while(dout_valid == 0) begin
      #5;
    end
    // $display("%b",dout_parallel);
    error = (dout_parallel == 8'b11000011) ?error:error+1;
		#10
    error = (dout_valid == 0) ?error:error+1;
    #10

    if (error == 0) begin
        $display("===========Your Design Passed===========");
    end
    else begin
    $display("===========Error===========");
    end
		$finish;
	end 
	serial2parallel u0(
    .clk           (clk)           ,
    .rst_n          (rst_n)          ,
    .din_serial    (din_serial)    ,
    .dout_parallel (dout_parallel) ,
    .din_valid     (din_valid)     ,
    .dout_valid    (dout_valid)
	);  
endmodule
module verified_serial2parallel(
	input clk,
	input rst_n,
	input din_serial,
	input din_valid,
	output reg [7:0]dout_parallel,
	output reg dout_valid
);

	reg[7:0]din_tmp;
	reg[3:0]cnt;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt <= 0;
		else if(din_valid)
			cnt <= (cnt == 4'd8)?0:cnt+1'b1;
		else	
			cnt <= 0;
	end
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			din_tmp <= 8'b0;
		else if(din_valid && cnt <= 4'd7)
			din_tmp <= {din_tmp[6:0],din_serial};
	
	end 
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			dout_valid <= 1'b0;
			dout_parallel <= 8'b0;
		end
		else if(cnt == 4'd8)begin
			dout_valid <= 1'b1;
			dout_parallel <= din_tmp;
		end
		else begin
			dout_valid <= 1'b0;
		end
	end 
	
endmodule
module test54();

    reg clk;
    reg rst;
    reg [31:0] a,b;
    wire [31:0] c;
    
    pe dut(clk,rst,a,b,c);


    initial begin

    a=0;
    b=0;
    clk=0;
    rst=1;
    #5;
    clk=1;
    #5;
    clk=0;
    rst=0;
    #5;

    a=1;
    b=1;
    #5;
    clk=1;
    #5;
    clk=0;

    a=2;
    b=2;
    #5;
    clk=1;
    #5;
    clk=0;

    a=3;
    b=3;
    #5;
    clk=1;
    #5;
    clk=0;

    //$display("%h", c);

	if(c==32'h0000000e)
	begin
		$display("===========Your Design Passed===========");
        end
	else
	begin
		$display("===========Error===========");
	end
    end
endmodule
module verified_pe(
    input clk,
    input rst,
    input [31:0] a,
    input [31:0] b,

    output [31:0] c
);

reg [31:0] c;

always@(posedge clk or posedge rst)
begin

  if(rst)
  begin
    c <= 0;
  end

  else
  begin
    c <= c + a*b;
  end

end

endmodule
module freq_div (CLK_in,CLK_50,CLK_10,CLK_1,RST);
input CLK_in,RST;
output reg CLK_50,CLK_10,CLK_1;

reg [3:0] cnt_10;
reg [6:0] cnt_100;

always @(posedge CLK_in or posedge RST) begin
	if (RST) begin
		CLK_50<= 1'b0;
        end
	else begin
		CLK_50<= ~CLK_50;
        end
end

always @(posedge CLK_in or posedge RST) begin
	if (RST) begin
		CLK_10<= 1'b0;
                cnt_10<=0;
        end
	else if (cnt_10==4) begin
		CLK_10<= ~CLK_10;
                cnt_10<=0;
        end
        else begin
                cnt_10<=cnt_10+1;
        end
end

always @(posedge CLK_in or posedge RST) begin
	if (RST) begin
		CLK_1<= 1'b0;
                cnt_100<=0;
        end
	else if (cnt_100==49) begin
		CLK_1<= ~CLK_1;
                cnt_100<=0;
        end
        else begin
                cnt_100<=cnt_100+1;
        end
end

endmodule
module test ();

reg  clk,rst;

wire out1;
wire out2;
wire out3;

freq_div dut(.CLK_in(clk),.RST(rst),.CLK_50(out1),.CLK_10(out2),.CLK_1(out3));

initial begin
	clk = 0;
	forever #5 clk = ~clk;
end

integer error=0;

initial begin 
	#10;
	rst = 1;
	#35;
	rst = 0;
	// 45, clk: 1, clk50: 0, rclk10: 0, clk1: 0
	error = (out1 != 0 || out2 != 0 || out3 !=0 ) ? error+1 : error;
	// 55, clk: 1, clk50: 1, rclk10: 0, clk1: 0
	#10;
	error = (out1 != 1 || out2 != 0 || out3 !=0 ) ? error+1 : error;
	// 95, clk50: 0, rclk10: 1, clk1: 0
	#40;
	error = (out1 != 1 || out2 != 1 || out3 !=0 ) ? error+1 : error;
	// 225, clk: 1, clk50: 0, rclk10: 1, clk1: 0
	#130;
	error = (out1 != 0 || out2 != 1 || out3 !=0 ) ? error+1 : error;
	// 625, clk: 1, clk50: 0, rclk10: 1, clk1: 1
	#400;
	error = (out1 != 0 || out2 != 1 || out3 !=1 ) ? error+1 : error;
	// 1035, clk: 1, clk50: 1, rclk10: 1, clk1: 1
	#410;
	error = (out1 != 1 || out2 != 1 || out3 !=1 ) ? error+1 : error;
	if (error == 0) begin
            $display("===========Your Design Passed===========");
        end
        else begin
        $display("===========Error===========", error);
        end
	$finish;
end

// initial begin 
// 	repeat(500) begin
// 		#5
// 		$display("Time: %t, clk: %b, clk50: %b, rclk10: %b, clk1: %b", $time, clk, out1, out2, out3);
// 	end
// end

endmodule
module verified_width_8to16(
	input 				   clk 		,   
	input 				   rst_n		,
	input				      valid_in	,
	input	   [7:0]		   data_in	,
 
 	output	reg			valid_out,
	output   reg [15:0]	data_out
);
reg 	[7:0]		data_lock;  //data buffer
reg 				flag	   ;
//input data buff in data_lock
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_lock <= 'd0;
	else if(valid_in && !flag)
		data_lock <= data_in;
end
//generate flag
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		flag <= 'd0;
	else if(valid_in)
		flag <= ~flag;
end
//generate valid_out
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		valid_out <= 'd0;
	else if(valid_in && flag)
		valid_out <= 1'd1;
	else
		valid_out <= 'd0;
end
//data stitching 
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_out <= 'd0;
	else if(valid_in && flag)
		data_out <= {data_lock, data_in};
end

endmodule
module testbench();
    reg rst,valid_in;
	reg clk=1;
	reg[7:0] data_in;
	wire valid_out;
	wire [15:0] data_out;

width_8to16 dut(
	.clk (clk),   
	.rst_n(rst),
	.valid_in(valid_in),
	.data_in(data_in),
	.valid_out(valid_out),
	.data_out(data_out)
);
	always #5 clk = ~clk;  

integer error = 0;
initial 
begin
	rst=0;valid_in=0;
 	#10 rst=1;valid_in=1;data_in=8'b10100000;
	// $display("data_out = %b", data_out);
	// $display("valid_out = %b", valid_out);
	error = valid_out ==0 ? error : error+1; 
	#10 data_in=8'b10100001; 
	// $display("data_out = %b", data_out); 
	#10 data_in=8'b10110000;
	// $display("data_out = %b", data_out); 
	// $display("valid_out = %b", valid_out);
	error = (data_out == 16'b1010000010100001 && valid_out ==1 )? error : error+1;
	#10 valid_in=0;
	#20 valid_in=1;data_in=8'b10110001; 
	#10 valid_in=0;
	// $display("data_out = %b", data_out); 
	// $display("valid_out = %b", valid_out);
	error = (data_out == 16'b1011000010110001 && valid_out ==1 )? error : error+1;
	#30

	if (error == 0) begin
		$display("===========Your Design Passed===========");
	end
	else begin
	$display("===========Test completed with %d / 3 failures===========", error);
	end

	$finish;
end  

endmodule
module verified_calendar(CLK,RST,Hours,Mins,Secs);
input CLK,RST;
output [5:0] Hours,Mins,Secs;
reg [5:0] Hours,Mins,Secs;

always@(posedge CLK or posedge RST) begin
	if (RST)
		Secs <= 0;
	else if (Secs == 59)
		Secs <= 0;
	else
		Secs <= Secs + 1;
end

always@(posedge CLK or posedge RST) begin
	if (RST)
		Mins <= 0;
	else if((Mins==59)&&(Secs==59))
		Mins <= 0;
	else if(Secs== 59)
		Mins <= Mins + 1;
	else
		Mins <= Mins;
end

always@(posedge CLK or posedge RST) begin
        if (RST)
                Hours <= 0;
        else if((Hours == 23)&&(Mins==59)&&(Secs==59))
                Hours <= 0;
        else if((Mins == 59)&&(Secs==59))
                Hours <= Hours + 1;
        else
                Hours <= Hours;
end

endmodule
module main();
reg clk,rst;

wire[5:0] out1,out2,out3;

calendar dut(.CLK(clk),.RST(rst),.Hours(out1),.Mins(out2),.Secs(out3));

initial begin
	clk=0;
	forever #5 clk=~clk;
end

integer outfile;
reg [17:0] clocktime;
always @(posedge clk) begin
    clocktime[17:12] <= out1;
    clocktime[11:6] <= out2;
    clocktime[5:0] <= out3;
end

reg [17:0] reference_data [0:4000];
integer i=0;
integer error = 0;
initial begin
	#10;
	rst = 1;
	#25;
	rst = 0;
	// outfile = $fopen("reference.txt", "w");
	$readmemh("reference.txt",reference_data);
	repeat(4000) begin	
		// $fwrite(outfile, "%h\n", clocktime);
		error = (reference_data[i] == clocktime) ? error :error +1;
		i = i + 1;

		#10;
	end
	if(error==0)
	begin
		$display("===========Your Design Passed===========");
        end
	else
	begin
		$display("===========Error===========");
	end
	// $fclose(outfile);
	$finish;
end

endmodule
module dual_port_RAM #(parameter DEPTH = 16,  parameter WIDTH = 8)
(
	 input wclk	,
	 input wenc	,
	 input [$clog2(DEPTH)-1:0] waddr  ,
	 input [WIDTH-1:0] wdata ,
	 input rclk	,
	 input renc	,
	 input [$clog2(DEPTH)-1:0] raddr ,
	 output reg [WIDTH-1:0] rdata 		
);

reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];

always @(posedge wclk) begin
	if(wenc)
		RAM_MEM[waddr] <= wdata;
end 

always @(posedge rclk) begin
	if(renc)
		rdata <= RAM_MEM[raddr];
end 

endmodule
module verified_asyn_fifo#(
	parameter	WIDTH = 8,
	parameter 	DEPTH = 16
)(
	input 					wclk	, 
	input 					rclk	,   
	input 					wrstn	,
	input					rrstn	,
	input 					winc	,
	input 			 		rinc	,
	input 		[WIDTH-1:0]	wdata	,

	output wire				wfull	,
	output wire				rempty	,
	output wire [WIDTH-1:0]	rdata
);

parameter ADDR_WIDTH = $clog2(DEPTH);


reg 	[ADDR_WIDTH:0]	waddr_bin;
reg 	[ADDR_WIDTH:0]	raddr_bin;

always @(posedge wclk or negedge wrstn) begin
	if(~wrstn) begin
		waddr_bin <= 'd0;
	end 
	else if(!wfull && winc)begin
		waddr_bin <= waddr_bin + 1'd1;
	end
end
always @(posedge rclk or negedge rrstn) begin
	if(~rrstn) begin
		raddr_bin <= 'd0;
	end 
	else if(!rempty && rinc)begin
		raddr_bin <= raddr_bin + 1'd1;
	end
end

wire 	[ADDR_WIDTH:0]	waddr_gray;
wire 	[ADDR_WIDTH:0]	raddr_gray;
reg 	[ADDR_WIDTH:0]	wptr;
reg 	[ADDR_WIDTH:0]	rptr;
assign waddr_gray = waddr_bin ^ (waddr_bin>>1);
assign raddr_gray = raddr_bin ^ (raddr_bin>>1);
always @(posedge wclk or negedge wrstn) begin 
	if(~wrstn) begin
		wptr <= 'd0;
	end 
	else begin
		wptr <= waddr_gray;
	end
end
always @(posedge rclk or negedge rrstn) begin 
	if(~rrstn) begin
		rptr <= 'd0;
	end 
	else begin
		rptr <= raddr_gray;
	end
end

reg		[ADDR_WIDTH:0]	wptr_buff;
reg		[ADDR_WIDTH:0]	wptr_syn;
reg		[ADDR_WIDTH:0]	rptr_buff;
reg		[ADDR_WIDTH:0]	rptr_syn;
always @(posedge wclk or negedge wrstn) begin 
	if(~wrstn) begin
		rptr_buff <= 'd0;
		rptr_syn <= 'd0;
	end 
	else begin
		rptr_buff <= rptr;
		rptr_syn <= rptr_buff;
	end
end
always @(posedge rclk or negedge rrstn) begin 
	if(~rrstn) begin
		wptr_buff <= 'd0;
		wptr_syn <= 'd0;
	end 
	else begin
		wptr_buff <= wptr;
		wptr_syn <= wptr_buff;
	end
end

assign wfull = (wptr == {~rptr_syn[ADDR_WIDTH:ADDR_WIDTH-1],rptr_syn[ADDR_WIDTH-2:0]});
assign rempty = (rptr == wptr_syn);

/***********RAM*********/
wire 	wen	;
wire	ren	;
wire 	wren;//high write
wire [ADDR_WIDTH-1:0]	waddr;
wire [ADDR_WIDTH-1:0]	raddr;
assign wen = winc & !wfull;
assign ren = rinc & !rempty;
assign waddr = waddr_bin[ADDR_WIDTH-1:0];
assign raddr = raddr_bin[ADDR_WIDTH-1:0];

dual_port_RAM #(.DEPTH(DEPTH),
				.WIDTH(WIDTH)
)dual_port_RAM(
	.wclk (wclk),  
	.wenc (wen),  
	.waddr(waddr[ADDR_WIDTH-1:0]),  //The depth is logarithmic to 2 to get the bit width of the address
	.wdata(wdata),       	//data_write
	.rclk (rclk), 
	.renc (ren), 
	.raddr(raddr[ADDR_WIDTH-1:0]),   
	.rdata(rdata)  		
);

endmodule
module pulse_detect_tb;
  reg clk;
  reg rst_n;
  reg data_in;
  wire data_out;

  // Instantiate the DUT (Design Under Test)
  pulse_detect dut (
    .clk(clk),
    .rst_n(rst_n),
    .data_in(data_in),
    .data_out(data_out)
  );

  // Generate clock
  initial begin
	clk=0;
	forever #5 clk=~clk;
  end

  integer error = 0;
  initial begin
      // Initialize inputs
      #10;
      rst_n = 0;
      data_in = 0;
      #28;
      rst_n = 1;
      #10      data_in = 0;
      #10      data_in = 0;  
      #10      data_in = 0;
      #10      data_in = 1;
      #10      data_in = 0;
      #10      data_in = 1;
      #10      data_in = 0;
      #10      data_in = 1;
      #10      data_in = 1;
      #10      data_in = 0;
      #10;
      // Finish simulation
      $finish;
  end

  initial begin
    #5;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 0) ? error : error+1;
    #10;
    error = (data_out == 1) ? error : error+1;
    // $display("%b,%b,%b", data_in, data_out, dut.pulse_level1);//1
    #20;
    error = (data_out == 1) ? error : error+1;
    #10;
    if (error == 0) begin
        $display("===========Your Design Passed===========");
    end
    else begin
    $display("===========Error===========");
    end
  end
endmodule
module verified_pulse_detect(    
    input clk,
    input rst_n,
    input data_in,
    output reg data_out
);

parameter s0 = 2'b00; // initial
parameter s1 = 2'b01; // 0, 00
parameter s2 = 2'b10; // 01
parameter s3 = 2'b11; // 010

reg [1:0] pulse_level1, pulse_level2;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        pulse_level1 <= s0;
    else
        pulse_level1 <= pulse_level2;
end

always @(*) begin
    case (pulse_level1)
        s0: begin
            if (data_in == 0)
                pulse_level2 = s1;
            else
                pulse_level2 = s0;
        end

        s1: begin
            if (data_in == 1)
                pulse_level2 = s2;
            else
                pulse_level2 = s1;
        end

        s2: begin
            if (data_in == 0)
                pulse_level2 = s3;
            else
                pulse_level2 = s0;
        end

        s3: begin
            if (data_in == 1)
                pulse_level2 = s2;
            else
                pulse_level2 = s1;
        end
    endcase
end

// always @(posedge clk or negedge rst_n) begin
//     if (~rst_n)
//         data_out <= 0;
//     else if (pulse_level1 == s2 && data_in == 0)
//         begin
//         data_out <= 1;
//         end
//     else
//         data_out <= 0;
// end

always @(*) begin
    if (~rst_n)
        data_out = 0;
    else if (pulse_level1 == s2 && data_in == 0)
        data_out = 1;
    else
        data_out = 0;
end

endmodule
module verified_fsm(IN,MATCH,CLK,RST);
input IN,CLK,RST;
output reg MATCH;

reg [2:0] ST_cr,ST_nt;

parameter s0 = 3'b000;
parameter s1 = 3'b001;
parameter s2 = 3'b010;
parameter s3 = 3'b011;
parameter s4 = 3'b100;
parameter s5 = 3'b101;

always@(posedge CLK or posedge RST) begin
	if(RST)
		ST_cr <= s0;
	else
		ST_cr <= ST_nt;
end

always@(*) begin
	case(ST_cr)
		s0:begin
			if (IN==0)
				ST_nt = s0;
			else
				ST_nt = s1;
		end
		
		s1:begin
                        if (IN==0)
                                ST_nt = s2;
                        else
                                ST_nt = s1;
                end

                s2:begin
                        if (IN==0)
                                ST_nt = s3;
                        else
                                ST_nt = s1;
                end

                s3:begin
                        if (IN==0)
                                ST_nt = s0;
                        else
                                ST_nt = s4;
                end

                s4:begin
                        if (IN==0)
                                ST_nt = s2;
                        else
                                ST_nt = s5;
                end

                s5:begin
                        if (IN==0)
                                ST_nt = s2;
                        else
                                ST_nt = s1;
                end

	endcase
end

always@(*) begin
        if(RST)
                MATCH  <= 0;
        else if (ST_cr == s4 && IN == 1)
                MATCH  <= 1;
	else 
		MATCH  <= 0;
end

endmodule
module main();

reg clk,rst;
reg IN;
wire MATCH;

fsm DUT(.CLK(clk),.RST(rst),.IN(IN),.MATCH(MATCH));

initial begin
	clk=0;
	forever #5 clk=~clk;
end

integer error = 0;
initial begin
	#10;
	rst =1;
	#28;
	rst = 0;
	IN = 0;
	#10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//0
        error = (MATCH==0)? error:error+1;
        #10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//00
        error = (MATCH==0)? error:error+1;
        #10 IN=1;
        // $display("%b, %b", MATCH, DUT.ST_cr);//001
        error = (MATCH==0)? error:error+1;
        #10 IN=1;  
        // $display("%b, %b", MATCH, DUT.ST_cr);//0011
        error = (MATCH==0)? error:error+1;
        #10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//00110
        error = (MATCH==0)? error:error+1;
        #10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//001100
        error = (MATCH==0)? error:error+1;
        #10 IN=1;
        // $display("%b, %b", MATCH, DUT.ST_cr);//0011001
        error = (MATCH==0)? error:error+1;
        #10 IN=1;
        // $display("%b, %b", MATCH, DUT.ST_cr);//00110011
        error = (MATCH==1)? error:error+1;
        #10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//001100110
        error = (MATCH==0)? error:error+1;
        #10 IN=0;
        // $display("%b, %b", MATCH, DUT.ST_cr);//0011001100
        error = (MATCH==0)? error:error+1;
        #10 IN=1;
        // $display("%b, %b", MATCH, DUT.ST_cr);//00110011001
        error = (MATCH==0)? error:error+1;
        #10 IN=1;
        // $display("%b, %b", MATCH, DUT.ST_cr);//001100110011
        error = (MATCH==1)? error:error+1;
        if(error==0)begin
                $display("===========Your Design Passed===========");
        end
        else begin
                $display("===========Error===========");
        end
	$finish;
end
endmodule
module verified_accu(
    input               clk         ,   
    input               rst_n       ,
    input       [7:0]   data_in     ,
    input               valid_in     ,
 
    output  reg         valid_out     ,
    output  reg [9:0]   data_out
);
    
   reg [1:0] count;
   wire add_cnt;
   wire ready_add;
   wire end_cnt;
   reg [9:0]   data_out_reg;

   assign add_cnt = ready_add;
   assign end_cnt = ready_add && (count == 'd3);
   
   //count
   always @(posedge clk or negedge rst_n) begin
       if(!rst_n) begin
          count <= 0;
       end
       else if(end_cnt) begin
          count <= 0;
       end
       else if(add_cnt) begin
          count <= count + 1;
       end
   end

    //data_out_reg
   always @(posedge clk or negedge rst_n) begin
      if(!rst_n) begin
        data_out_reg <= 0;
      end
      else if (add_cnt && count == 0) begin
          data_out_reg <= data_in;
      end
      else if (add_cnt) begin
          data_out_reg <= data_out_reg + data_in;
      end
   end

    //data_out
   always @(posedge clk or negedge rst_n) begin
      if(!rst_n) begin
        data_out <= 0;
      end
      else if (add_cnt && count == 0) begin
          data_out <= data_in;
      end
      else if (add_cnt) begin
          data_out <= data_out + data_in;
      end
   end

   //ready_add
   assign ready_add = !valid_out | valid_in;

   //valid_out
   always @(posedge clk or negedge rst_n) begin
       if(!rst_n) begin
           valid_out <= 0;
       end
       else if(end_cnt) begin
           valid_out <= 1;
       end
       else begin
           valid_out <= 0;
       end
   end  
     
endmodule
module tb_valid_ready;


parameter PERIOD  = 10;
reg   clk                                  = 0 ;
reg   rst_n                                = 0 ;
reg   [7:0]  data_in                       = 0 ;
reg   valid_in                             = 0 ;

wire  valid_out                              ;
wire  [9:0]  data_out                       ;


initial
begin
    forever #(PERIOD/2)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
end

accu  uut (
    .clk                     ( clk             ),
    .rst_n                   ( rst_n           ),
    .data_in                 ( data_in   [7:0] ),
    .valid_in                ( valid_in        ),

    .valid_out               ( valid_out       ),
    .data_out                ( data_out  [9:0] )
);

initial
begin
    #(PERIOD*1+0.01); 
    #(PERIOD)   data_in = 8'd1;valid_in = 1;
    #(PERIOD)   data_in = 8'd2;
    #(PERIOD)   data_in = 8'd3;
    #(PERIOD)   data_in = 8'd14;

    #(PERIOD)   data_in = 8'd5;
    #(PERIOD)   data_in = 8'd2;
    #(PERIOD)   data_in = 8'd103;
    #(PERIOD)   data_in = 8'd4;

    #(PERIOD)   data_in = 8'd5;
    #(PERIOD)   data_in = 8'd6;
    #(PERIOD)   data_in = 8'd3;
    #(PERIOD)   data_in = 8'd54;
    #(PERIOD*2);
    $finish;
end

reg [9:0] result [0:2];
initial begin
    result[0] = 9'd20;
    result[1] = 9'd114;
    result[2] = 9'd68;
end

integer i;
integer casenum = 0;
integer error = 0;

initial
begin
    for (i = 0; i < 15; i = i + 1) begin
        #((PERIOD) * 1);         
        if (valid_out) begin
            error = (data_out == result[casenum]) ? error : error + 1;
            casenum = casenum + 1;
        end        
    end
    if(error==0 && casenum==3)
	begin
		$display("===========Your Design Passed===========");
        end
	else
	begin
		$display("===========Error===========");
	end
    $finish;
end


endmodule
module verified_counter_12 
(
  input rst_n,
  input clk,
  input valid_count,

  output reg [3:0] out
);

  always @(posedge clk or negedge rst_n) begin
    if (!rst_n) 
	begin
      out <= 4'b0000;
    end 

	else if (valid_count) 
	begin
      if (out == 4'd11) 
	  begin
        out <= 4'b0000;
      end 
	  else begin
        out <= out + 1;
      end
    end 
	
	else begin
      out <= out; // Pause the count when valid_count is invalid
    end
  end

endmodule
module counter_12_tb;

  reg clk, rst_n, valid_count;
  wire [3:0] out;

  counter_12 dut (
    .rst_n(rst_n),
    .clk(clk),
    .valid_count(valid_count),
    .out(out)
  );


  always #5 clk = ~clk;
  integer i = 0;
  integer error = 0;
  initial begin
    clk = 0;
    rst_n = 0;
    valid_count = 0;

    #20 rst_n = 1;
    // testcase1: validation of valid_count
    repeat(15) begin	
      error = (out == 0) ?error:error+1;
      #10;
    end
    // testcase2: counter
    #100 valid_count = 1;
    repeat(11) begin	
      error = (out == i) ?error:error+1;
      i = i+1;
      #10;
    end
    // testcase3: the count is paused if valid_count is invalid
    valid_count = 0;
    repeat(5) begin	
      error = (out == 11) ?error:error+1;
      #10;
    end

    if (error == 0) begin
              $display("===========Your Design Passed===========");
          end
          else begin
          $display("===========Failed===========", error);
          end
    $finish;
  end


endmodule
module verified_signal_generator(
  input clk,
  input rst_n,
  output reg [4:0] wave
);

  reg [1:0] state;
  
  always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      state <= 2'b0;
      wave <= 5'b0;
    end
    else begin
      case (state)
        2'b00:
          begin
            if (wave == 5'b11111)
              state <= 2'b01;
            else
              wave <= wave + 1;
          end
          
        2'b01:
          begin
            if (wave == 5'b00000)
              state <= 2'b00;
            else
              wave <= wave - 1;
          end
      endcase
    end
  end

endmodule
module tb_signal_generator;
reg				clk,rst_n;
wire[4:0]		wave;

signal_generator uut(
				.clk(clk),
				.rst_n(rst_n),
				.wave(wave)
				);

reg[31:0]reference[0:99];

integer i = 0;
integer error = 0;
// integer outfile;
initial begin
      $readmemh("tri_gen.txt",reference);
			clk = 0;
      rst_n = 0;
			#10
      rst_n =1;
      // outfile = $fopen("tri_gen.txt", "w");
			repeat(100) begin
        // $fwrite(outfile, "%h\n", wave);
        // $display(wave);
        error=(wave==reference[i])?error:error+1;
        #10;
        i = i+1;
      end
      // $fclose(outfile);
      if(error==0)
      begin
        $display("===========Your Design Passed===========");
            end
      else
      begin
        $display("===========Error===========");
      end
      $finish;
end
 
always #5 clk =~clk;
 
endmodule
module verified_JC_counter(
   input                clk ,
   input                rst_n,
 
   output reg [63:0]     Q  
);
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n) Q <= 'd0;
        else if(!Q[0]) Q <= {1'b1, Q[63 : 1]};
        else Q <= {1'b0, Q[63 : 1]};
    end
endmodule
module testbench;

    // Parameters
    parameter CLK_PERIOD = 10; // Clock period in simulation time units
    
    // Inputs
    reg clk;
    reg rst_n;
    
    // Outputs
    wire [63:0] Q;

    // Instantiate the module
    JC_counter uut (
        .clk(clk),
        .rst_n(rst_n),
        .Q(Q)
    );
    
    // Clock generation
    always #((CLK_PERIOD)/2) clk = ~clk;
    
    integer error=0;
    // Initial block for stimulus generation
    initial begin
        // Initialize inputs
        clk = 0;
        rst_n = 1;
        
        // Wait for a few clock cycles
        #((CLK_PERIOD) * 2);
        
        // Release reset
        rst_n = 0;
        #((CLK_PERIOD) * 2);
        rst_n = 1;
        
        // Simulate for a number of clock cycles
        #((CLK_PERIOD) * 20);
        error = (Q ==64'b 1111111111111111111100000000000000000000000000000000000000000000)? error : error+1;
        #((CLK_PERIOD) * 44);
        error = (Q ==64'b 1111111111111111111111111111111111111111111111111111111111111111)? error : error+1;
        #((CLK_PERIOD) * 1);
        error = (Q ==64'b 0111111111111111111111111111111111111111111111111111111111111111)? error : error+1;
        #((CLK_PERIOD) * 62);
        error = (Q ==64'b 0000000000000000000000000000000000000000000000000000000000000001)? error : error+1;

        if (error == 0) begin
            $display("===========Your Design Passed===========");
        end
        else begin
        $display("===========Error===========");
        end
        // $display("Q = %b", Q); 
        
        // Finish simulation
        $finish;
    end

endmodule
module verified_div_16bit(
    input wire [15:0] A,
    input wire [7:0] B,
    output wire [15:0] result,
    output wire [15:0] odd
    );

reg [15:0] a_reg;
reg [15:0] b_reg;
reg [31:0] tmp_a;
reg [31:0] tmp_b;
integer i;

always@(*) begin
    a_reg = A;
    b_reg = B;
end

always@(*) begin
    begin
        tmp_a = {16'b0, a_reg};
        tmp_b = {b_reg, 16'b0};
        for(i = 0;i < 16;i = i+1) begin
            tmp_a = tmp_a << 1;
            if (tmp_a >= tmp_b) begin
                tmp_a = tmp_a - tmp_b + 1;
            end
            else begin
                tmp_a = tmp_a;
            end
        end
    end
end

assign odd = tmp_a[31:16];
assign result = tmp_a[15:0];

endmodule
module multi_pipe_tb;
  reg clk;
  reg rst_n;
  reg [3:0] mul_a;
  reg [3:0] mul_b;
  wire [7:0] mul_out;
  wire signed [7:0] perfect = mul_a*mul_b;
  // Instantiate the DUT (Design Under Test)
  multi_pipe_4bit #(.size(4)) dut (
    .clk(clk),
    .rst_n(rst_n),
    .mul_a(mul_a),
    .mul_b(mul_b),
    .mul_out(mul_out)
  );

  // Generate clock
  always #5 clk = ~clk;

  integer fail_count =0;
  integer i=0;
  initial begin
    // Initialize inputs
    clk = 0;
    rst_n = 0;
    mul_a = 4'b0;
    mul_b = 4'b0;

    // Wait for a few clock cycles for reset to settle
    #10;

    // Apply reset
    rst_n = 1;
  
    // Perform test case
    for (i = 0; i < 100; i = i + 1) begin
      mul_a =  $random;
      mul_b =  $random;
      #10;
      // without pipeline
      fail_count = (perfect == mul_out)? fail_count+1:fail_count;
      #20;
      // $display("%d, %d, %d, %d", mul_a, mul_b, perfect, mul_out);
      fail_count = (perfect == mul_out)? fail_count:fail_count+1;
    end

    if (fail_count == 0) begin
        $display("===========Your Design Passed===========");
    end
    else begin
    $display("===========Test completed with %d / 100 failures===========", fail_count);
    end
    $finish;
  end
endmodule
module verified_multi_pipe#(
	parameter size = 4
)(
	input 						clk 		,   
	input 						rst_n		,
	input	[size-1:0]			mul_a		,
	input	[size-1:0]			mul_b		,
 
 	output	reg	[size*2-1:0]	mul_out		
);

parameter N = 2 * size;

reg     [N-1:0]     sum_tmp1                ;
reg     [N-1:0]     sum_tmp2                ;
wire    [N-1:0]     mul_a_extend            ;
wire    [N-1:0]     mul_b_extend            ;

wire    [N-1:0]     mul_result[size-1:0]    ;

genvar i;
generate
    for(i = 0; i < size; i = i + 1) begin:add
        assign mul_result[i] = mul_b[i] ? mul_a_extend << i : 'd0;
    end
endgenerate

assign mul_a_extend = {{size{1'b0}}, mul_a};
assign mul_b_extend = {{size{1'b0}}, mul_b};

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        sum_tmp1 <= 'd0;
        sum_tmp2 <= 'd0;
    end
    else begin
        sum_tmp1 <= mul_result[0] + mul_result[1];
        sum_tmp2 <= mul_result[2] + mul_result[3];
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        mul_out <= 'd0;
    end
    else begin
        mul_out <= sum_tmp1 + sum_tmp2;
    end
end

endmodule
module verified_multi_booth_8bit (p, rdy, clk, reset, a, b);
   input clk, reset;
   input [7:0] a, b;
   output [15:0] p;
   output rdy;
   
   reg [15:0] p;
   reg [15:0] multiplier;
   reg [15:0] multiplicand;
   reg rdy;
   reg [4:0] ctr;

always @(posedge clk or posedge reset) begin
    if (reset) 
    begin
    rdy     <= 0;
    p   <= 0;
    ctr     <= 0;
    multiplier <= {{8{a[7]}}, a};
    multiplicand <= {{8{b[7]}}, b};
    end 
    else 
    begin 
      if(ctr < 16) 
          begin
          multiplicand <= multiplicand << 1;
            if (multiplier[ctr] == 1)
            begin
                p <= p + multiplicand;
            end
            ctr <= ctr + 1;
          end
       else 
           begin
           rdy <= 1;
           end
    end
  end //End of always block
    
endmodule