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