1//
2// Copyright 2015 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7
8module axi_serializer #(
9  parameter WIDTH = 32)
10(
11  input clk, input rst, input reverse_input,
12  input [WIDTH-1:0] i_tdata, input  i_tlast, input i_tvalid,  output reg i_tready,
13  output reg o_tdata, output reg o_tlast, output reg o_tvalid, input o_tready
14);
15
16  reg i_tlast_latch;
17  reg [WIDTH-1:0] serial_data_reg;
18  reg [$clog2(WIDTH)-1:0] serial_cnt;
19  reg serializing;
20
21  always @(posedge clk) begin
22    if (rst) begin
23      i_tready        <= 1'b0;
24      i_tlast_latch   <= 1'b0;
25      o_tdata         <= 1'b0;
26      o_tlast         <= 1'b0;
27      o_tvalid        <= 1'b0;
28      serial_data_reg <= 'd0;
29      serializing     <= 1'b0;
30      serial_cnt      <= 0;
31    end else begin
32      i_tready <= 1'b0;
33      // Shift out a bit when downstream can consume it
34      if (serializing & o_tready) begin
35        o_tvalid <= 1'b1;
36        if (reverse_input) begin
37          o_tdata                    <= serial_data_reg[0];
38          serial_data_reg[WIDTH-2:0] <= serial_data_reg[WIDTH-1:1];
39        end else begin
40          o_tdata                    <= serial_data_reg[WIDTH-1];
41          serial_data_reg[WIDTH-1:1] <= serial_data_reg[WIDTH-2:0];
42        end
43        if (serial_cnt == WIDTH-1) begin
44          serial_cnt      <= 0;
45          serial_data_reg <= i_tdata;
46          i_tlast_latch   <= i_tlast;
47          o_tlast         <= i_tlast_latch;
48          if (~i_tvalid) begin
49            serializing <= 1'b0;
50          end else begin
51            i_tready <= 1'b1;
52          end
53        end else begin
54          serial_cnt <= serial_cnt + 1;
55        end
56      end else if (~serializing) begin
57        i_tready <= 1'b1;
58        if (o_tvalid && o_tready) begin
59          o_tvalid <= 1'b0;
60        end
61        // Serial shift register (serial_data_reg) is empty, load it
62        if (i_tvalid) begin
63          i_tready        <= 1'b0;
64          serializing     <= 1'b1;
65          i_tlast_latch   <= i_tlast;
66          serial_data_reg <= i_tdata;
67        end
68      end
69    end
70  end
71
72endmodule