dakies/OSS_Verilog huggingface dataset:
module CM_FIFO_1x (
	rst,

	push_clk,
	push,
	din,
	full,
	push_flag,
	overflow,

	pop_clk,
	pop,
	dout,
	empty,
	pop_flag,
	
	CM_FIFO_1x_din_o			,		
	CM_FIFO_1x_push_int_o		,
	CM_FIFO_1x_pop_int_o		,
	CM_FIFO_1x_push_clk_o		,
	CM_FIFO_1x_pop_clk_o		,
	CM_FIFO_1x_rst_o			,
	                           
	CM_FIFO_1x_almost_full_i	,
	CM_FIFO_1x_almost_empty_i	,
	CM_FIFO_1x_push_flag_i		,
	CM_FIFO_1x_pop_flag_i		,
	CM_FIFO_1x_dout_i			
	
	
);

input			rst;

input			push_clk;
input			push;
input	[17:0]	din;
output			full;
output	[3:0]	push_flag;
output			overflow;

input			pop_clk;
input			pop;
output	[8:0]	dout;
output			empty;
output	[3:0]	pop_flag;

output 	[17:0]	CM_FIFO_1x_din_o			;
output 			CM_FIFO_1x_push_int_o		;
output 			CM_FIFO_1x_pop_int_o		;
output 			CM_FIFO_1x_push_clk_o		;
output 			CM_FIFO_1x_pop_clk_o		;
output 			CM_FIFO_1x_rst_o			;

input 			CM_FIFO_1x_almost_full_i	;
input 			CM_FIFO_1x_almost_empty_i	;
input 	[3:0]	CM_FIFO_1x_push_flag_i		;
input 	[3:0]	CM_FIFO_1x_pop_flag_i		;
input 	[8:0]	CM_FIFO_1x_dout_i			;



reg				overflow;


wire			push_int;
wire			pop_int;
reg				pop_r1, pop_r2, pop_r3;


// over-run/under-run protection
assign push_int = full ? 1'b0 : push;

// changed to match the current S2 functionality
//assign pop_int = empty ? 1'b0 : pop;
assign pop_int = empty ? 1'b0 : (pop_r2 ^ pop_r3);


assign CM_FIFO_1x_din_o 		= din;
assign CM_FIFO_1x_push_int_o 	= push_int;
assign CM_FIFO_1x_pop_int_o 	= pop_int;
assign CM_FIFO_1x_push_clk_o 	= push_clk;
assign CM_FIFO_1x_pop_clk_o 	= pop_clk;
assign CM_FIFO_1x_rst_o 		= rst;
assign almost_full 				= CM_FIFO_1x_almost_full_i;
assign almost_empty 			= CM_FIFO_1x_almost_empty_i;
assign push_flag 				= CM_FIFO_1x_push_flag_i;
assign pop_flag 				= CM_FIFO_1x_pop_flag_i;
assign dout 					= CM_FIFO_1x_dout_i;




assign full = (push_flag == 4'h0);
assign empty = (pop_flag == 4'h0);


// overflow detection
always @(posedge push_clk or posedge rst)
	if (rst)
		overflow <= 0;
	else
		if (push && full)
			overflow <= 1;
		else
			overflow <= 0;

/// Synchronize SPI FIFO Read to SPI CLock due to delay
always @(posedge pop_clk or posedge rst)
	if (rst) begin
		pop_r1 <= 1'b0;
		pop_r2 <= 1'b0;
		pop_r3 <= 1'b0;
	end
	else begin
		pop_r1 <= pop;
		pop_r2 <= pop_r1;
		pop_r3 <= pop_r2;
	end


endmodule
module SMMemory (
    // General Interface
    input         ResetIn,
	input		  SMBusyIn,
    
    //Read Interface
    input   [9:0] ReadAddressIn,
    output [17:0] ReadDataOut,
    input         ReadSelectIn,
    input         ReadClockIn,
    
    //Write Interface
    input   [9:0] WriteAddressIn,
    input   [8:0] WriteDataIn,
    input         WriteSelectIn,

    input   [9:0] WriteAddressIn_TLC,
    input   [8:0] WriteDataIn_TLC,
    input         WriteSelectIn_TLC,

    input         WriteClockIn,
	
	output 	[9:0]	SMMemory_WriteAddressIn_TLC_o,
	output 	[8:0]	SMMemory_ReadAddressIn_o,
	output 			SMMemory_WriteSelectIn_TLC_o,
	output 			SMMemory_ReadSelect_RAM0_o,
	output 			SMMemory_WriteClockIn_o,
	output 			SMMemory_ReadClockIn_o,
	output  [8:0]	SMMemory_WriteDataIn_TLC_o,
	input  	[17:0]	SMMemory_ReadDataOut_SRAM_i,
	output 	[9:0]	SMMemory_WriteAddressIn_o,
	output 		    SMMemory_WriteSelectIn_o,
	output 			SMMemory_ReadSelect_RAM1_o,
	output 			SMMemory_WriteDataIn_o,
	input  	[17:0]	SMMemory_ReadDataOut_SRAM1_i
	
	

	
    );

	// Define local variables
	//
	wire   [17:0] ReadDataOut_SRAM;
	wire   [17:0] ReadDataOut_SRAM_1;

	reg				ReadDataSel;
	wire			ReadSelect_RAM0;
	wire			ReadSelect_RAM1;
	wire			SMMemoryBankSelect;


	// generate individual read enables
	assign ReadSelect_RAM0 = ReadSelectIn && !ReadAddressIn[9];
	assign ReadSelect_RAM1 = ReadSelectIn && ReadAddressIn[9];


	// Mux the read data
	always @(posedge ReadClockIn)
		ReadDataSel <= ReadAddressIn[9];

	assign SMMemoryBankSelect = SMBusyIn ? ReadAddressIn[9] : ReadDataSel;
	assign ReadDataOut = SMMemoryBankSelect ? ReadDataOut_SRAM_1: ReadDataOut_SRAM;


	// Instantiate the Memory Blocks
	//
	assign SMMemory_WriteAddressIn_TLC_o = WriteAddressIn_TLC;
	assign SMMemory_ReadAddressIn_o[8:0] = ReadAddressIn[8:0];
	assign SMMemory_WriteSelectIn_TLC_o  = WriteSelectIn_TLC;
	assign SMMemory_ReadSelect_RAM0_o    = ReadSelect_RAM0;
	assign SMMemory_WriteClockIn_o       = WriteClockIn;
	assign SMMemory_ReadClockIn_o        = ReadClockIn;
	assign SMMemory_WriteDataIn_TLC_o    = WriteDataIn_TLC;
	assign ReadDataOut_SRAM   		     = SMMemory_ReadDataOut_SRAM_i;
	
	assign SMMemory_WriteAddressIn_o     = WriteAddressIn;
	assign SMMemory_WriteSelectIn_o      = WriteSelectIn;
	assign SMMemory_ReadSelect_RAM1_o    = ReadSelect_RAM1;
	assign SMMemory_WriteDataIn_o         = WriteDataIn;
	assign ReadDataOut_SRAM1   		     = SMMemory_ReadDataOut_SRAM1_i;

endmodule
module dff_pre_clr (
	input	CLK,
	input	CLR,
	input	D,
	input	PRE,
	output	Q
);

dffpc dffpc_0 ( .CLK(CLK) , .CLR(CLR), .D(D), .PRE(PRE), .Q(Q) )/* synthesis black_box */;
//pragma attribute dffpc_0 dont_touch true

endmodule
module clock_buffer (
	input	A,
	output	Z
);



GCLKBUFF gclkbuff_0 (.A(A), .Z(Z));
//pragma attribute gclkbuff_0 ql_pack 1
//pragma attribute gclkbuff_0 hierarchy preserve

endmodule
module ck_buff ( A , Q )/* synthesis black_box black_box_pad_pin = "A" */;
input A/* synthesis syn_isclock=1 */;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* ck buff */
module GCLKBUFF ( A , Z )/* synthesis black_box */;
input A;
output Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* gclk buff */
module in_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* in buff */
module out_buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /* out buff */
module inv ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*inverter*/
module buff ( A , Q )/* synthesis black_box */;
input A;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*buffer*/
module mux2x0 ( A , B, S, Q )/* synthesis black_box */;
input A, B, S;
output Q;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*mux2x0*/
module LOGIC_Cell (T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3, 
            TB0S, Q0DI, CD0S, Q0EN, QST, QRT, QCK, QCKS, C0Z, Q0Z, B0Z)/* synthesis black_box */;
input T0I0, T0I1, T0I2, T0I3, B0I0, B0I1, B0I2, B0I3;
input TB0S, Q0DI, CD0S, Q0EN;				  
input QST, QRT, QCK, QCKS;
output C0Z, B0Z, Q0Z;
//pragma synthesis_off
//pragma synthesis_on
endmodule /*LOGIC_Cell*/
module io_tc1 (mux_in, demux_out,mux_sel, demux_sel);
input [0:511] mux_in;
input [8:0]mux_sel; 
input [8:0]demux_sel;
output [511:0]demux_out;

mux_512x1 mux0 (.in(mux_in),.sel(mux_sel),.out(mux_out));
demux_1x512 demux0 (.in(mux_out),.sel(demux_sel),.out(demux_out));

endmodule
module mux_512x1 (in,sel,out);
input [511:0] in;
input [8:0]sel;
output out;
wire out0_w, out1_w;

mux_256x1 m512_0(.in(in[255:0]),.sel(sel[7:0]),.out(out0_w));
mux_256x1 m512_1(.in(in[511:256]),.sel(sel[7:0]),.out(out1_w));
mux_2x1 m512_2(.a(out0_w),.b(out1_w),.sel(sel[8]),.out(out));

endmodule
module mux_256x1 (in,sel,out);
input [255:0] in;
input [7:0]sel;
output out;
wire out0_w, out1_w;

mux_128x1 m256_0(.in(in[127:0]),.sel(sel[6:0]),.out(out0_w));
mux_128x1 m256_1(.in(in[255:128]),.sel(sel[6:0]),.out(out1_w));
mux_2x1 m256_2(.a(out0_w),.b(out1_w),.sel(sel[7]),.out(out));

endmodule
module mux_128x1 (in,sel,out);
input [127:0] in;
input [6:0]sel;
output out;
wire out0_w, out1_w;

mux_64x1 m128_0(.in(in[63:0]),.sel(sel[5:0]),.out(out0_w));
mux_64x1 m128_1(.in(in[127:64]),.sel(sel[5:0]),.out(out1_w));
mux_2x1 m128_2(.a(out0_w),.b(out1_w),.sel(sel[6]),.out(out));

endmodule
module mux_64x1 (in,sel,out);
input [63:0] in;
input [5:0]sel;
output out;
wire out0_w, out1_w;

mux_32x1 m64_0(.in(in[31:0]),.sel(sel[4:0]),.out(out0_w));
mux_32x1 m64_1(.in(in[63:32]),.sel(sel[4:0]),.out(out1_w));
mux_2x1 m64_2(.a(out0_w),.b(out1_w),.sel(sel[5]),.out(out));

endmodule
module mux_32x1 (in,sel,out);
input [31:0] in;
input [4:0]sel;
output out;
wire out0_w, out1_w;

mux_16x1 m32_0(.in(in[15:0]),.sel(sel[3:0]),.out(out0_w));
mux_16x1 m32_1(.in(in[31:16]),.sel(sel[3:0]),.out(out1_w));
mux_2x1 m32_2(.a(out0_w),.b(out1_w),.sel(sel[4]),.out(out));

endmodule
module mux_16x1 (in,sel,out);
input [15:0] in;
input [3:0]sel;
output out;
wire out0_w, out1_w;

mux_8x1 m16_0(.in(in[7:0]),.sel(sel[2:0]),.out(out0_w));
mux_8x1 m16_1(.in(in[15:8]),.sel(sel[2:0]),.out(out1_w));
mux_2x1 m16_2(.a(out0_w),.b(out1_w),.sel(sel[3]),.out(out));

endmodule
module mux_8x1 (in,sel,out);
input [7:0] in;
input [2:0]sel;
output out;
wire out0_w, out1_w;

mux_4x1 m8_0(.in(in[3:0]),.sel(sel[1:0]),.out(out0_w));
mux_4x1 m8_1(.in(in[7:4]),.sel(sel[1:0]),.out(out1_w));
mux_2x1 m8_2(.a(out0_w),.b(out1_w),.sel(sel[2]),.out(out));

endmodule
module mux_4x1 (in,sel,out);
input [3:0] in;
input [1:0]sel;
output out;
wire out0_w, out1_w;

mux_2x1 m4_0(.a(in[0]),.b(in[1]),.sel(sel[0]),.out(out0_w));
mux_2x1 m4_1(.a(in[2]),.b(in[3]),.sel(sel[0]),.out(out1_w));
mux_2x1 m4_2(.a(out0_w),.b(out1_w),.sel(sel[1]),.out(out));

endmodule
module mux_2x1 (a,b,sel,out);
input a,b;
input sel;
output out;

assign out = sel ? b : a;

endmodule
module demux_1x512 (in,sel,out);
input in;
input [8:0] sel;
output [511:0] out;
wire [1:0] out_w;

demux_1x2 d512_0(.in(in),.sel(sel[8]),.out(out_w[1:0]));
demux_1x256 d512_1(.in(out_w[0]),.sel(sel[7:0]),.out(out[255:0]));
demux_1x256 d512_2(.in(out_w[1]),.sel(sel[7:0]),.out(out[511:256]));

endmodule
module demux_1x256 (in,sel,out);
input in;
input [7:0] sel;
output [255:0] out;
wire [1:0] out_w;

demux_1x2 d256_0(.in(in),.sel(sel[7]),.out(out_w[1:0]));
demux_1x128 d256_1(.in(out_w[0]),.sel(sel[6:0]),.out(out[127:0]));
demux_1x128 d256_2(.in(out_w[1]),.sel(sel[6:0]),.out(out[255:128]));

endmodule
module demux_1x128 (in,sel,out);
input in;
input [6:0] sel;
output [127:0] out;
wire [1:0] out_w;

demux_1x2 d128_0(.in(in),.sel(sel[6]),.out(out_w[1:0]));
demux_1x64 d128_1(.in(out_w[0]),.sel(sel[5:0]),.out(out[63:0]));
demux_1x64 d128_2(.in(out_w[1]),.sel(sel[5:0]),.out(out[127:64]));

endmodule
module demux_1x64 (in,sel,out);
input in;
input [5:0] sel;
output [63:0] out;
wire [1:0] out_w;

demux_1x2 d64_0(.in(in),.sel(sel[5]),.out(out_w[1:0]));
demux_1x32 d64_1(.in(out_w[0]),.sel(sel[4:0]),.out(out[31:0]));
demux_1x32 d64_2(.in(out_w[1]),.sel(sel[4:0]),.out(out[63:32]));

endmodule
module demux_1x32 (in,sel,out);
input in;
input [4:0] sel;
output [31:0] out;
wire [1:0] out_w;

demux_1x2 d32_0(.in(in),.sel(sel[4]),.out(out_w[1:0]));
demux_1x16 d32_1(.in(out_w[0]),.sel(sel[3:0]),.out(out[15:0]));
demux_1x16 d32_2(.in(out_w[1]),.sel(sel[3:0]),.out(out[31:16]));

endmodule
module demux_1x16 (in,sel,out);
input in;
input [3:0] sel;
output [15:0] out;
wire [1:0] out_w;

demux_1x2 d16_0(.in(in),.sel(sel[3]),.out(out_w[1:0]));
demux_1x8 d16_1(.in(out_w[0]),.sel(sel[2:0]),.out(out[7:0]));
demux_1x8 d16_2(.in(out_w[1]),.sel(sel[2:0]),.out(out[15:8]));

endmodule
module demux_1x8 (in,sel,out);
input in;
input [2:0] sel;
output [7:0] out;
wire [1:0] out_w;

demux_1x2 d8_0(.in(in),.sel(sel[2]),.out(out_w[1:0]));
demux_1x4 d8_1(.in(out_w[0]),.sel(sel[1:0]),.out(out[3:0]));
demux_1x4 d8_2(.in(out_w[1]),.sel(sel[1:0]),.out(out[7:4]));

endmodule
module demux_1x4 (in,sel,out);
input in;
input [1:0] sel;
output [3:0] out;
wire [1:0]out_w;

demux_1x2 d4_0(.in(in),.sel(sel[1]),.out(out_w));
demux_1x2 d4_1(.in(out_w[0]),.sel(sel[0]),.out(out[1:0]));
demux_1x2 d4_2(.in(out_w[1]),.sel(sel[0]),.out(out[3:2]));


endmodule
module demux_1x2 (in,sel,out);
input in,sel;
output [1:0] out;

assign out[0] = (sel==0) ? in :0;
assign out[1] = (sel==1) ? in :0;

endmodule
module shift_reg_8192 #( parameter size = 8191 ) (shift_in, clk, shift_out);

   // Port Declaration
   input   shift_in;
   input   clk;
   output  shift_out;
   
   reg [ size:0 ] shift; // shift register  
   
    always @ (posedge clk)
     begin
	  shift = { shift[size-1:0] , shift_in } ;	
     end
   
   assign shift_out = shift[size];   
   
endmodule
module  multi_enc_decx2x4(
    // Inputs
    clock,
    datain,
    datain1,
    datain1_0,
    datain_0,
    reset,
    // Outputs
    dataout,
    dataout1,
    dataout1_0,
    dataout_0
);

//--------------------------------------------------------------------
// Input
//--------------------------------------------------------------------
input          clock;
input  [127:0] datain;
input  [127:0] datain1;
input  [127:0] datain1_0;
input  [127:0] datain_0;
input          reset;
//--------------------------------------------------------------------
// Output
//--------------------------------------------------------------------
output [127:0] dataout;
output [127:0] dataout1;
output [127:0] dataout1_0;
output [127:0] dataout_0;
//--------------------------------------------------------------------
// Nets
//--------------------------------------------------------------------
wire           clock;
wire   [127:0] datain;
wire   [127:0] datain1;
wire   [127:0] datain1_0;
wire   [127:0] datain_0;
wire   [127:0] dataout_net_0;
wire   [127:0] dataout1_net_0;
wire   [127:0] dataout1_0_net_0;
wire   [127:0] dataout_0_net_0;
wire           reset;
wire   [127:0] top_0_dataout;
wire   [127:0] top_1_dataout1;
wire   [127:0] dataout_net_1;
wire   [127:0] dataout1_net_1;
wire   [127:0] dataout1_0_net_1;
wire   [127:0] dataout_0_net_1;
//--------------------------------------------------------------------
// Top level output port assignments
//--------------------------------------------------------------------
assign dataout_net_1     = dataout_net_0;
assign dataout[127:0]    = dataout_net_1;
assign dataout1_net_1    = dataout1_net_0;
assign dataout1[127:0]   = dataout1_net_1;
assign dataout1_0_net_1  = dataout1_0_net_0;
assign dataout1_0[127:0] = dataout1_0_net_1;
assign dataout_0_net_1   = dataout_0_net_0;
assign dataout_0[127:0]  = dataout_0_net_1;
//--------------------------------------------------------------------
// Component instances
//--------------------------------------------------------------------
//--------top
top top_0(
        // Inputs
        .clock    ( clock ),
        .reset    ( reset ),
        .datain   ( datain ),
        .datain1  ( datain1 ),
        // Outputs
        .dataout  ( top_0_dataout ),
        .dataout1 ( dataout1_0_net_0 ) 
        );

//--------top
top top_1(
        // Inputs
        .clock    ( clock ),
        .reset    ( reset ),
        .datain   ( datain_0 ),
        .datain1  ( datain1_0 ),
        // Outputs
        .dataout  ( dataout_0_net_0 ),
        .dataout1 ( top_1_dataout1 ) 
        );

//--------top
top top_2(
        // Inputs
        .clock    ( clock ),
        .reset    ( reset ),
        .datain   ( top_0_dataout ),
        .datain1  ( top_1_dataout1 ),
        // Outputs
        .dataout  ( dataout_net_0 ),
        .dataout1 ( dataout1_net_0 ) 
        );


endmodule
module top(clock,reset,datain,dataout,datain1,dataout1);


input clock,reset;

input [127:0] datain;
output [127:0] dataout;
                          
input [127:0] datain1;   
output [127:0] dataout1; 
                          
wire [6:0] enc_out;
reg  [127:0] data_encin;
reg  [6:0] data_encout;

wire [6:0] enc_out1;
reg  [127:0] data_encin1;
reg  [6:0] data_encout1;





encoder128 U01(.datain(data_encin),.dataout(enc_out));
decoder128 U02(.datain(data_encout),.dataout(dataout));

encoder128 U011(.datain(data_encin1),.dataout(enc_out1));
decoder128 U021(.datain(data_encout1),.dataout(dataout1));



	always @(posedge clock)
		
		begin
		
			if (reset)
			
				data_encin <= 127'h00000;
				
			else
			
				data_encin <= datain;
				
				
		end
		
		
	always @(posedge clock)
		
		begin
		
			if (reset)
			
				data_encout <= 7'h0;
				
			else
			
				data_encout<= enc_out;
				
				
		end
			
			
			
		always @(posedge clock)
		
		begin
		
			if (reset)
			
				data_encin1 <= 127'h00000;
				
			else
			
				data_encin1 <= datain1;
				
				
		end
		
		
	always @(posedge clock)
		
		begin
		
			if (reset)
			
				data_encout1 <= 7'h0;
				
			else
			
				data_encout1<= enc_out1;
				
				
		end		
			
			
			
			
			
			
			
endmodule
module unsigned_mult_80 (out, a, b);
output [40:0] out;
wire [80:0] mult_wire;
	input  [40:0] a;
	input  [40:0] b;

	assign mult_wire = a * b;
    assign out = mult_wire[80:40] | mult_wire[39:0];

endmodule
module top_module_test;

	// Inputs
	reg clk;
	reg data_in;
	reg [1:0] data_rdy;

	// Outputs
	wire cipher_out;
	
	// Plaintext and key from the NSA Simon and Speck paper
	reg [127:0] plaintext = 128'h63736564207372656c6c657661727420;
	reg [127:0] key = 128'h0f0e0d0c0b0a09080706050403020100;
	
	integer i;

	// Instantiate the Unit Under Test (UUT)
	top_module uut (
		.clk(clk), 
		.data_in(data_in), 
		.data_rdy(data_rdy), 
		.cipher_out(cipher_out)
	);

	initial begin
		// Initialize Inputs
		clk = 0;
		data_in = 0;
		data_rdy = 0;

		#110;
		#5;
		//Set data_rdy=1 to load plaintext
		data_rdy=1;
		
		//Loads the plaintext one bit per clock cycle for 128 cycles
		for(i=0;i<128;i = i+1)
		begin
			data_in = plaintext[i];
			#20;
		end
		
		//Set data_rdy=2 to load key
		data_rdy = 2;
			
		//Loads the key one bit per clock cycle for 128 cycles
		for(i=0;i<128;i = i+1)
		begin
			data_in = key[i];
			#20;
		end
		//Set data_rdy=0 after loading is done
		data_rdy = 0;
		#20;
		
		//Keep data_rdy=3 while the cipher is running
		data_rdy = 3;


	end
	

	
	always #10 clk = ~clk;
        

      
endmodule
module top_module(clk,data_in,data_rdy,cipher_out);

input clk,data_in;
input [1:0] data_rdy;
output cipher_out;

wire key;
wire [5:0] bit_counter;
wire round_counter_out;

/*
	data_rdy=0 -> Reset, Idle
	data_rdy=1 -> Load Plaintext
	data_rdy=2 -> Load Key
	data_rdy=3 -> Run (keep at 3 while the block cipher is running)
*/

simon_datapath_shiftreg datapath(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_in(key), 
								 . cipher_out(cipher_out), .round_counter(round_counter_out), .bit_counter(bit_counter));
											
simon_key_expansion_shiftreg key_exp(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_out(key), .bit_counter(bit_counter), 
									 .round_counter_out(round_counter_out));


endmodule
module Simon_bit_serial_top(clk,data_in,data_rdy,cipher_out);

input clk,data_in;
input [1:0] data_rdy;
output cipher_out;

wire key;
wire [5:0] bit_counter;
wire round_counter_out;

/*
	data_rdy=0 -> Reset, Idle
	data_rdy=1 -> Load Plaintext
	data_rdy=2 -> Load Key
	data_rdy=3 -> Run (keep at 3 while the block cipher is running)
*/

simon_datapath_shiftreg datapath(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_in(key), 
								 . cipher_out(cipher_out), .round_counter(round_counter_out), .bit_counter(bit_counter));
											
simon_key_expansion_shiftreg key_exp(.clk(clk), .data_in(data_in), .data_rdy(data_rdy), .key_out(key), .bit_counter(bit_counter), 
									 .round_counter_out(round_counter_out));


endmodule
module sd_crc_7(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
   input        BITVAL;                            // Next input bit
   input        ENABLE;                            // Enable calculation
   input        BITSTRB;                           // Current bit valid (Clock)
   input        CLEAR;                             // Init CRC value
   output [6:0] CRC;                               // Current output CRC value

   reg    [6:0] CRC;                               // We need output registers
   wire         inv;
   
   assign inv = BITVAL ^ CRC[6];                   // XOR required?
   
   always @(posedge BITSTRB or posedge CLEAR) begin
      if (CLEAR) begin
         CRC <= 0;                                  // Init before calculation
         end
      else begin
         if (ENABLE == 1) begin
             CRC[6] <= CRC[5];
             CRC[5] <= CRC[4];
             CRC[4] <= CRC[3];
             CRC[3] <= CRC[2] ^ inv;
             CRC[2] <= CRC[1];
             CRC[1] <= CRC[0];
             CRC[0] <= inv;
             end
         end
      end
   
endmodule
module bistable_domain_cross(
    rst,
    clk_a,
    in,
    clk_b,
    out
);
parameter width = 1;
input rst;
input clk_a;
input [width-1:0] in;
input clk_b;
output [width-1:0] out;

// We use a two-stages shift-register to synchronize in to the clk_b clock domain
reg [width-1:0] sync_clk_b [1:0];
always @(posedge clk_b or posedge rst)
begin
    if (rst == 1) begin
        sync_clk_b[0] <= 0;
        sync_clk_b[1] <= 0;
    end else begin
        sync_clk_b[0] <= in;
        sync_clk_b[1] <= sync_clk_b[0];
    end
end

assign out = sync_clk_b[1];  // new signal synchronized to (=ready to be used in) clk_b domain

endmodule
module edge_detect (
    input rst,
    input clk, 
    input sig,
    output rise,
    output fall
);

reg [1:0] sig_reg;

always @(posedge clk or posedge rst)
    if (rst == 1'b1)
        sig_reg <= 2'b00;
    else
        sig_reg <= {sig_reg[0], sig};

assign rise = sig_reg[0] == 1'b1 && sig_reg[1] == 1'b0 ? 1'b1 : 1'b0;
assign fall = sig_reg[0] == 1'b0 && sig_reg[1] == 1'b1 ? 1'b1 : 1'b0;

endmodule
module sd_fifo_filler(
           input wb_clk,
           input rst,
           //WB Signals
           output [31:0] wbm_adr_o,
           output wbm_we_o,
           output [31:0] wbm_dat_o,
           input [31:0] wbm_dat_i,
           output wbm_cyc_o,
           output wbm_stb_o,
           input wbm_ack_i,
           //Data Master Control signals
           input en_rx_i,
           input en_tx_i,
           input [31:0] adr_i,
           //Data Serial signals
           input sd_clk,
           input [31:0] dat_i,
           output [31:0] dat_o,
           input wr_i,
           input rd_i,
           output sd_full_o,
           output sd_empty_o,
           output wb_full_o,
           output wb_empty_o
       );

`define FIFO_MEM_ADR_SIZE 4
`define MEM_OFFSET 4

wire reset_fifo;
wire fifo_rd;
reg [31:0] offset;
reg fifo_rd_ack;
reg fifo_rd_reg;

assign fifo_rd = wbm_cyc_o & wbm_ack_i;
assign reset_fifo = !en_rx_i & !en_tx_i;

assign wbm_we_o = en_rx_i & !wb_empty_o;
assign wbm_cyc_o = en_rx_i ? en_rx_i & !wb_empty_o : en_tx_i & !wb_full_o;
assign wbm_stb_o = en_rx_i ? wbm_cyc_o & fifo_rd_ack : wbm_cyc_o;

generic_fifo_dc_gray #(
    .dw(32), 
    .aw(`FIFO_MEM_ADR_SIZE)
    ) generic_fifo_dc_gray0 (
    .rd_clk(wb_clk),
    .wr_clk(sd_clk), 
    .rst(!(rst | reset_fifo)), 
    .clr(1'b0), 
    .din(dat_i), 
    .we(wr_i),
    .dout(wbm_dat_o), 
    .re(en_rx_i & wbm_cyc_o & wbm_ack_i), 
    .full(sd_full_o), 
    .empty(wb_empty_o), 
    .wr_level(), 
    .rd_level() 
    );
    
generic_fifo_dc_gray #(
    .dw(32), 
    .aw(`FIFO_MEM_ADR_SIZE)
    ) generic_fifo_dc_gray1 (
    .rd_clk(sd_clk),
    .wr_clk(wb_clk), 
    .rst(!(rst | reset_fifo)), 
    .clr(1'b0), 
    .din(wbm_dat_i), 
    .we(en_tx_i & wbm_cyc_o & wbm_stb_o & wbm_ack_i),
    .dout(dat_o), 
    .re(rd_i), 
    .full(wb_full_o), 
    .empty(sd_empty_o), 
    .wr_level(), 
    .rd_level() 
    );

assign wbm_adr_o = adr_i+offset;

always @(posedge wb_clk or posedge rst)
    if (rst) begin
        offset <= 0;
        fifo_rd_reg <= 0;
        fifo_rd_ack <= 1;
    end
    else begin
        fifo_rd_reg <= fifo_rd;
        fifo_rd_ack <= fifo_rd_reg | !fifo_rd;
        if (wbm_cyc_o & wbm_stb_o & wbm_ack_i)
            offset <= offset + `MEM_OFFSET;
        else if (reset_fifo)
            offset <= 0;
    end

endmodule
module sd_clock_divider (
           input CLK,
           input [7:0] DIVIDER,
           input RST,
           output SD_CLK
       );

reg [7:0] ClockDiv;
reg SD_CLK_O;

//assign SD_CLK = DIVIDER[7] ? CLK : SD_CLK_O;
assign SD_CLK = SD_CLK_O;

always @(posedge CLK or posedge RST)
begin
    if (RST) begin
        ClockDiv <= 8'b0000_0000;
        SD_CLK_O <= 0;
    end
    else if (ClockDiv == DIVIDER) begin
        ClockDiv <= 0;
        SD_CLK_O <= ~SD_CLK_O;
    end else begin
        ClockDiv <= ClockDiv + 8'h1;
        SD_CLK_O <= SD_CLK_O;
    end
end

endmodule
module monostable_domain_cross(
    input rst,
    input clk_a,
    input in, 
    input clk_b,
    output out
);

// this changes level when the in is seen in clk_a
reg toggle_clk_a;
always @(posedge clk_a or posedge rst)
begin
    if (rst)
        toggle_clk_a <= 0;
    else
        toggle_clk_a <= toggle_clk_a ^ in;
end

// which can then be sync-ed to clk_b
reg [2:0] sync_clk_b;
always @(posedge clk_b or posedge rst)
begin
    if (rst)
        sync_clk_b <= 0;
    else
        sync_clk_b <= {sync_clk_b[1:0], toggle_clk_a};
end

// and recreate the flag in clk_b
assign out = (sync_clk_b[2] ^ sync_clk_b[1]);

endmodule
module sd_crc_16(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
   input        BITVAL;                            // Next input bit
   input        ENABLE;                            // Enable calculation
   input        BITSTRB;                           // Current bit valid (Clock)
   input        CLEAR;                             // Init CRC value
   output [15:0] CRC;                               // Current output CRC value

   reg    [15:0] CRC;                               // We need output registers
   wire         inv;
   
   assign inv = BITVAL ^ CRC[15];                   // XOR required?
   
   always @(posedge BITSTRB or posedge CLEAR) begin
      if (CLEAR) begin
         CRC <= 0;                                  // Init before calculation
         end
      else begin
         if (ENABLE == 1) begin
             CRC[15] <= CRC[14];
             CRC[14] <= CRC[13];
             CRC[13] <= CRC[12];
             CRC[12] <= CRC[11] ^ inv;
             CRC[11] <= CRC[10];
             CRC[10] <= CRC[9];
             CRC[9] <= CRC[8];
             CRC[8] <= CRC[7];
             CRC[7] <= CRC[6];
             CRC[6] <= CRC[5];
             CRC[5] <= CRC[4] ^ inv;
             CRC[4] <= CRC[3];
             CRC[3] <= CRC[2];
             CRC[2] <= CRC[1];
             CRC[1] <= CRC[0];
             CRC[0] <= inv;
             end
         end
      end
   
endmodule
module sd_data_xfer_trig (
           input sd_clk,
           input rst,
           input cmd_with_data_start_i,
           input r_w_i,
           input [`INT_CMD_SIZE-1:0] cmd_int_status_i,
           output reg start_tx_o,
           output reg start_rx_o
       );

reg r_w_reg;
parameter SIZE = 2;
reg [SIZE-1:0] state;
reg [SIZE-1:0] next_state;
parameter IDLE             = 2'b00;
parameter WAIT_FOR_CMD_INT = 2'b01;
parameter TRIGGER_XFER     = 2'b10;

always @(state or cmd_with_data_start_i or r_w_i or cmd_int_status_i)
begin: FSM_COMBO
    case(state)
        IDLE: begin
            if (cmd_with_data_start_i & r_w_i)
                next_state <= TRIGGER_XFER;
            else if (cmd_with_data_start_i)
                next_state <= WAIT_FOR_CMD_INT;
            else
                next_state <= IDLE;
        end
        WAIT_FOR_CMD_INT: begin
            if (cmd_int_status_i[`INT_CMD_CC])
                next_state <= TRIGGER_XFER;
            else if (cmd_int_status_i[`INT_CMD_EI])
                next_state <= IDLE;
            else
                next_state <= WAIT_FOR_CMD_INT;
        end
        TRIGGER_XFER: begin
            next_state <= IDLE;
        end
        default: next_state <= IDLE;
    endcase
end

always @(posedge sd_clk or posedge rst)
begin: FSM_SEQ
    if (rst) begin
        state <= IDLE;
    end
    else begin
        state <= next_state;
    end
end

always @(posedge sd_clk or posedge rst)
begin
    if (rst) begin
        start_tx_o <= 0;
        start_rx_o <= 0;
        r_w_reg <= 0;
    end
    else begin
        case(state)
            IDLE: begin
                start_tx_o <= 0;
                start_rx_o <= 0;
                r_w_reg <= r_w_i;
            end
            WAIT_FOR_CMD_INT: begin
                start_tx_o <= 0;
                start_rx_o <= 0;
            end
            TRIGGER_XFER: begin
                start_tx_o <= ~r_w_reg;
                start_rx_o <= r_w_reg;
            end
        endcase
    end
end

endmodule
module cavlc_len_gen
(
    cavlc_state,
    len_read_total_coeffs_comb,
    len_read_levels_comb,
    len_read_total_zeros_comb,
    len_read_run_befores_comb,
    len_comb
);
//------------------------
// ports
//------------------------
input  [7:0] cavlc_state;
input  [4:0] len_read_total_coeffs_comb;
input  [4:0] len_read_levels_comb;
input  [3:0] len_read_total_zeros_comb;
input  [3:0] len_read_run_befores_comb;

output [4:0] len_comb;

//------------------------
// regs
//------------------------
reg [4:0] len_comb;         //number of bits comsumed by cavlc in a cycle

//------------------------
// len_comb
//------------------------
always @ (*)
case (1'b1) //synthesis parallel_case
    cavlc_state[`cavlc_read_total_coeffs_bit]  : len_comb <= len_read_total_coeffs_comb;
    cavlc_state[`cavlc_read_t1s_flags_bit],  
    cavlc_state[`cavlc_read_level_prefix_bit],
    cavlc_state[`cavlc_read_level_suffix_bit]  : len_comb <= len_read_levels_comb;       
    cavlc_state[`cavlc_read_total_zeros_bit]   : len_comb <= len_read_total_zeros_comb;
    cavlc_state[`cavlc_read_run_befores_bit]   : len_comb <= len_read_run_befores_comb;
    cavlc_state[`cavlc_calc_level_bit],
    cavlc_state[`cavlc_idle_bit]               : len_comb <= 0;
    default                                    : len_comb <= 'bx;
endcase

endmodule
module cavlc_fsm
(
    clk,
    rst_n,
    ena,
    start,
    max_coeff_num,
    TotalCoeff,
    TotalCoeff_comb,
    TrailingOnes,
    TrailingOnes_comb,
    ZeroLeft,
    state,
    i,
    idle,
    valid
);
//------------------------
//ports
//------------------------
input  clk;
input  rst_n;
input  ena;
input  start;

input  [4:0]  max_coeff_num;
input  [4:0]  TotalCoeff;
input  [4:0]  TotalCoeff_comb;
input  [1:0]  TrailingOnes;
input  [1:0]  TrailingOnes_comb;
input  [3:0]  ZeroLeft;

output [7:0]  state;
output [3:0]  i;
output idle;
output valid;

//------------------------
//FFs
//------------------------
reg  [7:0]  state;
reg  [3:0]  i;
reg  valid;

//------------------------
//state & i & valid
//------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
    state   <= `cavlc_idle_s;
    i <= 0;
    valid <= 0;
end
else if (ena)
case(state)
    `cavlc_idle_s : begin
        if (start) begin
            state <= `cavlc_read_total_coeffs_s;
            valid <= 0;
        end
        else begin
            state <= `cavlc_idle_s;
        end     
    end
    `cavlc_read_total_coeffs_s : begin
        i <= TotalCoeff_comb -1;
        if (TrailingOnes_comb > 0 && TotalCoeff_comb > 0)
            state <= `cavlc_read_t1s_flags_s;
        else if (TotalCoeff_comb > 0)
            state <= `cavlc_read_level_prefix_s;
        else begin
            state <= `cavlc_idle_s;     
            valid <= 1;
        end
    end
    `cavlc_read_t1s_flags_s : begin
        if (TrailingOnes == TotalCoeff)
            state <= `cavlc_read_total_zeros_s;         
        else begin
            state <= `cavlc_read_level_prefix_s;
            i <= i - TrailingOnes;
        end
    end
    `cavlc_read_level_prefix_s : begin
        state <= `cavlc_read_level_suffix_s;        
    end
    `cavlc_read_level_suffix_s : begin
        state <= `cavlc_calc_level_s;       
    end
    `cavlc_calc_level_s : begin
        if ( i == 0  && TotalCoeff < max_coeff_num)
            state <= `cavlc_read_total_zeros_s;
        else if (i == 0) begin
            state <= `cavlc_read_run_befores_s;
            i <= TotalCoeff - 1;
        end
        else begin
            state <= `cavlc_read_level_prefix_s;
            i <= i - 1;
        end
    end 
    `cavlc_read_total_zeros_s : begin
        state <= `cavlc_read_run_befores_s;
        i <= TotalCoeff - 1;
    end
    `cavlc_read_run_befores_s : begin
        if (i == 0 || ZeroLeft == 0) begin
            state <= `cavlc_idle_s;
            valid <= 1;
        end
        else begin
            state <= `cavlc_read_run_befores_s;
            i <= i - 1;
        end
    end     
endcase

assign idle = state[`cavlc_idle_bit];

endmodule
module des3(desOut, desIn, key1, key2, key3, decrypt, clk); 
output	[63:0]	desOut;
input	[63:0]	desIn;
input	[55:0]	key1;
input	[55:0]	key2;
input	[55:0]	key3;
input		decrypt;
input		clk;

wire	[55:0]	key_a;
wire	[55:0]	key_b;
wire	[55:0]	key_c;
wire	[63:0]	stage1_out, stage2_out;
reg	[55:0]	key_b_r [16:0];
reg	[55:0]	key_c_r [33:0];
integer		i;

assign key_a = decrypt ? key3 : key1;
assign key_b = key2;
assign key_c = decrypt ? key1 : key3;

always @(posedge clk)
	key_b_r[0] <= #1 key_b;

always @(posedge clk)
	for(i=0;i<16;i=i+1)
		key_b_r[i+1] <= #1 key_b_r[i];


always @(posedge clk)
	key_c_r[0] <= #1 key_c;

always @(posedge clk)
	for(i=0;i<33;i=i+1)
		key_c_r[i+1] <= #1 key_c_r[i];

des u0(	.desOut(stage1_out),	.desIn(desIn),		.key(key_a), .decrypt(decrypt), .clk(clk) );

des u1(	.desOut(stage2_out),	.desIn(stage1_out),	.key(key_b_r[16]), .decrypt(!decrypt), .clk(clk) );

des u2(	.desOut(desOut),	.desIn(stage2_out),	.key(key_c_r[33]), .decrypt(decrypt),	.clk(clk) );

endmodule
module aes_rcon(clk, kld, out);
input		clk;
input		kld;
output	[31:0]	out;
reg	[31:0]	out;
reg	[3:0]	rcnt;
wire	[3:0]	rcnt_next;

always @(posedge clk)
	if(kld)		out <= #1 32'h01_00_00_00;
	else		out <= #1 frcon(rcnt_next);

assign rcnt_next = rcnt + 4'h1;
always @(posedge clk)
	if(kld)		rcnt <= #1 4'h0;
	else		rcnt <= #1 rcnt_next;

function [31:0]	frcon;
input	[3:0]	i;
case(i)	// synopsys parallel_case
   4'h0: frcon=32'h01_00_00_00;
   4'h1: frcon=32'h02_00_00_00;
   4'h2: frcon=32'h04_00_00_00;
   4'h3: frcon=32'h08_00_00_00;
   4'h4: frcon=32'h10_00_00_00;
   4'h5: frcon=32'h20_00_00_00;
   4'h6: frcon=32'h40_00_00_00;
   4'h7: frcon=32'h80_00_00_00;
   4'h8: frcon=32'h1b_00_00_00;
   4'h9: frcon=32'h36_00_00_00;
   default: frcon=32'h00_00_00_00;
endcase
endfunction

endmodule
module usbf_crc5(crc_in, din, crc_out);
input	[4:0]	crc_in;
input	[10:0]	din;
output	[4:0]	crc_out;

assign crc_out[0] =	din[10] ^ din[9] ^ din[6] ^ din[5] ^ din[3] ^
			din[0] ^ crc_in[0] ^ crc_in[3] ^ crc_in[4];

assign crc_out[1] =	din[10] ^ din[7] ^ din[6] ^ din[4] ^ din[1] ^
			crc_in[0] ^ crc_in[1] ^ crc_in[4];

assign crc_out[2] =	din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[6] ^
			din[3] ^ din[2] ^ din[0] ^ crc_in[0] ^ crc_in[1] ^
			crc_in[2] ^ crc_in[3] ^ crc_in[4];

assign crc_out[3] =	din[10] ^ din[9] ^ din[8] ^ din[7] ^ din[4] ^ din[3] ^
			din[1] ^ crc_in[1] ^ crc_in[2] ^ crc_in[3] ^ crc_in[4];

assign crc_out[4] =	din[10] ^ din[9] ^ din[8] ^ din[5] ^ din[4] ^ din[2] ^
			crc_in[2] ^ crc_in[3] ^ crc_in[4];

endmodule
module usbf_ep_rf_dummy(
		clk, wclk, rst,

		// Wishbone Interface
		adr, re, we, din, dout, inta, intb,
		dma_req, dma_ack,

		// Internal Interface

		idin,
		ep_sel, ep_match,
		buf0_rl, buf0_set, buf1_set,
		uc_bsel_set, uc_dpd_set,

		int_buf1_set, int_buf0_set, int_upid_set,
		int_crc16_set, int_to_set, int_seqerr_set,
		out_to_small,

		csr, buf0, buf1, dma_in_buf_sz1, dma_out_buf_avail
		);

input		clk, wclk, rst;
input	[1:0]	adr;
input		re;
input		we;
input	[31:0]	din;
output	[31:0]	dout;
output		inta, intb;
output		dma_req;
input		dma_ack;

input	[31:0]	idin;		// Data Input
input	[3:0]	ep_sel;		// Endpoint Number Input
output		ep_match;	// Asserted to indicate a ep no is matched
input		buf0_rl;	// Reload Buf 0 with original values

input		buf0_set;	// Write to buf 0
input		buf1_set;	// Write to buf 1
input		uc_bsel_set;	// Write to the uc_bsel field
input		uc_dpd_set;	// Write to the uc_dpd field
input		int_buf1_set;	// Set buf1 full/empty interrupt
input		int_buf0_set;	// Set buf0 full/empty interrupt
input		int_upid_set;	// Set unsupported PID interrupt
input		int_crc16_set;	// Set CRC16 error interrupt
input		int_to_set;	// Set time out interrupt
input		int_seqerr_set;	// Set PID sequence error interrupt
input		out_to_small;	// OUT packet was to small for DMA operation

output	[31:0]	csr;		// Internal CSR Output
output	[31:0]	buf0;		// Internal Buf 0 Output
output	[31:0]	buf1;		// Internal Buf 1 Output
output		dma_in_buf_sz1;	// Indicates that the DMA IN buffer has 1 max_pl_sz
				// packet available
output		dma_out_buf_avail;// Indicates that there is space for at least
				// one MAX_PL_SZ packet in the buffer

///////////////////////////////////////////////////////////////////
//
// Internal Access
//

assign	dout = 32'h0;
assign	inta = 1'b0;
assign	intb = 1'b0;
assign	dma_req = 1'b0;
assign	ep_match = 1'b0;
assign	csr = 32'h0;
assign	buf0 = 32'hffff_ffff;
assign	buf1 = 32'hffff_ffff;
assign	dma_in_buf_sz1 = 1'b0;
assign	dma_out_buf_avail = 1'b0;

endmodule
module usbf_utmi_if( // UTMI Interface (EXTERNAL)
		phy_clk, rst,
		DataOut, TxValid, TxReady,
		RxValid, RxActive, RxError, DataIn,
		XcvSelect, TermSel, SuspendM, LineState,
		OpMode, usb_vbus,

		// Internal Interface
		rx_data, rx_valid, rx_active, rx_err,
		tx_data, tx_valid, tx_valid_last, tx_ready,
		tx_first,

		// Misc Interfaces
		mode_hs, usb_reset, usb_suspend, usb_attached,
		resume_req, suspend_clr
		);

input		phy_clk;
//input		wclk;
input		rst;

output	[7:0]	DataOut;
output		TxValid;
input		TxReady;

input	[7:0]	DataIn;
input		RxValid;
input		RxActive;
input		RxError;

output		XcvSelect;
output		TermSel;
output		SuspendM;
input	[1:0]	LineState;
output	[1:0]	OpMode;
input		usb_vbus;

output	[7:0]	rx_data;
output		rx_valid, rx_active, rx_err;
input	[7:0]	tx_data;
input		tx_valid;
input		tx_valid_last;
output		tx_ready;
input		tx_first;

output		mode_hs;	// High Speed Mode
output		usb_reset;	// USB Reset
output		usb_suspend;	// USB Suspend
output		usb_attached;	// Attached to USB
input		resume_req;

output		suspend_clr;

///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//
reg	[7:0]	rx_data;
reg		rx_valid, rx_active, rx_err;
reg	[7:0]	DataOut;
reg		tx_ready;
reg		TxValid;
wire		drive_k;
reg		drive_k_r;

///////////////////////////////////////////////////////////////////
//
// Misc Logic
//


///////////////////////////////////////////////////////////////////
//
// RX Interface Input registers
//

`ifdef USBF_ASYNC_RESET
always @(posedge phy_clk or negedge rst)
`else
always @(posedge phy_clk)
`endif
	if(!rst)	rx_valid <= 1'b0;
	else		rx_valid <= RxValid;

`ifdef USBF_ASYNC_RESET
always @(posedge phy_clk or negedge rst)
`else
always @(posedge phy_clk)
`endif
	if(!rst)	rx_active <= 1'b0;
	else		rx_active <= RxActive;

`ifdef USBF_ASYNC_RESET
always @(posedge phy_clk or negedge rst)
`else
always @(posedge phy_clk)
`endif
	if(!rst)	rx_err <= 1'b0;
	else		rx_err <= RxError;

always @(posedge phy_clk)
		rx_data <= DataIn;

///////////////////////////////////////////////////////////////////
//
// TX Interface Output/Input registers
//

always @(posedge phy_clk)
	if(TxReady || tx_first)	DataOut <= tx_data;
	else
	if(drive_k)		DataOut <= 8'h00;

always @(posedge phy_clk)
	tx_ready <= TxReady;

always @(posedge phy_clk)
	drive_k_r <= drive_k;


`ifdef USBF_ASYNC_RESET
always @(posedge phy_clk or negedge rst)
`else
always @(posedge phy_clk)
`endif
	if(!rst)	TxValid <= 1'b0;
	else
	TxValid <= tx_valid | drive_k | tx_valid_last | (TxValid & !(TxReady | drive_k_r));

///////////////////////////////////////////////////////////////////
//
// Line Status Signaling & Speed Negotiation Block
//

usbf_utmi_ls	u0(
		.clk(		phy_clk		),
		.rst(		rst		),
		.resume_req(	resume_req	),
		.rx_active(	rx_active	),
		.tx_ready(	tx_ready	),
		.drive_k(	drive_k		),
		.XcvSelect(	XcvSelect	),
		.TermSel(	TermSel		),
		.SuspendM(	SuspendM	),
		.LineState(	LineState	),
		.OpMode(	OpMode		),
		.usb_vbus(	usb_vbus	),
		.mode_hs(	mode_hs		),
		.usb_reset(	usb_reset	),
		.usb_suspend(	usb_suspend	),
		.usb_attached(	usb_attached	),
		.suspend_clr(	suspend_clr	)
		);

endmodule
module usbf_crc16(crc_in, din, crc_out);
input	[15:0]	crc_in;
input	[7:0]	din;
output	[15:0]	crc_out;

assign crc_out[0] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^
			din[2] ^ din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9] ^
			crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^
			crc_in[14] ^ crc_in[15];
assign crc_out[1] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^
			din[1] ^ crc_in[9] ^ crc_in[10] ^ crc_in[11] ^
			crc_in[12] ^ crc_in[13] ^ crc_in[14] ^ crc_in[15];
assign crc_out[2] =	din[1] ^ din[0] ^ crc_in[8] ^ crc_in[9];
assign crc_out[3] =	din[2] ^ din[1] ^ crc_in[9] ^ crc_in[10];
assign crc_out[4] =	din[3] ^ din[2] ^ crc_in[10] ^ crc_in[11];
assign crc_out[5] =	din[4] ^ din[3] ^ crc_in[11] ^ crc_in[12];
assign crc_out[6] =	din[5] ^ din[4] ^ crc_in[12] ^ crc_in[13];
assign crc_out[7] =	din[6] ^ din[5] ^ crc_in[13] ^ crc_in[14];
assign crc_out[8] =	din[7] ^ din[6] ^ crc_in[0] ^ crc_in[14] ^ crc_in[15];
assign crc_out[9] =	din[7] ^ crc_in[1] ^ crc_in[15];
assign crc_out[10] =	crc_in[2];
assign crc_out[11] =	crc_in[3];
assign crc_out[12] =	crc_in[4];
assign crc_out[13] =	crc_in[5];
assign crc_out[14] =	crc_in[6];
assign crc_out[15] =	din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[2] ^
			din[1] ^ din[0] ^ crc_in[7] ^ crc_in[8] ^ crc_in[9] ^
			crc_in[10] ^ crc_in[11] ^ crc_in[12] ^ crc_in[13] ^
			crc_in[14] ^ crc_in[15];

endmodule
module usbf_mem_arb(	phy_clk, wclk, rst,

		// SSRAM Interface
		sram_adr, sram_din, sram_dout, sram_re, sram_we,

		// IDMA Memory Interface
		madr, mdout, mdin, mwe, mreq, mack,

		// WISHBONE Memory Interface
		wadr, wdout, wdin, wwe, wreq, wack

		);

parameter	SSRAM_HADR = 14;

input		phy_clk, wclk, rst;

output	[SSRAM_HADR:0]	sram_adr;
input	[31:0]	sram_din;
output	[31:0]	sram_dout;
output		sram_re, sram_we;

input	[SSRAM_HADR:0]	madr;
output	[31:0]	mdout;
input	[31:0]	mdin;
input		mwe;
input		mreq;
output		mack;

input	[SSRAM_HADR:0]	wadr;
output	[31:0]	wdout;
input	[31:0]	wdin;
input		wwe;
input		wreq;
output		wack;

///////////////////////////////////////////////////////////////////
//
// Local Wires and Registers
//

wire		wsel;
reg	[SSRAM_HADR:0]	sram_adr;
reg	[31:0]	sram_dout;
reg		sram_we;
wire		mack;
wire		mcyc;
reg		wack_r;

///////////////////////////////////////////////////////////////////
//
// Memory Arbiter Logic
//

// IDMA has always first priority

// -----------------------------------------
// Ctrl Signals

assign wsel = (wreq | wack) & !mreq;

// -----------------------------------------
// SSRAM Specific
// Data Path
always @(wsel or wdin or mdin)
	if(wsel)	sram_dout = wdin;
	else		sram_dout = mdin;

// Address Path
always @(wsel or wadr or madr)
	if(wsel)	sram_adr = wadr;
	else		sram_adr = madr;

// Write Enable Path
always @(wsel or wwe or wreq or mwe or mcyc)
	if(wsel)	sram_we = wreq & wwe;
	else		sram_we = mwe & mcyc;

assign sram_re = 1'b1;

// -----------------------------------------
// IDMA specific

assign mdout = sram_din;

assign mack = mreq;

assign mcyc = mack;	// Qualifier for writes

// -----------------------------------------
// WISHBONE specific
assign wdout = sram_din;

assign wack = wack_r & !mreq;

`ifdef USBF_ASYNC_RESET
always @(posedge phy_clk or negedge rst)
`else
always @(posedge phy_clk)
`endif
	if(!rst)	wack_r <= 1'b0;
	else		wack_r <= wreq & !mreq & !wack;

endmodule
module keysched(clk,reset,start_i,round_i,last_key_i,new_key_o,ready_o,sbox_access_o,sbox_data_o,sbox_data_i,sbox_decrypt_o);
input clk;
input reset;
input start_i;
input [3:0] round_i;
input [127:0] last_key_i;
output [127:0] new_key_o;
output ready_o;
output sbox_access_o;
output [7:0] sbox_data_o;
input [7:0] sbox_data_i;
output sbox_decrypt_o;

reg [127:0] new_key_o;
reg ready_o;
reg sbox_access_o;
reg [7:0] sbox_data_o;
reg sbox_decrypt_o;

reg [2:0] next_state;
reg [2:0] state;
reg [7:0] rcon_o;
reg [31:0] next_col;
reg [31:0] col;
reg [127:0] key_reg;
reg [127:0] next_key_reg;
reg next_ready_o;


//rcon:
always @(  round_i)

begin

	
	case(round_i)
	1:
begin
rcon_o = (1);
end
	2:
begin
rcon_o = (2);
end
	3:
begin
rcon_o = (4);
end
	4:
begin
rcon_o = (8);
end
	5:
begin
rcon_o = ('h10);
end
	6:
begin
rcon_o = ('h20);
end
	7:
begin
rcon_o = ('h40);
end
	8:
begin
rcon_o = ('h80);
end
	9:
begin
rcon_o = ('h1B);
end
	10:
begin
rcon_o = ('h36);
end
default:
begin
			rcon_o = (0);
end
	endcase


end
//registers:
always @(posedge clk or negedge reset)

begin

	if(!reset)
	begin
		state = (0);
		col = (0);
		key_reg = (0);
		ready_o = (0);
	end
else
	begin
		state = (next_state);	
		col = (next_col);
		key_reg = (next_key_reg);
		ready_o = (next_ready_o);
	end


end
//generate_key:
reg[127:0] K_var,W_var;
	reg[31:0] col_t;
	reg[23:0] zero;
	
always @(  start_i or   last_key_i or   sbox_data_i or   state or   rcon_o or   col or   key_reg)

begin

	
	zero=0;
	
	col_t=col;
	W_var=0;
	
	next_state = (state);
	next_col = (col);
	
	next_ready_o = (0);
	next_key_reg = (key_reg);
	new_key_o = (key_reg);
	
sbox_decrypt_o = (0);
	sbox_access_o = (0);
	sbox_data_o = (0);
	K_var=last_key_i;
		
	case(state)
	//Substitutethebyteswhilerotatingthem
		//FouraccessestoSBoxareneeded
		0:
begin
		if(start_i)
begin
	
			col_t=0;
		sbox_access_o = (1);
			sbox_data_o = (K_var[31:24]);
			next_state = (1);
		
end

		end
	1:
begin
		sbox_access_o = (1);
	sbox_data_o = (K_var[23:16]);
	col_t[7:0]=sbox_data_i;
	next_col = (col_t);
		next_state = (2);
	end
	2:
begin
		sbox_access_o = (1);
	sbox_data_o = (K_var[15:8]);
	col_t[31:24]=sbox_data_i;
	next_col = (col_t);
		next_state = (3);
	end
	3:
begin
		sbox_access_o = (1);
	sbox_data_o = (K_var[7:0]);	
	col_t[23:16]=sbox_data_i;
	next_col = (col_t);
	next_state = (4);
	end
	4:
begin
		sbox_access_o = (1);
		col_t[15:8]=sbox_data_i;
	next_col = (col_t);
		W_var[127:96]=col_t^K_var[127:96]^{rcon_o,zero};		
	W_var[95:64]=W_var[127:96]^K_var[95:64];
	W_var[63:32]=W_var[95:64]^K_var[63:32];
	W_var[31:0]=W_var[63:32]^K_var[31:0];
next_ready_o = (1);
next_key_reg = (W_var);	
	next_state = (0);
		end

default:
begin
		next_state = (0);
	end
endcase


end

endmodule
module mixcolum(clk,reset,decrypt_i,start_i,data_i,ready_o,data_o);
input clk;
input reset;
input decrypt_i;
input start_i;
input [127:0] data_i;
output ready_o;
output [127:0] data_o;

reg ready_o;
reg [127:0] data_o;

reg [127:0] data_reg;
reg [127:0] next_data_reg;
reg [127:0] data_o_reg;
reg [127:0] next_data_o;
reg next_ready_o;
reg [1:0] state;
reg [1:0] next_state;
wire [31:0] outx;

wire [31:0] outy;

reg [31:0] mix_word;
reg [31:0] outmux;

word_mixcolum w1 (.in(mix_word), .outx(outx), .outy(outy));

//assign_data_o:
always @(  data_o_reg)

begin

	data_o = (data_o_reg);

end
//mux:
always @(  outx or   outy or decrypt_i)

begin

	outmux = (decrypt_i?outy:outx);

end
//registers:
always @(posedge clk or negedge reset)

begin

if(!reset)
	begin
		data_reg = (0);
		state = (0);
		ready_o = (0);
		data_o_reg = (0);
	end
else			  
	begin
		data_reg = (next_data_reg);
		state = (next_state);
		ready_o = (next_ready_o);
		data_o_reg = (next_data_o);
	end


end
//mixcol:
reg[127:0] data_i_var;
	reg[31:0] aux;
	reg[127:0] data_reg_var;

always @(  decrypt_i or   start_i or   state or   data_reg or   outmux or   data_o_reg or data_i)

begin

	
	data_i_var=data_i;
	data_reg_var=data_reg;
	next_data_reg = (data_reg);
	next_state = (state);
	
	mix_word = (0);
	
	next_ready_o = (0);
	next_data_o = (data_o_reg);
		
	case(state)
	
		0:
begin
			if(start_i)
begin

			aux=data_i_var[127:96];
		mix_word = (aux);
			data_reg_var[127:96]=outmux;
			next_data_reg = (data_reg_var);
			next_state = (1);
			
end

			end
		1:
begin
			aux=data_i_var[95:64];
			mix_word = (aux);
		data_reg_var[95:64]=outmux;
			next_data_reg = (data_reg_var);
			next_state = (2);
			end
		2:
begin
			aux=data_i_var[63:32];
			mix_word = (aux);
		data_reg_var[63:32]=outmux;
			next_data_reg = (data_reg_var);
			next_state = (3);
			end
	3:
begin
			aux=data_i_var[31:0];
			mix_word = (aux);
			data_reg_var[31:0]=outmux;
		next_data_o = (data_reg_var);
			next_ready_o = (1);
			next_state = (0);
			end	
		default:
			begin
			end
	endcase
			

end

endmodule
module byte_mixcolum(a,b,c,d,outx,outy);

input [7:0] a,b,c,d;
output [7:0] outx, outy;

reg [7:0] outx, outy;

function [7:0] xtime;
input [7:0] in;
reg [3:0] xtime_t;

begin
xtime[7:5] = in[6:4];
xtime_t[3] = in[7];
xtime_t[2] = in[7];
xtime_t[1] = 0;
xtime_t[0] = in[7];
xtime[4:1] =xtime_t^in[3:0];
xtime[0] = in[7];
end
endfunction

reg [7:0] w1,w2,w3,w4,w5,w6,w7,w8,outx_var;
always @ (a, b, c, d)
begin
w1 = a ^b;
w2 = a ^c;
w3 = c ^d;
w4 = xtime(w1);
w5 = xtime(w3);
w6 = w2 ^w4 ^w5;
w7 = xtime(w6);
w8 = xtime(w7);

outx_var = b^w3^w4;
outx=outx_var;
outy=w8^outx_var;

end

endmodule