blob: 5531177a7ecdb3c375b249db91cda4fc0de96df1 [file] [log] [blame]
`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