Create yonga_lz4_decoder_controller.v
diff --git a/verilog/rtl/yonga_lz4_decoder_controller.v b/verilog/rtl/yonga_lz4_decoder_controller.v
new file mode 100644
index 0000000..5531177
--- /dev/null
+++ b/verilog/rtl/yonga_lz4_decoder_controller.v
@@ -0,0 +1,415 @@
+`timescale 1ns / 1ps
+// =====================================================================================  
+// (C) COPYRIGHT 2016 YongaTek (Yonga Technology Microelectronics)
+// All rights reserved.
+// This file contains confidential and proprietary information of YongaTek and 
+// is protected under international copyright and other intellectual property laws.
+// =====================================================================================
+// Project           : lz4_decompress
+// File ID           : %%
+// Design Unit Name  : yonga_lz4_decoder_controller.v
+// Description       : 
+// Comments          :
+// Revision          : %%
+// Last Changed Date : %%
+// Last Changed By   : 
+// Designer
+//          Name     : Bahadir TÜRKOGLU
+//          E-mail   : bahadir.turkoglu@yongatek.com          
+// =====================================================================================
+
+
+module yonga_lz4_decoder_controller(
+	input wire          clk,
+	input wire          rstn,
+	
+	input wire          i_lz4_decompress_enable,         
+    input wire          lz4_decompress_start,
+	
+	output reg          o_read_ram_en,
+	input  wire[7:0]    i_read_ram_data,  
+	output reg[6:0]     o_read_ram_address,
+	
+	output reg          o_write_ram_en,
+	output reg[6:0]     o_write_ram_address,  
+	output reg[7:0]     o_write_ram_data,
+	
+	input  wire         i_fifo1_empty,
+	output reg          o_fifo1_read,  
+	input  wire[7:0]    i_fifo1_compressed_data,
+	
+	input  wire         i_fifo2_full,
+	input  wire         i_fifo2_almst_full,  
+	output reg          o_fifo2_write,
+	output reg[7:0]     o_fifo2_decompress_data,
+	
+	output reg          o_idle
+    );
+	
+	
+////--------------- internal variables ---------------------------------------------------------			
+			
+			reg  [1:0]     block_size_byte;			
+			reg	 [30:0]    block_size_parameter;
+				 
+			reg	 [16:0]    literal_length_parameter;		
+				 	
+			reg	 [16:0]    match_length_parameter;
+			reg	           match_length_overflow;			
+			reg	 	       offset_byte;		
+			reg	 [15:0]    offset_parameter;	
+			
+			reg	[6:0]      write_ram_address_int;
+            reg	[6:0]      write_ram_address_ptr;
+            reg [6:0]      read_ram_address_int;
+			reg [15:0]     offset_count;
+			
+			reg            read_ram_int;         
+			reg            ram_read_request;     
+			reg            last_data_read_ram;   
+			reg            last_data_write_ram;  
+			
+			reg [1:0]      end_of_block_byte;
+			reg [7:0]      write_ram_data_int;
+			
+			reg            write_ram_en_int;  
+			reg            fifo1_read_int;    
+			reg            fifo1_read_request;
+			reg            read_fifo_enable;  
+			
+			reg[3:0] lz4_decompress_state;
+			
+/*             parameter idle = 10'b0000000001, block_size_assign = 10'b0000000010, block_uncompressed = 10'b0000000100, token_assign = 10'b0000001000, 
+                      literal_length_optional = 10'b0000010000, literals_assign = 10'b0000100000, offset_assing = 10'b0001000000,
+					  match_length_optional = 10'b0010000000, literals_copy = 10'b0100000000, end_of_block = 10'b1000000000; */
+					  
+            parameter idle = 1, block_size_assign = 2, block_uncompressed = 3, token_assign = 4, 
+                      literal_length_optional = 5, literals_assign = 6, offset_assing = 7,
+					  match_length_optional = 8, literals_copy = 9, end_of_block = 10;
+//// ------------------------------------------------------------------------------------------------	
+
+
+//// Control for read fifo
+	always @(i_fifo1_empty,read_fifo_enable)
+		begin
+			if(i_fifo1_empty == 1'b0 && read_fifo_enable == 1'b1)
+				fifo1_read_int    = 1'b1;
+			else
+				fifo1_read_int    = 1'b0;		
+		end
+
+	always @ (lz4_decompress_state,offset_byte,match_length_overflow,i_fifo1_compressed_data,end_of_block_byte,
+			  fifo1_read_request,i_fifo2_almst_full,last_data_write_ram)
+		begin
+			if(offset_byte == 1'b1  && match_length_overflow ==  1'b0 & fifo1_read_request == 1'b1)
+				read_fifo_enable = 1'b0;		
+			else if(lz4_decompress_state == token_assign  &&  i_fifo1_compressed_data[7:4] != 4'b1111  && i_fifo2_almst_full == 1'b1)
+				read_fifo_enable = 1'b0;
+			else if(lz4_decompress_state == literal_length_optional  &&  i_fifo1_compressed_data[7:0] != 8'b11111111  && i_fifo2_almst_full == 1'b1) 
+				read_fifo_enable = 1'b0;
+			else if(lz4_decompress_state == literals_assign  && i_fifo2_almst_full == 1'b1)
+				read_fifo_enable = 1'b0;	
+			else if(lz4_decompress_state == match_length_optional  &&  i_fifo1_compressed_data[7:0] != 4'b1111 )
+				read_fifo_enable = 1'b0;
+			else if(lz4_decompress_state == literals_copy  && last_data_write_ram == 1'b0)
+				read_fifo_enable = 1'b0;
+			else if(end_of_block_byte == 2'b11  && fifo1_read_request == 1'b1)
+				read_fifo_enable = 1'b0;
+			else
+				read_fifo_enable = 1'b1;
+        end
+//// --------------------------------------------------------------------------------------------------
+
+//// Connect internal regs to ouput ports
+	always @ (write_ram_data_int,write_ram_en_int,read_ram_address_int,read_ram_int,fifo1_read_int)
+		begin
+			o_fifo2_decompress_data = write_ram_data_int;
+			o_fifo2_write           = write_ram_en_int;
+			
+			o_write_ram_en          = write_ram_en_int;
+			o_write_ram_data        = write_ram_data_int;
+			
+			o_read_ram_address      = read_ram_address_int;
+			o_read_ram_en           = read_ram_int;
+			
+			o_fifo1_read            = fifo1_read_int;
+		end
+//// --------------------------------------------------------------------------------------------------
+
+//// LZ4 Decompress State Machine
+	always @(posedge clk)
+		begin
+			if(rstn == 1'b0)
+				begin
+					o_idle                   <= 1'b1;
+				    last_data_write_ram      <= 1'b0;
+				    match_length_overflow    <= 1'b0;
+                    offset_byte              <= 1'b0;
+                    read_ram_int             <= 1'b0;
+                    ram_read_request         <= 1'b0;
+                    last_data_read_ram       <= 1'b0;
+                    block_size_byte          <= 0;
+                    block_size_parameter     <= 0;
+                    literal_length_parameter <= 0;
+                    match_length_parameter   <= 0;
+                    offset_parameter         <= 0;
+                    write_ram_address_int    <= 0;
+                    write_ram_address_ptr    <= 0;
+                    read_ram_address_int     <= 0;
+                    offset_count      <= 0;
+				    end_of_block_byte        <= 0;
+				    o_write_ram_address      <= 0;
+				    write_ram_en_int         <= 1'b0;
+				    fifo1_read_request       <= 1'b0;	
+				    write_ram_data_int       <= 0;
+				    lz4_decompress_state	 <= idle;
+				end
+			else
+				begin
+					last_data_read_ram   <= 1'b0;
+					write_ram_en_int     <= 1'b0;
+					read_ram_int         <= 1'b0;
+					
+					ram_read_request     <= read_ram_int;		
+					fifo1_read_request   <= fifo1_read_int;
+					
+					last_data_write_ram  <= last_data_read_ram;
+					o_write_ram_address  <= write_ram_address_int;	
+					
+					case(lz4_decompress_state)
+					
+						idle:							
+						   begin	
+						    o_idle <= 1'b1;
+						    write_ram_address_int <= 0;	
+						    read_ram_address_int  <= 0;
+							if(i_fifo1_empty == 1'b0)
+								begin
+							        o_idle <= 1'b0;
+									lz4_decompress_state <= block_size_assign;													
+								end			  
+						   end
+						   
+						block_size_assign:
+							    
+							if(fifo1_read_request == 1'b1)
+								begin
+									case(block_size_byte)
+										2'b00  :
+											begin
+												block_size_byte <= 1;
+												block_size_parameter[7:0] <= i_fifo1_compressed_data;	
+											end
+										2'b01  :
+											begin
+												block_size_byte <= 2;
+												block_size_parameter[15:8] <= i_fifo1_compressed_data;	
+											end																				
+										2'b10  :
+											begin
+												block_size_byte <= 3;
+												block_size_parameter[23:16] <= i_fifo1_compressed_data;	
+											end										
+										2'b11  :
+											begin
+												block_size_byte <= 0;
+												block_size_parameter[30:24] <= i_fifo1_compressed_data;
+													if(i_fifo1_compressed_data[7] == 1'b0)	//block is compressed												
+														lz4_decompress_state <= token_assign;									
+													else // block is uncompressed.
+														lz4_decompress_state <=  block_uncompressed;		
+											end	
+									endcase								
+							    end
+							
+						token_assign:
+							if(fifo1_read_request == 1'b1)
+								begin
+									lz4_decompress_state <= literals_assign;
+									block_size_parameter <= block_size_parameter -1;
+									
+									literal_length_parameter[3:0] <= i_fifo1_compressed_data[7:4];
+									match_length_parameter        <= i_fifo1_compressed_data[3:0] + 4;
+									
+									if(i_fifo1_compressed_data[7:4] ==  4'b1111)
+										lz4_decompress_state <= literal_length_optional;							
+									
+									if(i_fifo1_compressed_data[3:0] ==  4'b1111)
+										match_length_overflow <= 1'b1;															
+								end 								
+
+						literal_length_optional:
+							if(fifo1_read_request == 1'b1)
+								begin
+									literal_length_parameter <= literal_length_parameter +  i_fifo1_compressed_data;
+									block_size_parameter <= block_size_parameter -1;
+									if(i_fifo1_compressed_data[7:0] != 8'b11111111)
+										lz4_decompress_state <= literals_assign;									
+								end 
+
+						literals_assign	:
+							if(fifo1_read_request == 1'b1)
+								begin
+									write_ram_en_int        <= 1'b1;
+									block_size_parameter    <= block_size_parameter -1;
+									write_ram_data_int      <= i_fifo1_compressed_data;
+									if (write_ram_address_int == 127) 
+										write_ram_address_int   <= 0;
+									else
+										write_ram_address_int   <= write_ram_address_int +1;									
+									
+									if(literal_length_parameter == 1'b1 && block_size_parameter == 1)
+										begin
+											lz4_decompress_state     <= end_of_block;
+											literal_length_parameter <= 0;
+										end
+									else if(literal_length_parameter == 1'b1)
+									    begin
+											lz4_decompress_state     <= offset_assing;
+                                            literal_length_parameter <= 0;									    
+									    end
+									else
+										literal_length_parameter <= literal_length_parameter - 1;																							
+						    	end 
+								
+						offset_assing:	
+							if(fifo1_read_request == 1'b1)
+							    begin
+									write_ram_address_ptr  <= write_ram_address_int;
+									block_size_parameter   <= block_size_parameter -1; 
+									case (offset_byte)
+										1'b0  :
+										    begin
+											    offset_byte <= 1'b1;
+											    offset_parameter[7:0] <= i_fifo1_compressed_data; 	
+											end							
+										1'b1  :
+											begin												    								 	
+												offset_byte <= 1'b0;
+												offset_parameter[15:8] <= i_fifo1_compressed_data; 
+												if(offset_parameter[7:0] == 0 && i_fifo1_compressed_data == 0 && block_size_parameter == 1)
+													lz4_decompress_state <= end_of_block;
+												else if(offset_parameter[7:0] == 0 && i_fifo1_compressed_data == 0 && block_size_parameter != 1)
+													lz4_decompress_state <= token_assign;
+												else
+													begin
+														if(match_length_overflow == 1'b1)
+															lz4_decompress_state <= match_length_optional;
+														else
+															lz4_decompress_state <= literals_copy;
+													end	
+                                                	
+                                            end												
+									endcase
+								end 	
+								
+						match_length_optional:
+							if(fifo1_read_request == 1'b1)					
+								begin
+									match_length_parameter <= match_length_parameter +  i_fifo1_compressed_data;
+									block_size_parameter <= block_size_parameter -1;									
+									if(i_fifo1_compressed_data[7:0] != 8'b11111111)
+										lz4_decompress_state <= literals_copy;									
+								end 
+								
+						literals_copy:
+						    begin
+								if(i_fifo2_almst_full == 1'b0)
+									begin
+										if(match_length_parameter != 0)
+											begin
+												match_length_parameter <= match_length_parameter -1;
+												if (match_length_parameter == 1)
+													last_data_read_ram  <= 1'b1;
+																																			
+												if(offset_count == 0 || offset_parameter == 1 )
+													begin
+														read_ram_int <= 1'b1;
+														
+														if(write_ram_address_ptr >= offset_parameter)
+															read_ram_address_int  <= write_ram_address_ptr - offset_parameter;
+														else
+															read_ram_address_int  <= 128 -  offset_parameter + write_ram_address_ptr;
+															
+														if(offset_parameter == 1)
+                                                            offset_count   <= 0; 
+                                                        else   
+                                                        	offset_count   <= offset_count +1; 
+													end
+													
+												else if(offset_count < offset_parameter)
+													begin
+														read_ram_int <= 1'b1;
+														offset_count  <= offset_count +1;
+														
+														if(read_ram_address_int == 127) 
+															read_ram_address_int <= 0;
+														else									
+															read_ram_address_int <= read_ram_address_int + 1;
+																																								
+														if(offset_count == offset_parameter-1)
+															     offset_count <= 0;																							
+													end 
+													
+											end 
+									end 
+									
+								if(ram_read_request == 1'b1)	
+									begin
+										write_ram_en_int        <= 1'b1;
+										write_ram_data_int      <= i_read_ram_data;
+										if (write_ram_address_int == 127)
+											write_ram_address_int   <= 0;
+										else
+											write_ram_address_int   <= write_ram_address_int +1;
+									end	
+								
+									
+								if(last_data_write_ram == 1'b1)
+									begin
+										offset_count <= 0;
+										if(block_size_parameter == 0)
+											lz4_decompress_state <= end_of_block;
+										else
+											lz4_decompress_state <= token_assign;
+									end 		
+							end
+							
+						block_uncompressed:
+							if(fifo1_read_request == 1'b1)
+								begin
+									write_ram_en_int        <= 1'b1;
+									write_ram_data_int      <= i_fifo1_compressed_data;	
+									if (write_ram_address_int == 127)
+										write_ram_address_int   <= 0;
+									else
+										write_ram_address_int   <= write_ram_address_int +1;
+									
+									if(block_size_parameter == 1)
+										lz4_decompress_state <= end_of_block;
+									else
+										block_size_parameter <= block_size_parameter -1;													
+						        end
+								
+						end_of_block:
+							if(i_fifo1_compressed_data == 0 && fifo1_read_request == 1'b1) // 4 byte zero	
+								begin
+									case (end_of_block_byte)
+										2'b00  :
+											end_of_block_byte <= 1;
+										2'b01  :		
+											end_of_block_byte <= 2;
+										2'b10  : 
+											end_of_block_byte <= 3;
+										2'b11  : 
+											begin
+												end_of_block_byte <= 0;
+												lz4_decompress_state <= idle;
+											end
+									endcase
+							    end 																
+					endcase	
+				end	
+		end
+//// ------------------------------------------------------------------------------------------------
+endmodule