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