dakies/OSS_Verilog huggingface dataset:
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
  reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 0;
    EW_VEHICLE_DETECT = 1;

    $display("                         NS | EW ");
    $display("              (Time) | R Y G R Y G ");
    $monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    #1 clk = ~clk;
  end

  always @ (clk) begin
    if ($time % 15 == 0) begin
      NS_VEHICLE_DETECT = ~NS_VEHICLE_DETECT;
    end
    
    if ($time % 2 == 0) begin
      EW_VEHICLE_DETECT = ~EW_VEHICLE_DETECT;
    end
  end
endmodule
module Traffic_Test;

	// Inputs
	reg NS_VEHICLE_DETECT;
	reg EW_VEHICLE_DETECT;

	// Outputs
	wire NS_RED;
	wire NS_YELLOW;
	wire NS_GREEN;
	wire EW_RED;
	wire EW_YELLOW;
	wire EW_GREEN;

	// Clock
	reg clk;

	// Counters
	wire[4:0] count1;
	wire[3:0] count2;
	wire[1:0] count3;

	// Counter Modules
	nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
	ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
	yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

	// Main Traffic Module
	Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

	initial begin

		clk = 0;
		NS_VEHICLE_DETECT = 0;
		EW_VEHICLE_DETECT = 1;

		$display("                         NS | EW ");
		$display("              (Time) | R Y G R Y G ");
		$monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

		#1000 $finish;
	end

	always begin
		#1 clk = ~clk;
	end

	always @ (clk) begin
		if ($time % 21 == 0) begin
			NS_VEHICLE_DETECT = ~NS_VEHICLE_DETECT;
			EW_VEHICLE_DETECT = ~EW_VEHICLE_DETECT;
		end
	end
endmodule
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
	reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 0;
    EW_VEHICLE_DETECT = 1;

    $display("                         NS | EW ");
    $display("              (Time) | R Y G R Y G ");
    $monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    	#1 clk = ~clk;
  end

  always @ (clk) begin
    if ($time % 15 == 0) begin
      NS_VEHICLE_DETECT = ~NS_VEHICLE_DETECT;
    end

    if ($time % 6 == 0) begin
      EW_VEHICLE_DETECT = ~EW_VEHICLE_DETECT;
    end
  end 
endmodule
module half_adder
(
  input iA,
  input iB,
  output oSUM,
  output oCARRY
);

  // This uses an exclusive OR gate to find the SUM of two inputs
  assign oSUM = iA ^ iB;

  // This uses an AND gate to find the CARRY of two inputs
  assign oCARRY = iA & iB;
endmodule
module half_adder_test;

  // Input Registers:
  reg iA;
  reg iB;

  // Output Registers:
  wire oSUM;
  wire oCARRY;

  // Instantiate the Unit Under Test (UUT)
  half_adder uut
  (
    .iA(iA),
    .iB(iB),
    .oSUM(oSUM),
    .oCARRY(oCARRY)
  );

  // The code below tests the half-adder by manually changing the values of each input register
  initial begin

    // Set the both input registers as 0 as a default
    iA = 0;
    iB = 0;

    // For five seconds, set one register to 1 while leaving the other as its default 0
    #5 iA = 0; iB = 1;

    // For five seconds, set the other register to 1 while flipping the other to its default 0
    #5 iA = 1; iB = 0;

    // For five seconds, set both registers to 1
    #5 iA = 1; iB = 1;
  end

  initial #25 $finish; // The test should run for a total of 25 nanoseconds
endmodule
module four_bit_adder_EC_test;

  // Inputs
  reg [3:0] A;
  reg [3:0] B;

  // Outputs
  wire [4:0] SUM;

  // Instantiate a counter variable for the loop
  integer count;

  // Instantiate the Unit Under Test (UUT)
  four_bit_adder_EC uut
  (
    .A(A),
    .B(B),
    .SUM(SUM)
  );

  initial begin

    // Initialize Inputs
    A = 0;
    B = 0;
    count = 0;
  end

  //Whenever the value of either A or B changes, iterate the possible combinations
  always @(A or B) begin

    // Loops over the possible combinations for A and B
    for (count = 0; count < 256; count = count + 1)
    #1 {A, B} = count;
    #2 $stop;
  end
endmodule
module four_bit_adder_EC
(
  input [3:0] A,
  input [3:0] B,
  output [4:0] SUM
);

  assign SUM[0] = A[0] ^ B[0];
  assign SUM[1] = A[1] ^ B[1] ^ (A[0] & B[0]);
  assign SUM[2] = A[2] ^ B[2] ^ ((A[1] & B[1]) | ((A[0] & B[0]) & (A[1] ^ B[1])));
  assign SUM[3] = A[3] ^ B[3] ^ ((A[2] & B[2]) | ((A[1] & B[1]) & (A[2] ^ B[2])) | ((A[0] & B[0]) & (A[1] ^ B[1]) & (A[2] ^ B[2])));
  assign SUM[4] = ((A[3] & B[3]) | (A[2] & B[2]) & (A[3] ^ B[3])) | ((A[1] & B[1]) & (A[2] ^ B[2]) & (A[3] ^ B[3])) | ((A[0] & B[0]) & (A[1] ^ B[1]) & (A[2] ^ B[2]) & (A[3] ^ B[3]));
endmodule
module three_bit_comparator_test;

  // Inputs
  reg [2:0] A;
  reg [2:0] B;

  // Outputs
  wire GT;
  wire LT;
  wire EQ;

  // Instantiate two counter variables for both loop
  integer count;

  // Instantiate the Unit Under Test (UUT)
  three_bit_comparator uut
  (
    .A(A),
    .B(B),
    .GT(GT),
    .LT(LT),
    .EQ(EQ)
  );

  initial begin

    // Initialize Inputs
    A = 0;
    B = 0;

    // Initialize counter variables
    count = 0;
  end

  // Whenever the value of either A or B changes, iterate the possible combinations
  always @(A or B) begin

    // Loops over the possible combinations for A and B
    for (count = 0; count < 64; count = count + 1)
      #1 {A, B} = count;
      #5 $stop;
    end
endmodule
module three_bit_comparator
(
  input [2:0] A,
  input [2:0] B,
  output GT,
  output LT,
  output EQ
);

  assign GT = (~B[2] & ~B[1] & ~B[0] & A[0]) | (~B[2] & ~B[1] & A[1]) | (~B[2] & A[2]) | (~B[2] & ~B[0] & A[1] & A[0]) | (~B[1] & ~B[0] & A[2] & A[0]) | (~B[1] & A[2] & A[1]) | (~B[0] & A[2] & A[1] & A[0]);
  assign LT = (B[0] & ~A[2] & ~A[1] & ~A[0]) | (B[1] & ~A[2] & ~A[1]) | (B[1] & B[0] & ~A[2] & ~A[0]) | (B[2] & ~A[2]) | (B[2] & B[0] & ~A[1] & ~A[0]) | (B[2] & B[1] & ~A[1]) | (B[2] & B[1] & B[0] & ~A[0]);
  assign EQ = (A[0] ^~ B[0]) & (A[1] ^~ B[1]) & (A[2] ^~ B[2]);
endmodule
module mux_four_to_one_test;

  // Inputs
  reg [3:0] DIN;
  reg [1:0] SEL;

  // Outputs
  wire DOUT;

  // Instantiate two counter variables for both loop
  integer count;
  integer count2;

  // Instantiate the Unit Under Test (UUT)
  mux_four_to_one uut
  (
    .DIN(DIN),
    .SEL(SEL),
    .DOUT(DOUT)
  );

  initial begin

    // Initialize Inputs
    DIN = 0;
    SEL = 0;

    // Initialize counter variables
    count = 0;
    count2 = 0;

    // Loops over the possible combinations for SEL and resets the value for DIN
    for (count = 0; count < 4; count = count + 1) begin
      SEL = count;
      DIN = 0;

      // Loops over the possible combinations for DIN for each SEL value
      for (count2 = 0; count2 <= 16; count2 = count2 + 1) begin
        #5 DIN = count2;
      end
    end
  end

  initial #340 $finish; // The test will run for a total interval of 340 nanoseconds
endmodule
module mux_four_to_one
(
  input [3:0] DIN,
  input [1:0] SEL,
  output DOUT
);

  // Each output relies on the value of the select bits and the input bits
  assign DOUT = (DIN[0] & ~SEL[0] & ~SEL[1]) | (DIN[1] & SEL[0] & ~SEL[1]) | (DIN[2] & ~SEL[0] & SEL[1]) | (DIN[3] & SEL[0] & SEL[1]);
endmodule
module full_adder_test;

  // Inputs
  reg A;
  reg B;
  reg CARRY_IN;

  // Outputs
  wire SUM;
  wire CARRY_OUT;

  // Instantiate a counter variable for the loop
  integer count;

  // Instantiate the Unit Under Test (UUT)
  full_adder uut
  (
    .A(A),
    .B(B),
    .CARRY_IN(CARRY_IN),
    .SUM(SUM),
    .CARRY_OUT(CARRY_OUT)
  );

  initial begin

    // Initialize Inputs
    A = 0;
    B = 0;
    CARRY_IN = 0;

    // Initialize counter variable
    count = 0;

    // Loops over the possible combinations for A, B and CARRY_IN
    for (count = 1; count < 12; count = count + 1) begin
      #5 {A, B, CARRY_IN} = count;
    end
  end

  initial #40 $finish; // The test will run for a total interval of 40 nanoseconds
endmodule
module full_adder
(
  input A,
  input B,
  input CARRY_IN,
  output SUM,
  output CARRY_OUT
);

  // This uses two exclusive OR (XOR) gates to SUM three inputs
  assign SUM = (A ^ B) ^ CARRY_IN;

  // This uses three OR gates to detect a CARRY_OUT from three inputs
  assign CARRY_OUT = (A & ~B & CARRY_IN) | (~A & B & CARRY_IN) | (A & B);
endmodule
module priority_encoder_test;

  // Input
  reg [3:0] D;

  // Outputs
  wire [1:0] ENC;
  wire VLD;

  // Instantiate a counter variable for the loop
  integer count;

  // Instantiate the Unit Under Test (UUT)
  priority_encoder uut
  (
    .D(D),
    .ENC(ENC),
    .VLD(VLD)
  );

  initial begin

    // Initialize Input
    D = 0;

    // Initialize counter variable
    count = 0;

    // Loops over the possible combinations for D
    for (count = 1; count <= 16; count = count + 1) begin
      #5 D = count;
    end
  end

  initial #80 $finish; // The test will run for a total interval of 80 nanoseconds
endmodule
module priority_encoder
(
  input [3:0] D,
  output [1:0] ENC,
  output VLD
);

  assign ENC[0] = (~D[2] & D[1]) | D[3];
  assign ENC[1] = D[2] | D[3];
  assign VLD = D[0] | D[1] | D[2] | D[3];
endmodule
module dec_4_to_16_test;

  // Inputs
  reg [3:0] ADDR;

  // Outputs
  wire [15:0] DEC;

  // Instantiate a counter variable for the loop
  integer count;

  // Instantiate the Unit Under Test (UUT)
  dec_4_to_16 uut
  (
    .ADDR(ADDR),
    .DEC(DEC)
  );

  initial begin

    // Initialize Inputs
    ADDR = 0;

    // Initialize counter variable
    count = 0;

    // Loops over the possible combinations for ADDR
    for (count = 1; count <= 16; count = count + 1) begin
      #5 ADDR = count;
    end
  end

  initial #80 $finish; // The test will run for a total interval of 80 nanoseconds
endmodule
module dec_4_to_16
(
  input [3:0] ADDR,
  output [15:0] DEC
);

  // Every output will output will have exactly one corresponding high
  assign DEC[0] = ~ADDR[0] & ~ADDR[1] & ~ADDR[2] & ~ADDR[3];
  assign DEC[1] = ~ADDR[0] & ~ADDR[1] & ~ADDR[2] & ADDR[3];
  assign DEC[2] = ~ADDR[0] & ~ADDR[1] & ADDR[2] & ~ADDR[3];
  assign DEC[3] = ~ADDR[0] & ~ADDR[1] & ADDR[2] & ADDR[3];
  assign DEC[4] = ~ADDR[0] & ADDR[1] & ~ADDR[2] & ~ADDR[3];
  assign DEC[5] = ~ADDR[0] & ADDR[1] & ~ADDR[2] & ADDR[3];
  assign DEC[6] = ~ADDR[0] & ADDR[1] & ADDR[2] & ~ADDR[3];
  assign DEC[7] = ~ADDR[0] & ADDR[1] & ADDR[2] & ADDR[3];
  assign DEC[8] = ADDR[0] & ~ADDR[1] & ~ADDR[2] & ~ADDR[3];
  assign DEC[9] = ADDR[0] & ~ADDR[1] & ~ADDR[2] & ADDR[3];
  assign DEC[10] = ADDR[0] & ~ADDR[1] & ADDR[2] & ~ADDR[3];
  assign DEC[11] = ADDR[0] & ~ADDR[1] & ADDR[2] & ADDR[3];
  assign DEC[12] = ADDR[0] & ADDR[1] & ~ADDR[2] & ~ADDR[3];
  assign DEC[13] = ADDR[0] & ADDR[1] & ~ADDR[2] & ADDR[3];
  assign DEC[14] = ADDR[0] & ADDR[1] & ADDR[2] & ~ADDR[3];
  assign DEC[15] = ADDR[0] & ADDR[1] & ADDR[2] & ADDR[3];
endmodule
module four_bit_adder
(
  input [3:0] A,
  input [3:0] B,
  output [4:0] SUM
);

  // The first carry is zero
  wire CARRY0;
  assign CARRY0 = 1'b0;

  // Four full adders are combined together into one 4-bit ripple adder
  full_adder op1 (A[0], B[0], CARRY0, SUM[0], CARRY1);
  full_adder op2 (A[1], B[1], CARRY1, SUM[1], CARRY2);
  full_adder op3 (A[2], B[2], CARRY2, SUM[2], CARRY3);
  full_adder op4 (A[3], B[3], CARRY3, SUM[3], SUM[4]);
endmodule
module four_bit_adder_test;

	// Inputs
	reg [3:0] A;
	reg [3:0] B;

	// Outputs
	wire [4:0] SUM;

	// Instantiate two counter variables for both loop
	integer count;

	// Instantiate the Unit Under Test (UUT)
	four_bit_adder uut
	(
		.A(A),
		.B(B),
		.SUM(SUM)
	);

  	initial begin

		// Initialize Inputs
		A = 0;
		B = 0;
		count = 0;

	end

  //Whenever the value of either A or B changes, iterate the possible combinations
  always @(A or B)
	begin
		// Loops over the possible combinations for A and B
		for (count = 0; count < 256; count = count + 1)
			#1 {A, B} = count;
			#2 $stop;
      end

endmodule
module behavioral_full_adder_64
(
  input [63:0] A,
  input [63:0] B,
  output [64:0] SUM
);

  assign SUM = (A + B);
endmodule
module behavioral_full_adder_test;

  // Inputs
  reg [63:0] A;
  reg [63:0] B;

  // Outputs
  wire [64:0] SUM;

  // Instantiate two counter variables for the test loop
  integer count;
  integer count2;

  // Instantiate the Unit Under Test (UUT)
  behavioral_full_adder_64 uut
  (
    .A(A),
    .B(B),
    .SUM(SUM)
  );

  initial begin

    $monitor("%d + %d = %d", A, B, SUM);

    // Iterate through all possible combination of 0-32
    count = 0;
    count2 = 0;

    A = 0;
    B = 0;

    // Loops over the possible combinations for the inputs A and B
    for (count = 0; count <= 32; count = count + 1) begin
      {A} = count;

      for (count2 = 0; count2 <= 32; count2 = count2 + 1) begin
        {B} = count2;
        #1;
      end
    end
  end

  initial #4000 $finish; // The test will run for a total interval of 4000 nanoseconds
endmodule
module look_ahead_adder_test;

  // Inputs
  reg [63:0] A;
  reg [63:0] B;

  // Outputs
  wire [63:0] SUM;
  wire CARRY;

  // Instantiate two counter variables for the test loop
  integer count;
  integer count2;

  // Instantiate the Unit Under Test (UUT)
  look_ahead_adder_64 uut
  (
    .A(A),
    .B(B),
    .SUM(SUM),
    .CARRY(CARRY)
  );

  initial begin

    $monitor("%d + %d = %d and carry %d", A, B, SUM, CARRY);

    // Iterate through all possible combination of 0-32
    count = 0;
    count2 = 0;

    A = 0;
    B = 0;

    // Loops over the possible combinations for the inputs A and B
    for (count = 0; count <= 32; count = count + 1) begin
      {A} = count;

      for (count2 = 0; count2 <= 32; count2 = count2 + 1) begin
        {B} = count2;
        #1;
      end
    end
  end

  initial #4000 $finish; // The test will run for a total interval of 4000 nanoseconds
endmodule
module look_ahead_adder_64
(
  input [63:0] A,
  input [63:0] B,
  output [63:0] SUM,
  output CARRY
);

  // Create wires to connect each full_adder module to another to create a ripple
  wire CARRY0, CARRY1, CARRY2, CARRY3, CARRY4, CARRY5, CARRY6, CARRY7, CARRY8, CARRY9, CARRY10;
  wire CARRY11, CARRY12, CARRY13, CARRY14, CARRY15, CARRY16, CARRY17, CARRY18, CARRY19, CARRY20;
  wire CARRY21, CARRY22, CARRY23, CARRY24, CARRY25, CARRY26, CARRY27, CARRY28, CARRY29, CARRY30, CARRY31;

  // The first carry is zero
  assign CARRY0 = 1'b0;

  two_bit_look_ahead op1 (A[1:0], B[1:0], CARRY0, SUM[1:0], CARRY1);
  two_bit_look_ahead op2 (A[3:2], B[3:2], CARRY1, SUM[3:2], CARRY2);
  two_bit_look_ahead op3 (A[5:4], B[5:4], CARRY2, SUM[5:4], CARRY3);
  two_bit_look_ahead op4 (A[7:6], B[7:6], CARRY3, SUM[7:6], CARRY4);
  two_bit_look_ahead op5 (A[9:8], B[9:8], CARRY4, SUM[9:8], CARRY5);
  two_bit_look_ahead op6 (A[11:10], B[11:10], CARRY5, SUM[11:10], CARRY6);
  two_bit_look_ahead op7 (A[13:12], B[13:12], CARRY6, SUM[13:12], CARRY7);
  two_bit_look_ahead op8 (A[15:14], B[15:14], CARRY7, SUM[15:14], CARRY8);
  two_bit_look_ahead op9 (A[17:16], B[17:16], CARRY8, SUM[17:16], CARRY9);
  two_bit_look_ahead op10 (A[19:18], B[19:18], CARRY9, SUM[19:18], CARRY10);
  two_bit_look_ahead op11 (A[21:20], B[21:20], CARRY10, SUM[21:20], CARRY11);
  two_bit_look_ahead op12 (A[23:22], B[23:22], CARRY11, SUM[23:22], CARRY12);
  two_bit_look_ahead op13 (A[25:24], B[25:24], CARRY12, SUM[25:24], CARRY13);
  two_bit_look_ahead op14 (A[27:26], B[27:26], CARRY13, SUM[27:26], CARRY14);
  two_bit_look_ahead op15 (A[29:28], B[29:28], CARRY14, SUM[29:28], CARRY15);
  two_bit_look_ahead op16 (A[31:30], B[31:30], CARRY15, SUM[31:30], CARRY16);
  two_bit_look_ahead op17 (A[33:32], B[33:32], CARRY16, SUM[33:32], CARRY17);
  two_bit_look_ahead op18 (A[35:34], B[35:34], CARRY17, SUM[35:34], CARRY18);
  two_bit_look_ahead op19 (A[37:36], B[37:36], CARRY18, SUM[37:36], CARRY19);
  two_bit_look_ahead op20 (A[39:38], B[39:38], CARRY19, SUM[39:38], CARRY20);
  two_bit_look_ahead op21 (A[41:40], B[41:40], CARRY20, SUM[41:40], CARRY21);
  two_bit_look_ahead op22 (A[43:42], B[43:42], CARRY21, SUM[43:42], CARRY22);
  two_bit_look_ahead op23 (A[45:44], B[45:44], CARRY22, SUM[45:44], CARRY23);
  two_bit_look_ahead op24 (A[47:46], B[47:46], CARRY23, SUM[47:46], CARRY24);
  two_bit_look_ahead op25 (A[49:48], B[49:48], CARRY24, SUM[49:48], CARRY25);
  two_bit_look_ahead op26 (A[51:50], B[51:50], CARRY25, SUM[51:50], CARRY26);
  two_bit_look_ahead op27 (A[53:52], B[53:52], CARRY26, SUM[53:52], CARRY27);
  two_bit_look_ahead op28 (A[55:54], B[55:54], CARRY27, SUM[55:54], CARRY28);
  two_bit_look_ahead op29 (A[57:56], B[57:56], CARRY28, SUM[57:56], CARRY29);
  two_bit_look_ahead op30 (A[59:58], B[59:58], CARRY29, SUM[59:58], CARRY30);
  two_bit_look_ahead op31 (A[61:60], B[61:60], CARRY30, SUM[61:60], CARRY31);
  two_bit_look_ahead op32 (A[63:62], B[63:62], CARRY31, SUM[63:62], CARRY);
endmodule
module two_bit_look_ahead
(
  input [1:0] A,
  input [1:0] B,
  input CARRY_IN,
  output [1:0] SUM,
  output CARRY_OUT
);

  // Defining wires for gate connections
  wire tmpsum;
  wire tmp1;
  wire tmp2;
  wire tmp3;
  wire tmp4;
  wire tmp5;
  wire tmp6;
  wire tmp7;

  // Using several XOR and AND gates to compute the bit by bit SUM output
  xor A1 (tmpsum, A[0], B[0]);
  xor A2 (SUM[0], tmpsum, CARRY_IN);
  and A3 (tmp1, tmpsum, CARRY_IN);
  and A4 (tmp2, A[0], B[0]);
  xor A5 (tmp3, A[1], B[1]);
  xor A6 (tmp4, tmp2, tmp1);
  xor A7 (SUM[1], tmp3, tmp4);

  // Using AND and OR gates to compue the CARRY_OUT output
  and B1 (tmp5, A[1], B[1]);
  or B2 (tmp6, tmp2, tmp1);
  and B3 (tmp7, tmp3, tmp6);
  or B4 (CARRY_OUT, tmp5, tmp7);
endmodule
module ripple_adder_64_test;

  // Inputs
  reg [63:0] A;
  reg [63:0] B;

  // Outputs
  wire [63:0] SUM;
  wire CARRY;

  // Instantiate two counter variables for the test loop
  integer count;
  integer count2;

  // Instantiate the Unit Under Test (UUT)
  ripple_adder_64 uut
  (
    .A(A),
    .B(B),
    .SUM(SUM),
    .CARRY(CARRY)
  );

  initial begin

    $monitor("%d + %d = %d and carry %d", A, B, SUM, CARRY);

    // Iterate through all possible combination of 0-32
    count = 0;
    count2 = 0;

    A = 0;
    B = 0;

    // Loops over the possible combinations for the inputs A and B
    for (count = 0; count <= 32; count = count + 1) begin
      {A} = count;

      for (count2 = 0; count2 <= 32; count2 = count2 + 1) begin
        {B} = count2;
        #1;
      end
    end
  end

  initial #4000 $finish; // The test will run for a total interval of 4000 nanoseconds
endmodule
module full_adder
(
  input A,
  input B,
  input CARRY_IN,
  output SUM,
  output CARRY_OUT
);

  // Declaring wires for gate connections
  wire tmpSum;
  wire tmp1;
  wire tmp1n;
  wire tmp2;
  wire tmp2n;
  wire tmp3;
  wire tmp4;
  wire tmp5;
  wire tmp6;

  // Using two XOR gates with 2 inputs per gate to compute the SUM bit output
  xor A1 (tmpSum, A, B);
  xor A2 (SUM, CARRY_IN, tmpSum);

  // Using various AND, NOT and OR gates with 2 inputs per gate to compute the CARRY_OUT bit
  not B1N (tmp1n, B);
  and B1 (tmp1, A, tmp1n);
  not B2N (tmp2n, A);
  and B2 (tmp2, tmp2n, B);
  and B3 (tmp3, A, B);
  and B4 (tmp4, tmp1, CARRY_IN);
  and B5 (tmp5, tmp2, CARRY_IN);
  or B6 (tmp6, tmp4, tmp5);
  or B7 (CARRY_OUT, tmp6, tmp3);
endmodule
module Timer (
  input                 clk,
  input                 rst,
  input                 chipSelect,
  input                 write,
  input                 writeCommand,
  input         [31:0]  dataIn,
  output        [31:0]  dataOut
);

reg timerRunning;

reg   [8:0]   divideBy;
reg   [8:0]   divider;
reg   [31:0]  counter;

wire  [2:0]   cmd;
wire  [29:0]  cmd_arg;

always @(posedge clk)
begin
  if (rst)
  begin
    divider       <= 0;
    counter       <= 0;
    divideBy      <= 64;
    timerRunning  <= 0;
  end
  else if (timerRunning)
  begin
    divider <= divider + 1;
    if (divider == divideBy -1)
    begin
      divider <= 0;
      counter <= counter + 1;
    end
  end

  if (~rst && chipSelect)
  begin
    if (write)
      counter <= dataIn;
    if (writeCommand)
    begin
      // data[2:0]  == CMD
      // data[31:3] == DATA
      case (cmd)
        0: // Reset
        begin
          divider       <= 0;
          counter       <= 0;
          timerRunning  <= 0;
        end
        1: // Set Divide By
        begin
          divideBy <= cmd_arg[8:0];
        end
        2: // Start Timer
        begin
          timerRunning <= 1;
        end
      endcase
    end
  end
end

assign dataOut  = counter;
assign cmd      = dataIn[2:0];
assign cmd_arg  = dataIn[31:3];

endmodule
module DigitalPort (
  input                 clk,
  input                 rst,
  input                 chipSelect,
  input                 writeIO,
  input                 writeDirection,
  input         [31:0]  dataIn,
  output        [31:0]  dataOut,
  output        [31:0]  directionOut,

  inout         [31:0]  IO                // Connected to FPGA pins
);

reg [31:0] direction;
reg [31:0] value;

always @(posedge clk)
begin
  if (rst)
  begin
    direction <= 0;
    value     <= 0;
  end
  else if (chipSelect)
  begin
    if (writeIO)          value     <= dataIn;
    if (writeDirection)   direction <= dataIn;
  end
end

generate
  genvar idx;
  for(idx = 0; idx < 32; idx = idx+1) begin: register
    `ifdef SIMULATION
    assign IO[idx] = direction[idx] ? value[idx] : 1'b0;
    `else
    assign IO[idx] = direction[idx] ? value[idx] : 1'bZ;
    `endif
  end
endgenerate

assign dataOut = IO;
assign directionOut = direction;

endmodule
module CPU (
  input   wire          clk,
  input   wire          reset,

  // BUS
  input         [31:0]  dataIn,
  output  wire  [31:0]  dataOut,
  output  wire  [31:0]  address,
  output  wire          busValid,          // 1 => Start bus transaction, 0 => Don't use bus
  output  wire          busInstr,          // 1 => Instruction, 0 => Data
  input   wire          busReady,          // 1 => Bus is ready with data, 0 => If bus is busy
  output                busWriteEnable,    // 1 => WRITE, 0 => READ

  // CSR
  input        [31:0]   csrDataIn,
  output       [31:0]   csrDataOut,
  output       [11:0]   csrNumber,
  output                csrWriteEnable,

  // Core CSRs
  output  wire [63:0]   instructionsExecuted
);

parameter EXCEPTION_HANDLING = 1;

// Program Counter
wire  [31:0]   pcDataOut;
wire  [31:0]   pcDataIn;
wire           pcWriteEnable;
wire           pcWriteAdd;
wire           pcCountEnable;

ProgramCounter PC(clk, reset, pcDataIn, pcDataOut, pcWriteEnable, pcWriteAdd, pcCountEnable);

// Register Bank
wire  [31:0]  regOut0;
wire  [3:0]   regNum0;

wire  [31:0]  regOut1;
wire  [3:0]   regNum1;

wire  [31:0]  wDataIn;
wire  [3:0]   wRegNum;
wire          writeEnable;

RegisterBank registers(
  .clk(clk),
  .reset(reset),
  // Port 0
  .dataOut0(regOut0),
  .regNum0(regNum0),

  // Port 1
  .dataOut1(regOut1),
  .regNum1(regNum1),

  // Write Port
  .wDataIn(wDataIn),
  .wRegNum(wRegNum),
  .writeEnable(writeEnable)
);

// ALU
wire  [3:0]   aluOp;
wire  [31:0]  aluX;
wire  [31:0]  aluY;
wire  [31:0]  aluO;
ALU alu(aluOp, aluX, aluY, aluO);

// Instruction Decoder
InstructionDecoder # (
  .EXCEPTION_HANDLING(EXCEPTION_HANDLING)
) ins (
  // Global Control
  .clk(clk),
  .reset(reset),

  // BUS
  .dataIn(dataIn),
  .dataOut(dataOut),
  .address(address),
  .busValid(busValid),
  .busInstr(busInstr),
  .busReady(busReady),
  .busWriteEnable(busWriteEnable),

  // PC Control
  .pcDataOut(pcDataOut),
  .pcWriteEnable(pcWriteEnable),
  .pcWriteAdd(pcWriteAdd),
  .pcCountEnable(pcCountEnable),
  .pcDataIn(pcDataIn),

  // Register Bank Control
  // Port 0
  .regOutA(regOut0),
  .regNumA(regNum0),

  // Port 1
  .regOutB(regOut1),
  .regNumB(regNum1),

  // Write Port
  .wRegDataIn(wDataIn),
  .wRegRegNum(wRegNum),
  .wRegWriteEnable(writeEnable),

  // ALU Control
  .aluO(aluO),
  .aluOp(aluOp),
  .aluX(aluX),
  .aluY(aluY),

  // CSR
  .csrDataIn(csrDataIn),
  .csrDataOut(csrDataOut),
  .csrNumber(csrNumber),
  .csrWriteEnable(csrWriteEnable),

  // Core CSRs
  .instructionsExecuted(instructionsExecuted)
);

endmodule
module Comparator (
  input         [3:0]   operation,
  input         [31:0]  X,
  input         [31:0]  Y,
  output        [31:0]  O
);

// Comparator Operations
// Matches funct3 from RISC-V ISA

parameter Equal = 4'h0;
parameter NotEqual = 4'h1;
parameter LesserThanSigned = 4'h4;
parameter GreaterThanOrEqualSigned = 4'h5;
parameter LesserThanUnsigned = 4'h6;
parameter GreaterThanOrEqualUnsigned = 4'h7;

reg [31:0] result;

integer i;

always @(*)
begin
  case (operation)
    LesserThanUnsigned:         result = X <  Y;
    LesserThanSigned:           result = $signed(X) < $signed(Y);
    GreaterThanOrEqualUnsigned: result = X >= Y;
    GreaterThanOrEqualSigned:   result = $signed(X) >= $signed(Y);
    Equal:                      result = X == Y;
    NotEqual:                   result = X != Y;
    default:                    result = 0;
  endcase
end

assign O = result;

endmodule
module RegisterBank (
  input   wire          clk,
  input   wire          reset,

  // Port 0
  output  wire  [31:0]  dataOut0,
  input         [3:0]   regNum0,

  // Port 1
  output  wire  [31:0]  dataOut1,
  input         [3:0]   regNum1,

  // Write Port
  input         [31:0]  wDataIn,
  input         [3:0]   wRegNum,
  input                 writeEnable     // 1 => WRITE
);

reg [31:0] registers [0:15];

initial begin
  for ( i = 0; i < 16; i=i+1)  registers[i] = 0;
end

integer i;

always @(posedge clk)
begin
  if (!reset)
  begin
   if (writeEnable) registers[wRegNum] <= wRegNum > 0 ? wDataIn : 0;
  end
end

assign dataOut0 = registers[regNum0];
assign dataOut1 = registers[regNum1];

// Only for simulation expose the registers
generate
  genvar idx;
  for(idx = 0; idx < 16; idx = idx+1) begin: register
    wire [31:0] tmp;
    assign tmp = registers[idx];
  end
endgenerate

endmodule
module ProgramCounter (
  input   wire          clk,
  input   wire          reset,
  input         [31:0]  dataIn,
  output  wire  [31:0]  dataOut,
  input                 writeEnable,    // 1 => WRITE, 0 => READ
  input                 writeAdd,       // 1 => Add dataIn to PC, 0 => Set dataIn to PC
  input                 countEnable     // 1 => COUNT UP, 0 => STOPPED
);

reg [31:0] programCounter;

always @(posedge clk)
begin
  if (reset)
  begin
    programCounter <= 0;
  end
  else if (writeEnable) programCounter <= writeAdd ? programCounter + $signed(dataIn) - 4 : dataIn;
  else if (countEnable) programCounter <= programCounter + 4;
end

assign dataOut = programCounter;

endmodule
module ALU (
  input         [3:0]   operation,
  input         [31:0]  X,
  input         [31:0]  Y,
  output        [31:0]  O
);

// ALU Operations
parameter ADD = 4'h0;
parameter SUB = 4'h1;
parameter OR = 4'h2;
parameter XOR = 4'h3;
parameter AND = 4'h4;
parameter LesserThanUnsigned = 4'h5;
parameter LesserThanSigned = 4'h6;
parameter ShiftRightUnsigned = 4'h7;
parameter ShiftRightSigned = 4'h8;
parameter ShiftLeftUnsigned = 4'h9;
parameter ShiftLeftSigned = 4'hA;
parameter GreaterThanOrEqualUnsigned = 4'hB;
parameter GreaterThanOrEqualSigned = 4'hC;
parameter Equal = 4'hD;
parameter NotEqual = 4'hE;

reg [31:0] result;

always @(*)
begin
  case (operation)
    ADD:                        result = X +  Y;
    SUB:                        result = X -  Y;
    OR:                         result = X |  Y;
    XOR:                        result = X ^  Y;
    AND:                        result = X &  Y;
    LesserThanUnsigned:         result = X <  Y;
    LesserThanSigned:           result = $signed(X) < $signed(Y);
    ShiftRightUnsigned:         result = X >> (Y[4:0]);
    ShiftRightSigned:           result = $signed(X) >>> (Y[4:0]);
    ShiftLeftUnsigned:          result = X << (Y[4:0]);
    ShiftLeftSigned:            result = $signed(X) <<< (Y[4:0]);
    GreaterThanOrEqualUnsigned: result = X >= Y;
    GreaterThanOrEqualSigned:   result = $signed(X) >= $signed(Y);
    Equal:                      result = X == Y;
    NotEqual:                   result = X != Y;
    // default:                    result = 0;
  endcase
end

assign O = result;

endmodule
module calc_unit_x16(
    input                       clk_100M,
    input                       rst_n,
    
    input [32*9*16-1:0]         w_in,
    input                       data_in_vld,
    input [32*9*16-1:0]         data_in,
    
    input [7:0]                 acc_para,
    input                       new_start,
    
    output                      data_out_vld,
    output [32*16-1:0]          data_out
);


genvar i;
generate
    for(i = 0; i < 16; i = i + 1) begin : calc_unit_gen
        calc_unit_single calc_unit_single(
            .clk_100M           (clk_100M),
            .rst_n              (rst_n),
            .w_in               (w_in[i*288+287:i*288]),
            .data_in_vld        (data_in_vld),
            .data_in            (data_in[i*288+287:i*288]),
            .new_start          (new_start),
            .data_out           (data_out[i*32+31:i*32])
        );
    end
endgenerate

reg [7:0]                      acc_cnt_cur;
always @ (posedge clk_100M or negedge rst_n)
begin
    if(!rst_n) begin
        acc_cnt_cur <= 8'b0;
    end
    else if (acc_cnt_cur >= acc_para) begin
        acc_cnt_cur <= 8'b0;
    end
    else if (data_in_vld == 1'b1) begin
        acc_cnt_cur <= acc_cnt_cur + 1'b1;
    end
end

wire                            data_out_vld_cur;
assign data_out_vld_cur = (acc_cnt_cur == acc_para) && (data_in_vld == 1'b1);

reg  [31:0]                     data_out_vld_reg;
always @ (posedge clk_100M or negedge rst_n)
begin
    if(!rst_n) begin
        data_out_vld_reg <= 31'b0;
    end
    else begin
        data_out_vld_reg <= {data_out_vld_reg[30:0], data_out_vld_cur};
    end
end

assign data_out_vld = data_out_vld_reg[31];

endmodule
module w_gen(
    input                       clk_200M,
    input                       rst_n,
    input                       clk_100M,
    
    input                       w_in_vld,
    input [127:0]               w_in,
    input                       data_vld_in,
    
    output [32*9*16-1:0]        w_out
);

wire [15:0]                     ram_w_wr_en;
wire [7:0]                      ram_w_wr_addr;
wire [32*9*16-1:0]              ram_w_wr_data_all;
wire [10:0]                     w_change_ctrl;

w_ctrl w_ctrl(
    .clk_200M                   (clk_200M         ),
    .rst_n                      (rst_n            ),
    .w_in_vld                   (w_in_vld         ),
    .w_in                       (w_in             ),
    .ram_w_wr_en                (ram_w_wr_en      ),
    .ram_w_wr_addr              (ram_w_wr_addr    ),
    .ram_w_wr_data_all          (ram_w_wr_data_all),
    .w_change_ctrl              (w_change_ctrl    )
);

genvar i;
// wire [287:0]                    ram_w_wr_data_part[15:0];
// generate
    // for(i = 0; i < 16; i = i + 1) begin : ram
        // assign ram_w_wr_data_part[i] = ram_w_wr_data_all[288*i+287 : 288*i];
    // end
// endgenerate

wire [7:0]                      ram_w_rd_addr;

generate
    for(i = 0; i < 16; i = i + 1) begin : ram_w_gen
        ram_w ram_w (
            .wrclock            ( clk_200M                  ),
            .wren               ( ram_w_wr_en[i]            ),
            .wraddress          ( ram_w_wr_addr             ),
            .data               ( ram_w_wr_data_all[288*i+287 : 288*i]),
            
            .rdclock            ( clk_100M                  ),
            .rdaddress          ( ram_w_rd_addr             ),
            .q                  ( w_out[288*i+287 : 288*i]  )
        );
    end
endgenerate

wire [10:0]                     w_change_ctrl_rd;

ram_w_ctrlsig	ram_w_ctrlsig (
    .wrclock                    ( clk_200M          ),
    .wren                       ( 1'b1              ),
    .wraddress                  ( 4'b0              ),
    .data                       ( w_change_ctrl     ),
    .rdclock                    ( clk_100M          ),
    .rdaddress                  ( 4'b0              ),
    .q                          ( w_change_ctrl_rd  )
);

reg [10:0]                      rd_cnt_cur;
always @ (posedge clk_100M or negedge rst_n)
begin
    if(!rst_n) begin
        rd_cnt_cur <= 11'd0;
    end
    else if (rd_cnt_cur >= w_change_ctrl_rd) begin
        rd_cnt_cur <= 1'b0;
    end
    else if (data_vld_in == 1'b1) begin
        rd_cnt_cur <= rd_cnt_cur + 1'b1;
    end
end

assign ram_w_rd_addr = rd_cnt_cur[7:0];



endmodule
module bias_gen(
    input                       clk_200M,
    input                       rst_n,
    input                       clk_100M,
    
    input                       bias_in_vld,
    input [127:0]               bias_in,
    
    output [511:0]              bias_out
);

wire                            fifo_wr_en;
wire  [511:0]                   fifo_wr_data;

bias_ctrl bias_ctrl(
    .clk_200M                   (clk_200M    ),
    .rst_n                      (rst_n       ),
    .bias_in_vld                (bias_in_vld ),
    .bias_in                    (bias_in     ),
    .fifo_wr_en                 (fifo_wr_en  ),
    .fifo_wr_data               (fifo_wr_data)
);

wire                            fifo_empty;
reg                             fifo_rd_en;
// wire [511:0]                    fifo_rd_data;

fifo_bias_gen	fifo_bias_gen_inst (
    .wrclk                      ( clk_200M ),
    .wrreq                      ( fifo_wr_en ),
    .wrfull                     (  ),
    .data                       ( fifo_wr_data ),
    .rdclk                      ( clk_100M ),
    .rdreq                      ( fifo_rd_en ),
    .rdempty                    ( fifo_empty ),
    .q                          ( bias_out )
);

always @ (posedge clk_100M or negedge rst_n)
begin
    if(!rst_n) begin
        fifo_rd_en <= 1'b0;
    end
    else if (fifo_empty == 1'b0) begin
        fifo_rd_en <= 1'b1;
    end
    else begin
        fifo_rd_en <= 1'b0;
    end
end






endmodule
module fp_mul (
		input  wire        clk,    //    clk.clk
		input  wire        areset, // areset.reset
		input  wire [31:0] a,      //      a.a
		input  wire [31:0] b,      //      b.b
		output wire [31:0] q       //      q.q
	);

	fp_mul_0002 fp_mul_inst (
		.clk    (clk),    //    clk.clk
		.areset (areset), // areset.reset
		.a      (a),      //      a.a
		.b      (b),      //      b.b
		.q      (q)       //      q.q
	);

endmodule
module fp_acc (
		input  wire        clk,    //    clk.clk
		input  wire        areset, // areset.reset
		input  wire [31:0] x,      //      x.x
		input  wire        n,      //      n.n
		output wire [31:0] r,      //      r.r
		output wire        xo,     //     xo.xo
		output wire        xu,     //     xu.xu
		output wire        ao,     //     ao.ao
		input  wire [0:0]  en      //     en.en
	);

	fp_acc_0002 fp_acc_inst (
		.clk    (clk),    //    clk.clk
		.areset (areset), // areset.reset
		.x      (x),      //      x.x
		.n      (n),      //      n.n
		.r      (r),      //      r.r
		.xo     (xo),     //     xo.xo
		.xu     (xu),     //     xu.xu
		.ao     (ao),     //     ao.ao
		.en     (en)      //     en.en
	);

endmodule
module fp_add (
		input  wire        clk,    //    clk.clk
		input  wire        areset, // areset.reset
		input  wire [31:0] a,      //      a.a
		input  wire [31:0] b,      //      b.b
		output wire [31:0] q       //      q.q
	);

	fp_add_0002 fp_add_inst (
		.clk    (clk),    //    clk.clk
		.areset (areset), // areset.reset
		.a      (a),      //      a.a
		.b      (b),      //      b.b
		.q      (q)       //      q.q
	);

endmodule
module fp_add_bias (
		input  wire        clk,    //    clk.clk
		input  wire        areset, // areset.reset
		input  wire [31:0] a,      //      a.a
		input  wire [31:0] b,      //      b.b
		output wire [31:0] q       //      q.q
	);

	fp_add_bias_0002 fp_add_bias_inst (
		.clk    (clk),    //    clk.clk
		.areset (areset), // areset.reset
		.a      (a),      //      a.a
		.b      (b),      //      b.b
		.q      (q)       //      q.q
	);

endmodule
module fp_cmp_bias (
		input  wire        clk,    //    clk.clk
		input  wire        areset, // areset.reset
		input  wire [31:0] a,      //      a.a
		input  wire [31:0] b,      //      b.b
		output wire [0:0]  q       //      q.q
	);

	fp_cmp_bias_0002 fp_cmp_bias_inst (
		.clk    (clk),    //    clk.clk
		.areset (areset), // areset.reset
		.a      (a),      //      a.a
		.b      (b),      //      b.b
		.q      (q)       //      q.q
	);

endmodule
module fifo_data (
	data,
	rdclk,
	rdreq,
	wrclk,
	wrreq,
	q,
	rdempty,
	rdusedw,
	wrfull);

	input	[784:0]  data;
	input	  rdclk;
	input	  rdreq;
	input	  wrclk;
	input	  wrreq;
	output	[784:0]  q;
	output	  rdempty;
	output	[7:0]  rdusedw;
	output	  wrfull;

	wire [784:0] sub_wire0;
	wire  sub_wire1;
	wire [7:0] sub_wire2;
	wire  sub_wire3;
	wire [784:0] q = sub_wire0[784:0];
	wire  rdempty = sub_wire1;
	wire [7:0] rdusedw = sub_wire2[7:0];
	wire  wrfull = sub_wire3;

	dcfifo	dcfifo_component (
				.data (data),
				.rdclk (rdclk),
				.rdreq (rdreq),
				.wrclk (wrclk),
				.wrreq (wrreq),
				.q (sub_wire0),
				.rdempty (sub_wire1),
				.rdusedw (sub_wire2),
				.wrfull (sub_wire3),
				.aclr (),
				.eccstatus (),
				.rdfull (),
				.wrempty (),
				.wrusedw ());
	defparam
		dcfifo_component.intended_device_family = "Cyclone V",
		dcfifo_component.lpm_numwords = 256,
		dcfifo_component.lpm_showahead = "ON",
		dcfifo_component.lpm_type = "dcfifo",
		dcfifo_component.lpm_width = 785,
		dcfifo_component.lpm_widthu = 8,
		dcfifo_component.overflow_checking = "ON",
		dcfifo_component.rdsync_delaypipe = 4,
		dcfifo_component.underflow_checking = "ON",
		dcfifo_component.use_eab = "ON",
		dcfifo_component.wrsync_delaypipe = 4;


endmodule
module ram_w_ctrlsig (
	data,
	rdaddress,
	rdclock,
	wraddress,
	wrclock,
	wren,
	q);

	input	[10:0]  data;
	input	[3:0]  rdaddress;
	input	  rdclock;
	input	[3:0]  wraddress;
	input	  wrclock;
	input	  wren;
	output	[10:0]  q;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_off
`endif
	tri1	  wrclock;
	tri0	  wren;
`ifndef ALTERA_RESERVED_QIS
// synopsys translate_on
`endif

	wire [10:0] sub_wire0;
	wire [10:0] q = sub_wire0[10:0];

	altsyncram	altsyncram_component (
				.address_a (wraddress),
				.address_b (rdaddress),
				.clock0 (wrclock),
				.clock1 (rdclock),
				.data_a (data),
				.wren_a (wren),
				.q_b (sub_wire0),
				.aclr0 (1'b0),
				.aclr1 (1'b0),
				.addressstall_a (1'b0),
				.addressstall_b (1'b0),
				.byteena_a (1'b1),
				.byteena_b (1'b1),
				.clocken0 (1'b1),
				.clocken1 (1'b1),
				.clocken2 (1'b1),
				.clocken3 (1'b1),
				.data_b ({11{1'b1}}),
				.eccstatus (),
				.q_a (),
				.rden_a (1'b1),
				.rden_b (1'b1),
				.wren_b (1'b0));
	defparam
		altsyncram_component.address_aclr_b = "NONE",
		altsyncram_component.address_reg_b = "CLOCK1",
		altsyncram_component.clock_enable_input_a = "BYPASS",
		altsyncram_component.clock_enable_input_b = "BYPASS",
		altsyncram_component.clock_enable_output_b = "BYPASS",
		altsyncram_component.intended_device_family = "Cyclone V",
		altsyncram_component.lpm_type = "altsyncram",
		altsyncram_component.numwords_a = 16,
		altsyncram_component.numwords_b = 16,
		altsyncram_component.operation_mode = "DUAL_PORT",
		altsyncram_component.outdata_aclr_b = "NONE",
		altsyncram_component.outdata_reg_b = "UNREGISTERED",
		altsyncram_component.power_up_uninitialized = "FALSE",
		altsyncram_component.ram_block_type = "MLAB",
		altsyncram_component.widthad_a = 4,
		altsyncram_component.widthad_b = 4,
		altsyncram_component.width_a = 11,
		altsyncram_component.width_b = 11,
		altsyncram_component.width_byteena_a = 1;


endmodule
module fifo_bias_gen (
	data,
	rdclk,
	rdreq,
	wrclk,
	wrreq,
	q,
	rdempty,
	wrfull);

	input	[511:0]  data;
	input	  rdclk;
	input	  rdreq;
	input	  wrclk;
	input	  wrreq;
	output	[511:0]  q;
	output	  rdempty;
	output	  wrfull;

	wire [511:0] sub_wire0;
	wire  sub_wire1;
	wire  sub_wire2;
	wire [511:0] q = sub_wire0[511:0];
	wire  rdempty = sub_wire1;
	wire  wrfull = sub_wire2;

	dcfifo	dcfifo_component (
				.data (data),
				.rdclk (rdclk),
				.rdreq (rdreq),
				.wrclk (wrclk),
				.wrreq (wrreq),
				.q (sub_wire0),
				.rdempty (sub_wire1),
				.wrfull (sub_wire2),
				.aclr (),
				.eccstatus (),
				.rdfull (),
				.rdusedw (),
				.wrempty (),
				.wrusedw ());
	defparam
		dcfifo_component.intended_device_family = "Cyclone V",
		dcfifo_component.lpm_numwords = 64,
		dcfifo_component.lpm_showahead = "OFF",
		dcfifo_component.lpm_type = "dcfifo",
		dcfifo_component.lpm_width = 512,
		dcfifo_component.lpm_widthu = 6,
		dcfifo_component.overflow_checking = "ON",
		dcfifo_component.rdsync_delaypipe = 4,
		dcfifo_component.underflow_checking = "ON",
		dcfifo_component.use_eab = "ON",
		dcfifo_component.wrsync_delaypipe = 4;


endmodule
module full_handshake_rx #(
    parameter DW = 32)(             // RX要接收数据的位宽

    input wire clk,                 // RX端时钟信号
    input wire rst_n,               // RX端复位信号

    // from tx
    input wire req_i,               // TX端请求信号
    input wire[DW-1:0] req_data_i,  // TX端输入数据

    // to tx
    output wire ack_o,              // RX端应答TX端信号

    // to rx
    output wire[DW-1:0] recv_data_o,// RX端接收到的数据
    output wire recv_rdy_o          // RX端是否接收到数据信号

    );

localparam STATE_IDLE     = 2'b01;
localparam STATE_DEASSERT = 2'b10;

reg[1:0] state;
reg[1:0] state_next;
reg req_d;
reg req;
reg[DW-1:0] recv_data;
reg recv_rdy;
reg ack;
    always @ (posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            state <= STATE_IDLE;
        end else begin
            state <= state_next;
        end
    end

    always @ (*) begin
        case (state)
            // 等待TX请求信号req=1
            STATE_IDLE: begin
                if (req == 1'b1) begin
                    state_next = STATE_DEASSERT;
                end else begin
                    state_next = STATE_IDLE;
                end
            end
            // 等待req=0
            STATE_DEASSERT: begin
                if (req) begin
                    state_next = STATE_DEASSERT;
                end else begin
                    state_next = STATE_IDLE;
                end
            end
            default: begin
                state_next = STATE_IDLE;
            end
        endcase
    end



    // 将请求信号打两拍进行同步
    always @ (posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            req_d <= 1'b0;
            req <= 1'b0;
        end else begin
            req_d <= req_i;
            req <= req_d;
        end
    end



    always @ (posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            ack <= 1'b0;
            recv_rdy <= 1'b0;
            recv_data <= {(DW){1'b0}};
        end else begin
            case (state)
                STATE_IDLE: begin
                    if (req == 1'b1) begin
                        ack <= 1'b1;
                        recv_rdy <= 1'b1;           // 这个信号只会持续一个时钟
                        recv_data <= req_data_i;    // 这个信号只会持续一个时钟
                    end
                end
                STATE_DEASSERT: begin
                    recv_rdy <= 1'b0;
                    recv_data <= {(DW){1'b0}};
                    // req撤销后ack也撤销
                    if (req == 1'b0) begin
                        ack <= 1'b0;
                    end
                end
            endcase
        end
    end

    assign ack_o = ack;
    assign recv_rdy_o = recv_rdy;
    assign recv_data_o = recv_data;

endmodule
module rstc (
    input wire clk,
    input wire hard_rst_n,  //硬件复位，低电平有效
    input wire soft_rst_en, //软件复位，高电平有效
    input wire jtag_rst_en, //JTAG复位，高电平有效
    output reg rst_n
);
reg [3:0] sys_rst_cnt = 4'h0;//系统复位计数器
reg hard_rst_r,hard_rst_en;

//复位计数
always @(posedge clk) begin
    hard_rst_r <= ~hard_rst_n;
    hard_rst_en <= hard_rst_r;
    if (jtag_rst_en | soft_rst_en | hard_rst_en) begin//若发生复位事件
        sys_rst_cnt <= 4'h0;
        rst_n <= 1'b0;
    end
    else begin//没有复位事件
        if(sys_rst_cnt == 4'hF) begin//复位完成
            sys_rst_cnt <= sys_rst_cnt;
            rst_n <= 1'b1;
        end
        else begin//复位中
            sys_rst_cnt <= sys_rst_cnt + 1;
            rst_n <= 1'b0;
        end
    end
end

endmodule
module sm3_core_top (
    input                       clk,
    input                       rst_n,
    input [`INPT_DW1:0]         msg_inpt_d,//消息数据32bit
    input [`INPT_BYTE_DW1:0]    msg_inpt_vld_byte,//消息字节使能
    input                       msg_inpt_vld,//消息输入有效
    input                       msg_inpt_lst,//消息输入最后一个数据
    
    output        wire          msg_inpt_rdy,//消息输入准备好

    output wire   [255:0]       cmprss_otpt_res,//杂凑结果256bit
    output        wire          cmprss_otpt_vld//杂凑结果输出有效
);

//interface
wire                       pad_otpt_ena;
wire [`INPT_DW1:0]         pad_otpt_d;
wire                       pad_otpt_lst;
wire                       pad_otpt_vld;

wire [`INPT_DW1:0]         expnd_otpt_wj; 
wire [`INPT_DW1:0]         expnd_otpt_wjj; 
wire                       expnd_otpt_lst;
wire                       expnd_otpt_vld; 


sm3_pad_core U_sm3_pad_core(

    .clk                    (clk                    ),
    .rst_n                  (rst_n                  ),

    .msg_inpt_d_i           (msg_inpt_d             ),
    .msg_inpt_vld_byte_i    (msg_inpt_vld_byte      ),
    .msg_inpt_vld_i         (msg_inpt_vld           ),
    .msg_inpt_lst_i         (msg_inpt_lst           ),

    .msg_inpt_rdy_o         (msg_inpt_rdy           ),

    .pad_otpt_ena_i         (pad_otpt_ena        ),

    .pad_otpt_d_o           (pad_otpt_d             ),
    .pad_otpt_lst_o         (pad_otpt_lst           ),
    .pad_otpt_vld_o         (pad_otpt_vld           )
); 

sm3_expnd_core U_sm3_expnd_core(

    .clk                    (clk                        ),
    .rst_n                  (rst_n                      ),


    .pad_inpt_d_i               ( pad_otpt_d                    ),
    .pad_inpt_vld_i             ( pad_otpt_vld                  ),
    .pad_inpt_lst_i             ( pad_otpt_lst                  ),

    .pad_inpt_rdy_o             ( pad_otpt_ena                  ),
    .expnd_otpt_wj_o            ( expnd_otpt_wj                 ),
    .expnd_otpt_wjj_o           ( expnd_otpt_wjj                ),
    .expnd_otpt_lst_o           ( expnd_otpt_lst                ),
    .expnd_otpt_vld_o           ( expnd_otpt_vld                )
);   

sm3_cmprss_core U_sm3_cmprss_core(

    .clk                    (clk                        ),
    .rst_n                  (rst_n                      ),


    .expnd_inpt_wj_i            ( expnd_otpt_wj                  ),
    .expnd_inpt_wjj_i           ( expnd_otpt_wjj                  ),
    .expnd_inpt_lst_i           ( expnd_otpt_lst                  ),
    .expnd_inpt_vld_i           ( expnd_otpt_vld                  ),


    .cmprss_otpt_res_o          ( cmprss_otpt_res               ),
    .cmprss_otpt_vld_o          ( cmprss_otpt_vld               )

);  
    
endmodule