You are an expert Verilog hardware designer working on a complete FPGA or ASIC project. You are given the full source code of a Verilog project. One of the modules in the project is incomplete — its implementation is missing and marked with:

// >>> Module Implementation Begin

// <<< Module Implementation End

Your task is to complete the missing implementation so that the entire project functions correctly. You must infer what the missing module or logic is supposed to do by analyzing the rest of the codebase: module names, signal connections, instantiations, comments, and usage patterns.

Follow these rules:

1. Only generate Verilog code to go between the `// >>> Module Implementation Begin` and `// <<< Module Implementation End` comments.
2. Use Verilog-2001 syntax. Ensure the code is synthesizable.
3. Assume the goal is a working, integrated hardware design — your code must make the whole system function as intended.
4. Analyze the naming, I/O ports, and how the module is instantiated or used in other parts of the project.
5. Implement correct behavior based on design context. Do not guess randomly — reason it out.
6. Avoid vendor-specific features unless explicitly required.
7. Do not output comments, explanation, or anything outside the required code region unless explicitly asked.

Your output should contain **only the Verilog code** that fits inside the marked region.

/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_bilal_trng (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

    // Set unused outputs to zero
    assign uio_oe = 8'b0000_0000;
    assign uio_out = 8'b0000_0000;
    assign uo_out[7:3] = 5'b00000;

    // Capture unused signals to avoid warnings
    wire _unused = &{ena, uio_in}; // Safely use unused inputs

    TRNG TRNG (
        .TRNG_Enable(ui_in[0]),
        .TRNG_Clock(clk),         // Clock signal (50 MHz) for Tiny Tapeout requirements
        .ctrl_mode(ui_in[1]),     // Control signal: 0 = hashed output, 1 = raw Sample_Out
        .failure(uo_out[0]),      // Repetition Count Test failure flag
        .UART_Tx(uo_out[2]),      // UART Transmitted Data
        .hash_rdy(uo_out[1])      // Hash ready signal
    );

endmodule



`default_nettype none

//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    12:20:19 06/03/2008 
// Design Name: 
// Module Name:    ch_xyz 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

//===========================================================================================

module ch_xyz	( 
				x,
				y,
				z,
				CH
			);

//===========================================================================================

input	[31:0]			x;
input	[31:0]			y;
input	[31:0]			z;
output	[31:0]			CH;

//===========================================================================================

assign	CH = ( (x & y) ^ ( (~x) & z) );

//--------------------------------------------------------------------------------------------------------

endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    12:31:36 06/03/2008 
// Design Name: 
// Module Name:    maj_xyz 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

//===========================================================================================

module maj_xyz	( 
					x,
					y,
					z,
					MAJ
				);

//===========================================================================================

input	[31:0]			x;
input	[31:0]			y;
input	[31:0]			z;
output	[31:0]			MAJ;

//===========================================================================================

assign	MAJ = ( (x & y) ^ (x & z) ^ (y & z) );

//--------------------------------------------------------------------------------------------------------

endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:29:02 06/03/2008 
// Design Name: 
// Module Name:    summation_1 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module summation_1 
				(
					x_1,
					sum_1				
				);

input	[31:0] 	x_1;
output	[31:0]	sum_1;
				
assign sum_1 = ( { x_1[5:0] , x_1[31:6] } ^ { x_1[10:0] , x_1[31:11] } ^ { x_1[24:0] , x_1[31:25] } );


endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:19:55 06/03/2008 
// Design Name: 
// Module Name:    compression 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////

//===========================================================================================
module compression
				(
					start,
					K,
					W,
					w_rdy,
					count,
					done,
					clk,
					hash_rdy,
					HASH
				);

//===========================================================================================

input				start;
input	[31:0]		K;
input	[31:0]		W;
input				w_rdy;
input	[4:0]		count;
input				done;
input				clk;
wire	[31:0]		a;
wire	[31:0]		b;
wire	[31:0]		c;
wire	[31:0]		e;
wire	[31:0]		f;
wire	[31:0]		g;
wire	[31:0]		h;
output				hash_rdy;
output	[255:0]		HASH;

//===========================================================================================

wire		[31:0]		t1;
wire		[31:0]		t2;

//===========================================================================================

T1 t_1
				(	
					.e					(e), 
					.f					(f), 
					.g					(g), 
					.h					(h), 
					.K					(K), 
					.W					(W), 
					.t1					(t1)
				 );

T2 t_2
				(
					.a					(a), 
					.b					(b), 
					.c					(c), 
					.t2					(t2)
				 );


hash_generator hash_gen 
				(
					.t1					(t1), 
					.t2					(t2),
					.count				(count),
					.w_rdy				(w_rdy),
					.done				(done),
					.clk					(clk), 
					.start				(start), 
					.a					(a), 
					.b					(b), 
					.c					(c), 
					.e					(e), 
					.f					(f), 
					.g					(g), 
					.h					(h),
					.hash_rdy				(hash_rdy),
					.HASH				(HASH)
				    );

//--------------------------------------------------------------------------------------------------------
endmodule

//===========================================================================================


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    11:29:54 06/04/2008 
// Design Name: 
// Module Name:    RAM 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module message_schedule
(
				addr1,
				addr2,
				din1,
				din2,
				we1,
				we2,
				clk,
				dout1,
				dout2
			);
			
input		[3:0]		addr1;
input		[3:0]		addr2;
input		[31:0]		din1;
input		[31:0]		din2;
input					we1;
input					we2;
input					clk;
output		[31:0]		dout1;
output		[31:0]		dout2;

reg			[31:0]		dout1;
reg			[31:0]		dout2;
reg			[31:0]		RAM		[0:15];

//===========================================================================================

//------------------------------------- port 1 ----------------------------------------------------------

always@(posedge clk) 
begin
	if (we1)
		RAM[addr1] <= din1;
	
	dout1 <= RAM[addr1];
end

//------------------------------------- port 2 ----------------------------------------------------------

always@(posedge clk) 
begin
	if (we2)
		RAM[addr2] <= din2;
	
	dout2 <= RAM[addr2];
end


endmodule

//===========================================================================================


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:37:25 06/05/2008 
// Design Name: 
// Module Name:    constants 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module constants(
				address,
				clk,
				dout
			);

input	[5:0]		address;
input				clk;
output	[31:0]		dout;

reg		[31:0]		dout;
reg		[31:0]		ROM		[0:63];

always@(posedge clk)
begin
	dout <= ROM[address];
end

initial
begin
	ROM[0] = 32'h428a2f98;
	ROM[1] = 32'h71374491;
	ROM[2] = 32'hb5c0fbcf;
	ROM[3] = 32'he9b5dba5;
	ROM[4] = 32'h3956c25b;
	ROM[5] = 32'h59f111f1;
	ROM[6] = 32'h923f82a4;
	ROM[7] = 32'hab1c5ed5;
	ROM[8] = 32'hd807aa98;
	ROM[9] = 32'h12835b01;
	ROM[10] = 32'h243185be;
	ROM[11] = 32'h550c7dc3;
	ROM[12] = 32'h72be5d74;
	ROM[13] = 32'h80deb1fe;
	ROM[14] = 32'h9bdc06a7;
	ROM[15] = 32'hc19bf174;
	ROM[16] = 32'he49b69c1;
	ROM[17] = 32'hefbe4786;
	ROM[18] = 32'h0fc19dc6;
	ROM[19] = 32'h240ca1cc;
	ROM[20] = 32'h2de92c6f;
	ROM[21] = 32'h4a7484aa;
	ROM[22] = 32'h5cb0a9dc;
	ROM[23] = 32'h76f988da;
	ROM[24] = 32'h983e5152;
	ROM[25] = 32'ha831c66d;
	ROM[26] = 32'hb00327c8;
	ROM[27] = 32'hbf597fc7;
	ROM[28] = 32'hc6e00bf3;
	ROM[29] = 32'hd5a79147;
	ROM[30] = 32'h06ca6351;
	ROM[31] = 32'h14292967;
	ROM[32] = 32'h27b70a85;
	ROM[33] = 32'h2e1b2138;
	ROM[34] = 32'h4d2c6dfc;
	ROM[35] = 32'h53380d13;
	ROM[36] = 32'h650a7354;
	ROM[37] = 32'h766a0abb;
	ROM[38] = 32'h81c2c92e;
	ROM[39] = 32'h92722c85;
	ROM[40] = 32'ha2bfe8a1;
	ROM[41] = 32'ha81a664b;
	ROM[42] = 32'hc24b8b70;
	ROM[43] = 32'hc76c51a3;
	ROM[44] = 32'hd192e819;
	ROM[45] = 32'hd6990624;
	ROM[46] = 32'hf40e3585;
	ROM[47] = 32'h106aa070;
	ROM[48] = 32'h19a4c116;
	ROM[49] = 32'h1e376c08;
	ROM[50] = 32'h2748774c;
	ROM[51] = 32'h34b0bcb5;
	ROM[52] = 32'h391c0cb3;
	ROM[53] = 32'h4ed8aa4a;
	ROM[54] = 32'h5b9cca4f;
	ROM[55] = 32'h682e6ff3;
	ROM[56] = 32'h748f82ee;
	ROM[57] = 32'h78a5636f;
	ROM[58] = 32'h84c87814;
	ROM[59] = 32'h8cc70208;
	ROM[60] = 32'h90befffa;
	ROM[61] = 32'ha4506ceb;
	ROM[62] = 32'hbef9a3f7;
	ROM[63] = 32'hc67178f2;
end

endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:50:47 06/03/2008 
// Design Name: 
// Module Name:    T1 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module T1		
		(
			e,
			f,
			g,
			h,
			K,
			W,
			t1
		);

input	[31:0]			e;
input	[31:0]			f;
input	[31:0]			g;
input	[31:0]			h;
input	[31:0]			K;
input	[31:0]			W;
output	[31:0]			t1;

wire		[31:0]			sum_1;
wire		[31:0]			CH;

ch_xyz ch 
		(
		    .x				(e), 
		    .y				(f), 
		    .z				(g), 
		    .CH			(CH)
		);

summation_1 sum1
		(
		    .x_1			(e), 
		    .sum_1			(sum_1)
		    );
		

assign	t1 = 	h + sum_1 + CH + K + W;



endmodule


//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Muhamamd Bilal
// 
// Create Date: 02/10/2025 09:40:16 AM
// Design Name: TRNG ON ASIC
// Module Name: repetition_count_test 
// Project Name: TRNG_CONDITIONED
// Target Devices: ZCU102
// Tool Versions: Vivado 2024.1
// Description:  This is the Approved Health test for my TRNG from Sp 800 -90 B Standard.
// 
// Dependencies: Standalone Moduel with a test bench file named as test_health_rep_count.v
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module Repetition_Count_Test (
    input wire clk,           // Clock signal
    input wire rst,           // Reset signal (active high)
    input wire bit_in,        // Input bit from the bitstream
    output reg failure        // Failure signal (asserts when test fails)
);

    parameter [5:0] CUTOFF = 32; // Maximum allowed consecutive repetitions of the same bit

    reg prev_bit;             // Register to store the previous bit
    reg [5:0] count;          // Counter to track repetitions of the same bit (6 bits for counting up to 64, we need 32)

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            // Reset the state
            prev_bit <= 1'b0;
            count <= 6'b0;
            failure <= 1'b0;
        end else begin
            if (bit_in == prev_bit) begin
                // Increment the repetition counter if the bit matches the previous one
                count <= count + 1;
                if (count >= CUTOFF) begin
                    failure <= 1'b1; // Signal failure if cutoff is exceeded
                end
            end else begin
                // Reset the counter and update the previous bit
                count <= 6'b1;
                prev_bit <= bit_in;
                failure <= 1'b0; // Clear the failure signal
            end
        end
    end
endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:02:31 06/03/2008 
// Design Name: 
// Module Name:    T2 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module T2
		(	
			a,
			b,
			c,
			t2		
		);

input	[31:0]			a;
input	[31:0]			b;
input	[31:0]			c;
output	[31:0]			t2;

wire		[31:0]			sum;
wire		[31:0]			MAJ;

maj_xyz maj
		(
		    .x			(a), 
		    .y			(b), 
		    .z			(c), 
		    .MAJ		(MAJ)
		);

summatin_0 sum0
		(
		    .x			(a), 
		    .sum		(sum)
        	);

assign	t2 = sum + MAJ;

endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:08:48 06/09/2008 
// Design Name: 
// Module Name:    iteration_generator 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module controller
					(
						start,
						clk,
						address,
						done,
						count
					);

input			start;
input			clk;
output	[5:0]	address;
output			done;
output	[4:0]	count;

reg		[8:0]	iteration;
reg				done;
reg		[4:0]	count;

assign address = iteration[5:0];

always @ (posedge clk)
begin
	if(start)
		count <= 0;
	else if(count == 21)
		count <= 16;
	else 
		count <= count + 1;
end

always @ (posedge clk)
begin
	if(start)
	begin
		iteration <= 0;
		done <= 0;
	end
	else if(iteration == 63)
	begin
		iteration <= 191;
		done <=  1;
	end
	else if(iteration == 191)
	begin
		iteration <= 255;
		done <=  1;
	end
	else if(iteration == 255)
	begin
		iteration <= 319;
		done <=  1;
	end
	
	else if(iteration == 319)
	begin
		iteration <= 383 ;
		done <=  1;
	end
	
	else if(iteration == 383)
	begin
		iteration <= 447 ;
		done <=  1;
	end
	
	else if(iteration == 447)
	begin
		iteration <= iteration ;
		done <=  0;
	end

	else if(count == 15 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else if(count == 16 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else if(count == 17 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else if(count == 18 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else if(count == 19 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else if(count == 20 )
	begin
		iteration <= iteration;
		done <=  0;
	end
	
	else
	begin
		iteration <= iteration + 1;
		done <= 0;
	end
end

endmodule


//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    09:50:40 06/05/2008 
// Design Name: 
// Module Name:    hash_computation 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module SHA256
					(
						M,
						start,
						clk,
						HASH,
						hash_rdy 
					);


input		[511:0]		M;
input					start;
input					clk;
output		[255:0]		HASH;
output					hash_rdy;

wire			[31:0]		W;
wire			[31:0]		K;
wire						start;
wire			[5:0]		connect;
wire			[4:0]		count;
wire						w_rdy;
wire						done;


constants const_inst 
			(
			    .address				(connect), 
			    .clk					(clk), 
			    .dout					(K)
			);

expansion expand			
			(
				.M					(M),
				.start				(start),
				.count				(count), 		
				.clk					(clk),
				.w_rdy				(w_rdy),								
				.W					(W)
			);

controller control
			(
				.start				(start), 
				.clk					(clk), 
				.address				(connect),
				.done				(done),
				.count				(count)
			);


compression compress 
			(
			    .start					(start),
			    .K						(K), 
			    .W					(W), 
			    .w_rdy					(w_rdy),
			    .done					(done),
			    .count					(count),
			    .clk					(clk),
			    .hash_rdy				(hash_rdy),
			    .HASH					(HASH)
			);


endmodule



//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: Muhamamd Bilal
// 
// Create Date: 02/10/2025 09:40:16 AM
// Design Name: TRNG ON ASIC (Version one submission for Tiny tape out, will use skywater 130 nm technology (open source))
// Module Name: TRNG
// Project Name: TRNG_V1
// Target Devices: ZCU102
// Tool Versions: Vivado 2024.1
// Description: This module implements a top-level True Random Number Generator (TRNG) designed for ASICs 
//              and validated on the ZCU102 FPGA. It integrates multiple submodules, including a noise source, sampler
//              and a SHA-256-based conditioner for cryptographic-grade randomness. 
//              The TRNG operates in two modes: hashed output mode for secure applications and raw output mode for entropy analysis. 
//              It features a state machine with modes for data collection, hashing, and UART-based transmission. 
//              Health tests, such as the Repetition Count Test, ensure the quality of generated random bits. 
//              The module is optimized for TinyTapeout requirements, including a 50 MHz clock input.
// 
// Dependencies: Repitition test count.v , SHA256 Files , Trng.v , uart_tx.v
// 
// Revision: 1.1
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

/////////////////////////////// EXOR_Gate /////////////////////////////////
module EXOR_Gate
(
    EXOR_Gate_In1,
    EXOR_Gate_In2,
    EXOR_Gate_In3,
    EXOR_Gate_In4,
    EXOR_Gate_In5,
    EXOR_Gate_Out
);

input EXOR_Gate_In1;
input EXOR_Gate_In2;
input EXOR_Gate_In3;
input EXOR_Gate_In4;
input EXOR_Gate_In5;
output EXOR_Gate_Out;

assign EXOR_Gate_Out = EXOR_Gate_In1 ^ EXOR_Gate_In2 ^ EXOR_Gate_In3 ^ EXOR_Gate_In4 ^ EXOR_Gate_In5;

endmodule

/////////////////////////////// NOT_Gate /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
module NOT_Gate
(
	NOT_Gate_In,
	NOT_Gate_Out
);
//- Ports -----------------------------------------------------------------------					
input	NOT_Gate_In;	// NOT Gate input.
output	NOT_Gate_Out;	// NOT Gate output.
//- Functionality ---------------------------------------------------------------
assign NOT_Gate_Out = ~ NOT_Gate_In;
//-------------------------------------------------------------------------------
endmodule

/////////////////////////////// NAND_Gate /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
module NAND_Gate
(
	NAND_Gate_In1,
	NAND_Gate_In2,
	NAND_Gate_Out
);			
input NAND_Gate_In1;	// Input 1 of NAND Gate
input NAND_Gate_In2; // Input 2 of NAND Gate
output NAND_Gate_Out;	// Output of NAND Gate
//- Functionality ---------------------------------------------------------------
assign NAND_Gate_Out = ~ (NAND_Gate_In1 & NAND_Gate_In2);
//-------------------------------------------------------------------------------
endmodule

/////////////////////////////// Noise_Source_Loop /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
(* dont_touch = "true" *)module Noise_Source_Loop
(
	Noise_Source_Loop_In,
	Noise_Source_Loop_Out
);
//- Ports -----------------------------------------------------------------------
(* dont_touch = "true" *)input	Noise_Source_Loop_In;	// FeedBack from the output
(* dont_touch = "true" *)output	Noise_Source_Loop_Out;	// Output and FeedBack to the input
//- Connections -----------------------------------------------------------------
(* dont_touch = "true" *)wire	NAND1_OUT_TO_NOT1_IN;
(* dont_touch = "true" *)wire	NOT1_OUT_TO_NOT2_IN;
(* dont_touch = "true" *)wire	NOT2_OUT_TO_NAND1_IN2;
//- Instantiation (NAND_Gate) ---------------------------------------------------
(* dont_touch = "true" *)NAND_Gate NAND_1
(
	 (* dont_touch = "true" *).NAND_Gate_In1(Noise_Source_Loop_In), 
	 (* dont_touch = "true" *).NAND_Gate_In2(NOT2_OUT_TO_NAND1_IN2), 
	 (* dont_touch = "true" *).NAND_Gate_Out(NAND1_OUT_TO_NOT1_IN)
);
//- Instantiation (NOT_Gate 1) --------------------------------------------------				
(* dont_touch = "true" *)NOT_Gate NOT_1 
(
	(* dont_touch = "true" *).NOT_Gate_In(NAND1_OUT_TO_NOT1_IN), 
	(* dont_touch = "true" *).NOT_Gate_Out(NOT1_OUT_TO_NOT2_IN)
);			
//- Instantiation (NOT_Gate 2) --------------------------------------------------					
(* dont_touch = "true" *)NOT_Gate NOT_2 
(
	 (* dont_touch = "true" *).NOT_Gate_In(NOT1_OUT_TO_NOT2_IN), 
	 (* dont_touch = "true" *).NOT_Gate_Out(NOT2_OUT_TO_NAND1_IN2)
);			
//- Output Connection -----------------------------------------------------------					
assign	Noise_Source_Loop_Out = NOT2_OUT_TO_NAND1_IN2;
//-------------------------------------------------------------------------------
endmodule

/////////////////////////////// Extension /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
module Extension
(
	Extension_In,
	Extension_Out1,
	Extension_Out2,
	Extension_Out3,
	Extension_Out4,
	Extension_Out5
);
//- Ports -----------------------------------------------------------------------			
input	Extension_In;
output	Extension_Out1;
output	Extension_Out2;
output	Extension_Out3;
output	Extension_Out4;
output	Extension_Out5;
//- Functionality ---------------------------------------------------------------
assign Extension_Out1 = Extension_In;
assign Extension_Out2 = Extension_In;
assign Extension_Out3 = Extension_In;
assign Extension_Out4 = Extension_In;
assign Extension_Out5 = Extension_In;
//-------------------------------------------------------------------------------
endmodule

/////////////////////////////// Noise_Source /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
(* KEEP = "true" *)module Noise_Source
(
	Noise_Source_In,
	Noise_Source_Out
);
//- Ports -----------------------------------------------------------------------					
(* KEEP = "true" *)input Noise_Source_In;	// Active Low. Acts as enable for the loop
(* KEEP = "true" *)output Noise_Source_Out; // Noise

//- Connections -----------------------------------------------------------------

(* KEEP = "true" *)wire	Loop1_Out_EXOR_In1;
(* KEEP = "true" *)wire	Loop2_Out_EXOR_In2;
(* KEEP = "true" *)wire	Loop3_Out_EXOR_In3;
(* KEEP = "true" *)wire	Loop4_Out_EXOR_In4;
(* KEEP = "true" *)wire	Loop5_Out_EXOR_In5;
(* KEEP = "true" *)wire	Noise_Source_In1;
(* KEEP = "true" *)wire	Noise_Source_In2;
(* KEEP = "true" *)wire	Noise_Source_In3;
(* KEEP = "true" *)wire	Noise_Source_In4;
(* KEEP = "true" *)wire	Noise_Source_In5;

//- Instantiation (Extension) ---------------------------------------------------
(* KEEP = "true" *)Extension Ext 
(
	 (* KEEP = "true" *).Extension_In	(Noise_Source_In), 
	 (* KEEP = "true" *).Extension_Out1	(Noise_Source_In1),
	 (* KEEP = "true" *).Extension_Out2	(Noise_Source_In2),
	 (* KEEP = "true" *).Extension_Out3	(Noise_Source_In3),
	 (* KEEP = "true" *).Extension_Out4	(Noise_Source_In4),
	 (* KEEP = "true" *).Extension_Out5	(Noise_Source_In5)
);
//- Instantiation (Noise Source Loop 1) -------------------------------------
(* KEEP = "true" *)Noise_Source_Loop Loop1 
(
	 (* KEEP = "true" *).Noise_Source_Loop_In		(Noise_Source_In1), 
	 (* KEEP = "true" *).Noise_Source_Loop_Out		(Loop1_Out_EXOR_In1)
);
//- Instantiation (Noise Source Loop 2) -------------------------------------
(* KEEP = "true" *)Noise_Source_Loop Loop2 
(
	 (* KEEP = "true" *).Noise_Source_Loop_In		(Noise_Source_In2), 
	 (* KEEP = "true" *).Noise_Source_Loop_Out		(Loop2_Out_EXOR_In2)
);
//- Instantiation (Noise Source Loop 3) -------------------------------------
(* KEEP = "true" *)Noise_Source_Loop Loop3
(
	 (* KEEP = "true" *).Noise_Source_Loop_In		(Noise_Source_In3), 
	 (* KEEP = "true" *).Noise_Source_Loop_Out		(Loop3_Out_EXOR_In3)
);
//- Instantiation (Noise Source Loop 4) -------------------------------------
(* KEEP = "true" *)Noise_Source_Loop Loop4
(
	 (* KEEP = "true" *).Noise_Source_Loop_In		(Noise_Source_In4), 
	 (* KEEP = "true" *).Noise_Source_Loop_Out		(Loop4_Out_EXOR_In4)
);
//- Instantiation (Noise Source Loop 5) -------------------------------------
(* KEEP = "true" *)Noise_Source_Loop Loop5
(
	 (* KEEP = "true" *).Noise_Source_Loop_In		(Noise_Source_In5), 
	 (* KEEP = "true" *).Noise_Source_Loop_Out		(Loop5_Out_EXOR_In5)
);
//- Instantiation (EXOR_Gate) ---------------------------------------------------
(* KEEP = "true" *)EXOR_Gate EXOR1 
(
	 (* KEEP = "true" *).EXOR_Gate_In1				(Loop1_Out_EXOR_In1), 
	 (* KEEP = "true" *).EXOR_Gate_In2				(Loop2_Out_EXOR_In2), 
	 (* KEEP = "true" *).EXOR_Gate_In3				(Loop3_Out_EXOR_In3),
	 (* KEEP = "true" *).EXOR_Gate_In4				(Loop4_Out_EXOR_In4),
	 (* KEEP = "true" *).EXOR_Gate_In5				(Loop5_Out_EXOR_In5),
	 (* KEEP = "true" *).EXOR_Gate_Out				(Noise_Source_Out)
);							
//-------------------------------------------------------------------------------
endmodule

/////////////////////////////// Noise_Sampler /////////////////////////////////
//- Module Declaration ----------------------------------------------------------
module Noise_Sampler
(
	Noise_In,
	Clock_In,
	Sample_Out
);
//- Ports -----------------------------------------------------------------------					
input Noise_In;
input Clock_In;
output Sample_Out;
//- Registers -------------------------------------------------------------------
reg	Sample_Out;
//- Functionality ---------------------------------------------------------------
always@(posedge Clock_In)
	Sample_Out <= Noise_In ? 1 : 0;
//-------------------------------------------------------------------------------
endmodule

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Top Level Module Version 1 TRNG whihc depends on control signal and enable signal, control signal is for user, 
// whenever he wans to output RAW data or hashed data. (Default output is hashed data when enable is ON)
// This module has a conroller state machine which has 6 states, IDLE, COLLECT_HASH, HASH, TRANSMIT_HASH, COLLECT_RAW, TRANSMIT_RAW
module TRNG (
    input TRNG_Enable,          // TRNG outputs random bits till the time this signal is asserted.
    input TRNG_Clock,           // Clock signal (50 MHz) for Tiny Tape out Requiremnts
    input ctrl_mode,            // Control signal: 0 = hashed output, 1 = raw Sample_Out
    output wire failure,        // Indicates if Repetition Count Test failed (if failed, bits discard other wise pass the bits to buffer to store 448 bits)
    output wire UART_Tx,        // UART Transmitted Data
    output wire hash_rdy        // Hash ready signal (For the use if he want to get the value of a hash, he can take it at this signal, when it goes ON, other wise it will generate continous hashed data not just 256 and stops)
);

    // Internal Connections
    wire Noise_Connect;
    wire Sample_Out;
    reg [8:0] bit_counter;   // For counting 448 bits (hash mode)
    reg [2:0] raw_bit_counter; // For counting 8 bits (raw mode)
    reg discard;          // Indicates whether bits are being discarded
    reg [447:0] Word_Out;        // 448-bit collected data (hash mode)
    reg [7:0] raw_byte;          // 8-bit collected data (raw mode)
    reg [511:0] Padded_Out;      // 512-bit padded data for SHA-256 requirment for one block processing
    reg Word_Valid;              // Indicates when Padded_Out is valid means it has 512 bits = ({448 data , 63 Zeros , length in 64 bits})
    reg [4:0] chunk_index;   // Index for selecting 8-bit hash chunks (32 chunks then goes 0 and start over)
    reg [7:0] chunk_reg;         // Register to hold current 8-bit chunk (hash mode)
    wire [255:0] hash;           // Full 256-bit hash output

    // UART TX Signals
    reg uart_start;
//    wire uart_done;
    wire uart_busy;

    // Synchronize ctrl_mode to avoid metastability
    reg [1:0] ctrl_mode_sync;
    reg prev_ctrl_mode;

    // State Machine for Both Modes (HASHED and RAW)
    reg [2:0] state;
    localparam STATE_IDLE          = 3'b000;
    localparam STATE_COLLECT_HASH  = 3'b001;
    localparam STATE_HASH          = 3'b010;
    localparam STATE_TRANSMIT_HASH = 3'b011;
    localparam STATE_COLLECT_RAW   = 3'b100;
    localparam STATE_TRANSMIT_RAW  = 3'b101;

    // Noise Source Instantiation
    Noise_Source NOISE_SOURCE (
        .Noise_Source_In(TRNG_Enable), 
        .Noise_Source_Out(Noise_Connect)
    );

    // Noise Sampler Instantiation
    Noise_Sampler NOISE_SAMPLER (
        .Noise_In(Noise_Connect), 
        .Clock_In(TRNG_Clock), 
        .Sample_Out(Sample_Out)
    );

    // Repetition Count Test Instantiation
    Repetition_Count_Test #(.CUTOFF(32)) Repetition_Count_Test (
        .clk(TRNG_Clock),       // Clock signal
        .rst(!TRNG_Enable),     // Reset signal (active high)
        .bit_in(Sample_Out),    // Input bit from the bitstream
        .failure(failure)       // Failure signal (asserts when test fails)
    );
    
    // SHA256 Module Instantiation
    SHA256 sha256 (
        .M(Padded_Out),
        .start(Word_Valid),
        .clk(TRNG_Clock),
        .HASH(hash),
        .hash_rdy(hash_rdy) 
    );
    
    // UART TX Instantiation
    uart_tx #(
        .TICKS_PER_BIT(435), // for 50 MHz clock it will be 435 with baud rate of 115200
        .TICKS_PER_BIT_SIZE(9)
    ) uart_tx_inst (
        .i_clk(TRNG_Clock),
        .i_start(uart_start),
        .i_data(ctrl_mode_sync[1] ? raw_byte : chunk_reg), // ctrl_mode
        .o_done(),
        .o_busy(uart_busy),
        .o_dout(UART_Tx)
    );

    
    // Synchronize ctrl_mode and detect edges
    always @(posedge TRNG_Clock or negedge TRNG_Enable) begin
        if (!TRNG_Enable) begin
            ctrl_mode_sync <= 2'b00;
            prev_ctrl_mode <= 1'b0;
        end else begin
            ctrl_mode_sync <= {ctrl_mode_sync[0], ctrl_mode}; // 2-stage synchronizer
            prev_ctrl_mode <= ctrl_mode_sync[1]; // Track previous synchronized value
        end
    end

    // State Machine for Both Modes
    always @(posedge TRNG_Clock or negedge TRNG_Enable) begin
        if (!TRNG_Enable) begin
            state <= STATE_IDLE;
            Word_Out <= 448'b0;
            raw_byte <= 8'b0;
            Padded_Out <= 512'b0;
            Word_Valid <= 1'b0;
            bit_counter <= 9'b0;
            raw_bit_counter <= 3'b0;
            discard <= 1'b0;
            chunk_index <= 5'd0;
            uart_start <= 1'b0;
        end else begin
            // Detect mode change and reset state machine
            if (prev_ctrl_mode != ctrl_mode_sync[1]) begin
                state <= STATE_IDLE;
                raw_byte <= 8'b0;
                bit_counter <= 9'b0;
                raw_bit_counter <= 3'b0;
            end

            case (state)
                // Idle: Select mode based on synchronized ctrl_mode
                STATE_IDLE: begin
                    if (ctrl_mode_sync[1] == 0) begin
                        state <= STATE_COLLECT_HASH; // Hash mode
                        bit_counter <= 9'b0;
                        Word_Out <= 448'b0; // Reset collected data
                    end else begin
                        state <= STATE_COLLECT_RAW;  // Raw mode
                        raw_bit_counter <= 3'b0;
                        raw_byte <= 8'b0; // Reset raw byte
                    end
                end

                // Hash Mode: Collect 448 bits
                STATE_COLLECT_HASH: begin
                    if (failure) begin
                        discard <= 1'b1;
                        bit_counter <= 9'b0;
                    end else if (discard) begin
                        discard <= 1'b0;
                    end else begin
                        Word_Out <= {Word_Out[446:0], Sample_Out}; 
                        bit_counter <= bit_counter + 1;

                        if (bit_counter == 9'd447) begin
                            Padded_Out <= {Word_Out[446:0], 1'b1, 64'd448};
                            Word_Valid <= 1'b1; // Start SHA256 hashing
                            state <= STATE_HASH;
                        end else begin
                            Word_Valid <= 1'b0; // Deassert after one cycle
                        end
                    end
                end

                // Hash Mode: Wait for hash computation
                STATE_HASH: begin
                    Word_Valid <= 1'b0; // Ensure Word_Valid is only ON for one cycle
                    if (hash_rdy) begin
                        state <= STATE_TRANSMIT_HASH;
                        chunk_index <= 5'd0;
                    end
                end

                // Hash Mode: Transmit 32-byte hash
                STATE_TRANSMIT_HASH: begin
                    if (!uart_busy && !uart_start) begin
                        if ({1'b0,chunk_index} < 6'd32) begin
                            chunk_reg <= hash[chunk_index*8 +: 8]; // Load 8-bit chunk
                            uart_start <= 1'b1; // Trigger UART transmission
                            chunk_index <= chunk_index + 1;
                        end else begin
                            state <= STATE_COLLECT_HASH; // Repeat collection
                            Word_Out <= 448'b0;
                            bit_counter <= 9'b0;
                        end
                    end else begin
                        uart_start <= 1'b0; // Ensure single-cycle pulse
                    end
                end

                // Raw Mode: Collect 8 bits
                STATE_COLLECT_RAW: begin
                    if (failure) begin
                        discard <= 1'b1;
                        raw_bit_counter <= 3'b0;
                    end else if (discard) begin
                        discard <= 1'b0;
                    end else begin
                        raw_byte <= {raw_byte[6:0], Sample_Out}; // Shift in New bit (Shift register)
                        raw_bit_counter <= raw_bit_counter + 1;

                        if (raw_bit_counter == 3'd7) begin
                            state <= STATE_TRANSMIT_RAW; // Ready to transmit data (wil do this in next state)
                        end
                    end
                end

                // Raw Mode: Transmit 1 byte
                STATE_TRANSMIT_RAW: begin
                    if (!uart_busy && !uart_start) begin
                        uart_start <= 1'b1; // Trigger UART transmission
                        state <= STATE_COLLECT_RAW; // Collect next byte
                        raw_bit_counter <= 3'b0;
                    end else begin
                        uart_start <= 1'b0; // Ensure single-cycle pulse
                    end
                end

                default: state <= STATE_IDLE;
            endcase
        end
    end
endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    10:26:22 06/25/2008 
// Design Name: 
// Module Name:    expansion_test 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module expansion_controller
			(
				M,
				start,
				final_sum,
				count,
				clk,
				w_rdy,
				W,
				address1,
				address2,
				data1_to_ram,
				data2_to_ram,
				write_en1,
				write_en2
			);

input	[511:0]	M;
input			start;
input	[31:0]	final_sum;
input	[4:0]	count;
input			clk;
output			w_rdy;
output	[31:0]	W;
output	[3:0]	address1;
output	[3:0]	address2;
output	[31:0]	data1_to_ram;
output	[31:0]	data2_to_ram;
output			write_en1;
output			write_en2;


reg				w_rdy;
reg		[31:0]	W;
reg		[3:0]	j; 
reg		[3:0]	j_2;
reg		[3:0]	j_7;
reg		[3:0]	j_15;
reg		[3:0]	address1;
reg		[3:0]	address2;
reg		[31:0]	data1_to_ram;
reg		[31:0]	data2_to_ram;
reg				write_en1;
reg				write_en2;
reg		[31:0]	sum;

always @ (posedge clk)	    
begin
	if(start)
	begin
		address1 <= 0;
		address2 <= 0;
		data1_to_ram <= 0;
		data2_to_ram <= 0;
		write_en1 <= 1;
		write_en2 <= 0;
		 sum <= 0;
		j <= 4'b0;
		j_2 <= 4'd14;
		j_7 <= 4'd9;
		j_15 <= 4'd1;
		W <= 0;
		w_rdy <= 1;
	end
	
	else
	begin
		case(count)
		0:	begin
				address1 <= 0;
				address2 <= 0;
				data1_to_ram <= M[511:480];
				data2_to_ram <= 0; 
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <=  M[511:480];
				w_rdy <= 1;
			end
		1:	begin
				address1 <= 1;
				address2 <= 0;
				data1_to_ram <= M[479:448];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <=M[479:448];
				w_rdy <= 1;
			end
		2:	begin
				address1 <= 2;
				address2 <= 0;
				data1_to_ram <= M[447:416];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[447:416];
				w_rdy <= 1;
			end
		3:	begin
				address1 <= 3;
				address2 <=0;
				data1_to_ram <= M[415:384];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[415:384];
				w_rdy <= 1;
			end
		4:	begin
				address1 <= 4;
				address2 <= 0;
				data1_to_ram <= M[383:352];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				  sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[383:352];
				w_rdy <= 1;
			end
		5:	begin
				address1 <= 5;
				address2 <= 0;
				data1_to_ram <=M[351:320] ;
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				  sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[351:320];
				w_rdy <= 1;
			end
		6:	begin
				address1 <= 6;
				address2 <= 0;
				data1_to_ram <= M[319:288];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				  sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[319:288];
				w_rdy <= 1;
			end
		7:	begin
				address1 <= 7;
				address2 <= 0;
				data1_to_ram <= M[287:256];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				  sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[287:256];
				w_rdy <= 1;
			end
		8:	begin
				address1 <= 8;
				address2 <= 0;
				data1_to_ram <=  M[255:224];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				  sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[255:224];
				w_rdy <= 1;
			end	
		9:	begin
				address1 <= 9;
				address2 <= 0;
				data1_to_ram <=M[223:192];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[223:192];
				w_rdy <= 1;
			end	
		10:	begin
				address1 <= 10;
				address2 <= 0;
				data1_to_ram <= M[191:160];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[191:160];
				w_rdy <= 1;
			end			
		11:	begin
				address1 <= 11;
				address2 <= 0;
				data1_to_ram <= M[159:128];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[159:128];
				w_rdy <= 1;
			end	
		12:	begin
				address1 <= 12;
				address2 <= 0;
				data1_to_ram <=M[127:96] ;
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <=M[127:96];
				w_rdy <= 1;
			end		
		13:	begin
				address1 <= 13;
				address2 <= 0;
				data1_to_ram <= M[95:64];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[95:64] ;
				w_rdy <= 1;
			end	
		14:	begin
				address1 <= 14;
				address2 <= 0;
				data1_to_ram <= M[63:32];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <= sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[63:32];
				w_rdy <= 1;
			end	
		15:	begin
				address1 <= 15;
				address2 <= 0;
				data1_to_ram <= M[31:0];
				data2_to_ram <= 0;
				write_en1 <= 1;
				write_en2 <= 0;
				sum <=  sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= M[31:0];
				w_rdy <= 0;
			end	
	
		16:	begin
				address1 <= j_15 ;		//==> 14
				address2 <=j_2  ;		//==> 1
				data1_to_ram <= 0;
				data2_to_ram <= 0;
				write_en1 <= 0;
				write_en2 <= 0;
				sum <= final_sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <=W;
				w_rdy <= 0;
			end
		17:	begin
				address1 <= j;			//==> 0
				address2 <= j_7;		//==> 9		
				data1_to_ram <= 0;
				data2_to_ram <= 0;
				write_en1 <= 0;			
				write_en2 <= 0;
				sum <= final_sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <=W;	
				w_rdy <= 0;
			end
		18:	begin
				address1 <= j;
				address2 <= address2;
				data1_to_ram <= 0;
				data2_to_ram <= 0;
				write_en1 <= 0;  	
				write_en2 <= 0;
				sum <=  final_sum;
				j <= j+1;
				j_2 <= j_2+1;
				j_7 <= j_7+1;
				j_15 <= j_15+1;
				W <= W;
				w_rdy <= 0;
			end
		19:	begin
				address1 <= address1 ;		
				address2 <=address2  ;		
				data1_to_ram <= 0;
				data2_to_ram <= 0;
				write_en1 <= 0;		
				write_en2 <= 0;
				sum <=  final_sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= W;
				w_rdy <= 0;
			end	
		20:	begin
				address1 <= address1 ;		
				address2 <=address2  ;		
				data1_to_ram <= final_sum;
				data2_to_ram <= 0;
				write_en1 <= 1;		
				write_en2 <= 0;
				sum <= final_sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= W;
				w_rdy <= 1;
			end	
		21:	begin
				address1 <= address1 ;		
				address2 <=address2  ;		
				data1_to_ram <= final_sum;
				data2_to_ram <= 0;
				write_en1 <= 0;		
				write_en2 <= 0;
				sum <=  final_sum;
				j <= j;
				j_2 <= j_2;
				j_7 <= j_7;
				j_15 <= j_15;
				W <= sum;
				w_rdy <= 0;
			end
		
		endcase 
	end	
end    
endmodule



`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:34:45 06/03/2008 
// Design Name: 
// Module Name:    sigma_0 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sigma_0(
				xg_0,
				sig_0				
				);

input	[31:0] 	xg_0;
output	[31:0]	sig_0;

assign sig_0 = ( { xg_0[6:0] , xg_0[31:7] } ^ { xg_0[17:0] , xg_0[31:18] } ^ { 3'b0 , xg_0[31:3] } ) ;


endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    15:56:23 06/05/2008 
// Design Name: 
// Module Name:    expantion_control_top 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module expansion
					(
						M,
						start,
						count,
						clk,
						w_rdy,						
						W
					);


input		[511:0]		M;
input					start;
input		[4:0]		count;
input					clk;
output					w_rdy;						
output		[31:0]	 	W;	

 		
wire			[3:0]	  	address1;					
wire			[3:0]    		address2;					
wire			[31:0]    		data1_to_ram;				
wire			[31:0]    		data2_to_ram;	
wire			[31:0]    		dout1;				
wire			[31:0]    		dout2;				
wire				    		write_en1;					
wire				    		write_en2;	
wire			[31:0]		sig_0;
wire			[31:0]		sig_1;
wire			[31:0]		sum_0;
wire			[31:0]		final_sum;


sigma_0 sig0
			(
				.xg_0				(dout1),
				.sig_0				(sig_0)
			);

sigma_1 sig1 
			(
				.xg_1					(dout2), 
				
				.sig_1					(sig_1)
			);

message_schedule msg_schdl
			(
				.addr1					(address1), 
				.addr2					(address2), 
				.din1						(data1_to_ram), 
				.din2					(data2_to_ram), 
				.we1						(write_en1), 
				.we2						(write_en2), 
				.clk						(clk), 
				.dout1					(dout1), 
				.dout2					(dout2)
			);
			
sum0 sm0 
		(
				.sig_0					(sig_0), 
				.sig_1					(sig_1),
				.clk						(clk),	
				.sum_0					(sum_0)
		);
		
finalsum smfn 
		(
				.sum_0					(sum_0),
				.data1_from_ram			(dout1), 
				.data2_from_ram			(dout2), 
				.clk						(clk),	
				.final_sum					(final_sum)
		);


expansion_controller exp_ctrl (
			    .M					(M), 
			    .start					(start), 
			    .final_sum				(final_sum), 
			    .count					(count), 
			    .clk					(clk), 
			    .w_rdy					(w_rdy), 
			    .W					(W), 
			    .address1				(address1), 
			    .address2				(address2), 
			    .data1_to_ram			(data1_to_ram), 
			    .data2_to_ram			(data2_to_ram), 
			    .write_en1				(write_en1), 
			    .write_en2				(write_en2)			    
			    );
endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    13:43:25 06/03/2008 
// Design Name: 
// Module Name:    sigma_1 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sigma_1 (
				xg_1,
				sig_1				
				);

input	[31:0] 	xg_1;
output	[31:0]	sig_1;

assign sig_1 =  ( { xg_1[16:0] , xg_1[31:17] } ^ { xg_1[18:0] , xg_1[31:19] } ^ { 10'b0 , xg_1[31:10] } );


endmodule


//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 01/30/2025 12:12:47 PM
// Design Name: 
// Module Name: uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////

module uart_tx 
	/* BEGIN PARAMETERS LIST */
	#(
		parameter TICKS_PER_BIT = 868,
		parameter TICKS_PER_BIT_SIZE = 10
	)
	/* END PARAMETERS LIST */ 
	
	/* BEGIN MODULE IO LIST */
	(
		input i_clk,
		input i_start,
		input [7:0] i_data,
		output wire o_done,
		output wire o_busy,
		output wire o_dout
	);
	/* END MODULE IO LIST */

	localparam	STATE_IDLE 			= 5'b00001,
				STATE_SEND_START 	= 5'b00010,
				STATE_SEND_BITS		= 5'b00100,
				STATE_SEND_STOP		= 5'b01000,
				STATE_DONE			= 5'b10000;
	
	reg [4:0] currentState, nextState;
	reg done_flag;
	reg busy_flag;
	reg tx_output;
	
	assign o_dout = tx_output;
	assign o_done = done_flag;
	assign o_busy = busy_flag;
	
	reg [7:0] tx_reg;
	reg [3:0] tx_bit_counter;
	reg [TICKS_PER_BIT_SIZE-1:0] ticks_counter;

	wire ticks_counter_ovf 		= (ticks_counter == TICKS_PER_BIT-1);
	wire tx_bit_counter_ovf 	= (tx_bit_counter[3]); // if equals >= 8

	//Init registers for testbench simulation
	initial begin
		currentState = STATE_IDLE;
		tx_reg = 0;
		tx_bit_counter = 0;
		ticks_counter = 0;
	end
	
	always @(*) begin
		case(currentState)

			default: begin 
				nextState = STATE_IDLE;
				done_flag = 0;
				busy_flag = 0;
				tx_output = 1; //idle line
			end

			STATE_IDLE: begin 
				done_flag = 0;
				busy_flag = 0;
				tx_output = 1; //idle line
				
				if(i_start)
					nextState = STATE_SEND_START;
				else
					nextState = STATE_IDLE;
			end // -- END STATE_IDLE --
			
			STATE_SEND_START: begin 
				done_flag = 0;
				busy_flag = 1;
				tx_output = 0; //send low signal (start)
				
				if(ticks_counter_ovf)
					nextState = STATE_SEND_BITS;
				else
					nextState = STATE_SEND_START;
					
			end // -- END STATE_SEND_START --
			
			STATE_SEND_BITS: begin 
				done_flag = 0;
				busy_flag = 1;
				tx_output = tx_bit_counter_ovf ? 1'b1 : tx_reg[0];
				
				if(tx_bit_counter_ovf)
					nextState = STATE_SEND_STOP;
				else
					nextState = STATE_SEND_BITS;
					
			end // -- END STATE_SEND_BITS --
			
			STATE_SEND_STOP: begin 
				done_flag = 0;
				busy_flag = 1;
				tx_output = 1; //send high signal (stop)
				
				if(ticks_counter_ovf)
					nextState = STATE_DONE;
				else
					nextState = STATE_SEND_STOP;
			end // -- END STATE_SEND_STOP --
			
			STATE_DONE: begin 
				done_flag = 1;
				busy_flag = 1;
				tx_output = 1; //idle line
				nextState = STATE_IDLE;
			end // -- END STATE_DONE --
			
		endcase
	end
	
	always @(posedge i_clk) begin 
		currentState <= nextState;

		//Any of those states require the 'ticks_counter_ovf' signal to work
		if (currentState == STATE_SEND_START || 
			currentState == STATE_SEND_BITS || 
			currentState == STATE_SEND_STOP) begin
			
			if(ticks_counter_ovf) begin
				ticks_counter <= 0;
			end	
			else 
				ticks_counter <= ticks_counter + 1;
		end
		
		if (currentState == STATE_SEND_BITS) begin 
			if(ticks_counter_ovf) begin
				tx_bit_counter <= tx_bit_counter + 1;
				tx_reg <= tx_reg >> 1; //LSB shift
			end
		end

		if(currentState == STATE_IDLE) begin 
			if(i_start) begin 
				tx_reg <= i_data;
				tx_bit_counter <= 0;
			end
		end
	end

endmodule 


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    09:19:42 06/09/2008 
// Design Name: 
// Module Name:    finalsum 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module finalsum
		(
			sum_0,
			data1_from_ram,
			data2_from_ram,
			clk,
			final_sum
		);

input	[31:0]	sum_0;
input	[31:0]	data1_from_ram;
input	[31:0]	data2_from_ram;
input			clk;
output	[31:0]	final_sum;


reg	[31:0]	final_sum;


always @ (posedge clk)
 final_sum <= sum_0 + data1_from_ram + data2_from_ram;


endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    08:38:14 06/09/2008 
// Design Name: 
// Module Name:    sum0 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sum0
		(
			sig_0,
			sig_1,
			clk,
			sum_0
		);

input	[31:0]	sig_0;
input	[31:0]	sig_1;
input			clk;
output	[31:0]	sum_0;

reg	[31:0]	sum_0;

always @ (posedge clk)
sum_0 <= ( sig_0 + sig_1) ;


endmodule


`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    14:51:13 06/09/2008 
// Design Name: 
// Module Name:    intermediate_result 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module hash_generator
					(
						t1,
						t2,
						count,
						w_rdy,
						done,
						clk,
						start,
						a,
						b,
						c,
						e,
						f,
						g,
						h,
						hash_rdy,
						HASH
					);
// >>> Module Implementation Begin

// <<< Module Implementation End
endmodule




`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    12:44:54 06/03/2008 
// Design Name: 
// Module Name:    summatin_0 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module summatin_0	(
				x,
				sum				
				);

input	[31:0] 	x;
output	[31:0]	sum;
				
assign sum = ( { x[1:0] , x[31:2] } ^ { x[12:0] , x[31:13] } ^ { x[21:0] , x[31:22] } );


endmodule


Reference solution:
rtl/generated.v: 					

input		[31:0]		t1;
input		[31:0]		t2;
input					w_rdy;
input					clk;
input		[4:0]		count;
input					start;

input					done;

output		[31:0]		a;
output		[31:0]		b;
output		[31:0]		c;
output		[31:0]		e;
output		[31:0]		f;
output		[31:0]		g;
output		[31:0]		h;

output					hash_rdy;
output		[255:0]		HASH;



reg			[31:0]		a;
reg			[31:0]		b;
reg			[31:0]		c;
reg			[31:0]		d;
reg			[31:0]		e;
reg			[31:0]		f;
reg			[31:0]		g;
reg			[31:0]		h;

reg						hash_rdy;
reg			[4:0]		temp;


always @ (posedge clk)
begin
if(! done)
	begin
	temp <= 5'b0;
	end
else
begin
	temp <= temp << 1;
	temp[0] <= done;
	
end
end



always@(posedge clk)
begin
	if(start)
	begin
		a <= 32'h0;
		b <= 32'h0;
		c <= 32'h0;
		d <= 32'h0;
		e <= 32'h0;
		f <= 32'h0;
		g <= 32'h0;
		h <= 32'h0;
		hash_rdy <= 0;
	end
	else if(count == 0)
	begin
		a <= 32'h6a09e667;
		b <= 32'hbb67ae85;
		c <= 32'h3c6ef372;
		d <= 32'ha54ff53a;
		e <= 32'h510e527f;
		f <= 32'h9b05688c;
		g <= 32'h1f83d9ab;
		h <= 32'h5be0cd19;
		hash_rdy <= 0;
	end
	else if (w_rdy==1)
	begin
		h <= g;
		g <= f;
		f <= e;
		e <= d + t1;
		d <= c;
		c <= b;
		b <= a;
		a <= t1 + t2;
		hash_rdy <= 0;
	end
	else if (temp[4])
	begin
		a <= a + 32'h6a09e667;
		b <= b + 32'hbb67ae85;
		c <= c + 32'h3c6ef372;
		d <= d + 32'ha54ff53a;
		e <= e + 32'h510e527f;
		f <= f + 32'h9b05688c;
		g <= g + 32'h1f83d9ab;
		h <= h + 32'h5be0cd19;
		hash_rdy <= 1;
	end
end

assign	HASH = {a,b,c,d,e,f,g,h};