// Copyright 2020-2024 Intel Corporation. // // This software and the related documents are Intel copyrighted materials, // and your use of them is governed by the express license under which they // were provided to you ("License"). Unless the License provides otherwise, // you may not use, modify, copy, publish, distribute, disclose or transmit // this software or the related documents without Intel's prior written // permission. // // This software and the related documents are provided as is, with no express // or implied warranties, other than those that are expressly stated in the // License. /** * dla_lt_data_conversion.sv * * The LT data conversion is responsible for converting U8 integers to FP16 values * for inference in the PE array. * */ `resetall `undefineall `default_nettype none module dla_lt_data_conversion #( parameter int DDR_BYTES, parameter int DATA_ELEMENT_WIDTH=8, parameter int ELEMENTS_PER_CYCLE ) ( input wire clk, input wire i_valid, input wire [8*DDR_BYTES-1:0] i_data, output wire [ELEMENTS_PER_CYCLE-1:0][15:0] o_fp16_val, output wire o_valid ); parameter BASE_EXP = 15 - 1; logic [ELEMENTS_PER_CYCLE-1:0][15:0] fp16_val; assign o_fp16_val = fp16_val; logic data_valid; assign o_valid = data_valid; always_ff @( posedge clk ) begin data_valid <= i_valid; // data_valid[1] <= data_valid[0]; end for (genvar in_token = 0; in_token < ELEMENTS_PER_CYCLE; in_token++) begin : g_fp16 logic [7:0] sample; logic [1:0][3:0] exp_offset_nib; logic [1:0][7:0] shifted_val_nib; logic token_in_progress; assign sample = i_data[(in_token*DATA_ELEMENT_WIDTH)+:DATA_ELEMENT_WIDTH]; // split token into nibbles and mux calculation... always_ff @(posedge clk) begin token_in_progress <= 0; // so that the last value is still converted. if (i_valid) begin token_in_progress <= 1; exp_offset_nib[0] <= 0; shifted_val_nib[0] <= 0; if (sample[3]) begin exp_offset_nib[0] <= 4; shifted_val_nib[0] <= {sample[2:0], 5'b0}; end else if (sample[2]) begin exp_offset_nib[0] <= 3; shifted_val_nib[0] <= {sample[1:0], 6'b0}; end else if (sample[1]) begin exp_offset_nib[0] <= 2; shifted_val_nib[0] <= {sample[0], 7'b0}; end else if (sample[0]) begin exp_offset_nib[0] <= 1; shifted_val_nib[0] <= 0; end end end always_ff @(posedge clk) begin if (i_valid) begin exp_offset_nib[1] <= 0; shifted_val_nib[1] <= 0; if (sample[7]) begin exp_offset_nib[1] <= 8; shifted_val_nib[1] <= {sample[6:0], 1'b0}; end else if (sample[6]) begin exp_offset_nib[1] <= 7; shifted_val_nib[1] <= {sample[5:0], 2'b0}; end else if (sample[5]) begin exp_offset_nib[1] <= 6; shifted_val_nib[1] <= {sample[4:0], 3'b0}; end else if (sample[4]) begin exp_offset_nib[1] <= 5; shifted_val_nib[1] <= {sample[3:0], 4'b0}; end end end logic [4:0] exp_offset; logic [4:0] exp_offset_reversed; logic [7:0] shifted_val; always_ff @(posedge clk) begin if ((i_valid) || token_in_progress) begin if (exp_offset_nib[1] > exp_offset_nib[0]) begin exp_offset <= exp_offset_nib[1] + BASE_EXP; shifted_val <= shifted_val_nib[1]; end else if (exp_offset_nib[0] > 0) begin exp_offset <= exp_offset_nib[0] + BASE_EXP; shifted_val <= shifted_val_nib[0]; end else begin exp_offset <= 0; shifted_val <= 0; end end end assign fp16_val[in_token] = { 1'b0, exp_offset, shifted_val, 2'b0 }; end endmodule