File: axi_demux.v

package info (click to toggle)
uhd 4.8.0.0%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 183,172 kB
  • sloc: cpp: 279,415; python: 109,850; ansic: 103,348; vhdl: 57,230; tcl: 20,007; xml: 8,581; makefile: 2,863; sh: 2,797; pascal: 230; javascript: 120; csh: 94; asm: 20; perl: 11
file content (154 lines) | stat: -rw-r--r-- 4,628 bytes parent folder | download | duplicates (2)
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 2024 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: axi_demux
//
// Description:
//
//   Implements a 1-to-SIZE demultiplexer for AXI-Stream. Switching output
//   paths happens only between packets. A bubble cycle is added between each
//   packet to allow the switching. The output to use for the next packet is
//   selected using the dest input.
//
//   The header output contains a copy of i_tdata and can be used when the
//   first word of the packet contains information that should be used to
//   determine the destination using combinational logic.
//

`default_nettype none


module axi_demux #(
  parameter WIDTH          = 64,
  parameter SIZE           = 4,
  parameter PRE_FIFO_SIZE  = 0,
  parameter POST_FIFO_SIZE = 0
) (
  input  wire                    clk,
  input  wire                    reset,
  input  wire                    clear,

  output wire [       WIDTH-1:0] header,
  input  wire [$clog2(SIZE)-1:0] dest,

  input  wire [       WIDTH-1:0] i_tdata,
  input  wire                    i_tlast,
  input  wire                    i_tvalid,
  output wire                    i_tready,

  output wire [(WIDTH*SIZE)-1:0] o_tdata,
  output wire [        SIZE-1:0] o_tlast,
  output wire [        SIZE-1:0] o_tvalid,
  input  wire [        SIZE-1:0] o_tready
);

  //---------------------------------------------------------------------------
  // Optional Input FIFO
  //---------------------------------------------------------------------------

  wire             i_tlast_int;
  wire             i_tready_int;
  wire             i_tvalid_int;
  wire [WIDTH-1:0] i_tdata_int;

  generate
    if (PRE_FIFO_SIZE == 0) begin : gen_no_pre_fifo
      assign i_tlast_int = i_tlast;
      assign i_tdata_int = i_tdata;
      assign i_tvalid_int = i_tvalid;
      assign i_tready = i_tready_int;
    end else begin : gen_pre_fifo
      axi_fifo #(
        .WIDTH(WIDTH+1),
        .SIZE(PRE_FIFO_SIZE)
      ) axi_fifo_i (
        .clk     (clk),
        .reset   (reset),
        .clear   (clear),
        .i_tdata ({i_tlast,i_tdata}),
        .i_tvalid(i_tvalid),
        .i_tready(i_tready),
        .o_tdata ({i_tlast_int,i_tdata_int}),
        .o_tvalid(i_tvalid_int),
        .o_tready(i_tready_int),
        .space   (),
        .occupied()
      );
    end
  endgenerate

  //---------------------------------------------------------------------------
  // Demultiplexer Logic
  //---------------------------------------------------------------------------

  assign header = i_tdata_int;

  // The state vector indicates which output is selected
  reg [SIZE-1:0] st = {SIZE{1'b0}};

  always @(posedge clk) begin
    if(reset | clear) begin
      st <= {SIZE{1'b0}};
    end else begin
      // If state is 0, that means no output path is selected and we are free
      // to select the next destination.
      if(st == 0) begin
        if(i_tvalid_int) begin
          st[dest] <= 1'b1;
        end
      end else begin
        // At the end of the packet, clear the state
        if(i_tready_int & i_tvalid_int & i_tlast_int) begin
          st <= {SIZE{1'b0}};
        end
      end
    end
  end

  //---------------------------------------------------------------------------
  // Optional Output FIFO(s)
  //---------------------------------------------------------------------------

  genvar n;
  generate
    if (POST_FIFO_SIZE == 0) begin : gen_no_post_fifo
      assign o_tdata      = {SIZE{i_tdata_int}};
      assign o_tlast      = {SIZE{i_tlast_int}};
      assign o_tvalid     = {SIZE{i_tvalid_int}} & st;
      assign i_tready_int = |(o_tready & st);
    end else begin : gen_post_fifo
      wire [SIZE-1:0] i_tready_fifo;
      wire [SIZE-1:0] i_tvalid_fifo;

      // Only read tready from and drive tvalid to the currently selected
      // output.
      assign i_tready_int  = |(i_tready_fifo & st);
      assign i_tvalid_fifo = {SIZE{i_tvalid_int}} & st;

      for (n = 0; n < SIZE; n = n + 1) begin : gen_post_axi_fifo
        axi_fifo #(
          .WIDTH(WIDTH+1),
          .SIZE (POST_FIFO_SIZE)
        ) axi_fifo_i (
          .clk     (clk),
          .reset   (reset),
          .clear   (clear),
          .i_tdata ({i_tlast_int, i_tdata_int}),
          .i_tvalid(i_tvalid_fifo[n]),
          .i_tready(i_tready_fifo[n]),
          .o_tdata ({o_tlast[n], o_tdata[WIDTH*(n+1)-1:WIDTH*n]}),
          .o_tvalid(o_tvalid[n]),
          .o_tready(o_tready[n]),
          .space   (),
          .occupied()
        );
      end
    end
  endgenerate

 endmodule // axi_demux


`default_nettype wire