summaryrefslogtreecommitdiff
path: root/python/openvino/demo/ip/intel_ai_ip/verilog/dla_lt_data_conversion.sv
blob: 7fe65c6a52c68dea96024ebc0e7b6c7f845715d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// 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