aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/control/axi_slave_mux.v
blob: 3f2424584592edc87172b6988ddaabea24184320 (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
//
// Copyright 2012 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

   

`define LOG2(N) (\
                 N < 2 ? 0 : \
                 N < 4 ? 1 : \
                 N < 8 ? 2 : \
                 N < 16 ? 3 : \
                 N < 32 ? 4 : \
                 N < 64 ? 5 : \
		 N < 128 ? 6 : \
		 N < 256 ? 7 : \
		 N < 512 ? 8 : \
		 N < 1024 ? 9 : \
                 10)


module axi_slave_mux
  #(
    parameter FIFO_WIDTH = 64, // AXI4-STREAM data bus width
    parameter DST_WIDTH = 16,  // Width of DST field we are routing on.
    parameter NUM_INPUTS = 2   // number of input AXI buses
    )
    (
     input 				 clk,
     input 				 reset,
     input 				 clear,
     // Inputs
     input [(FIFO_WIDTH*NUM_INPUTS)-1:0] i_tdata,
     input [NUM_INPUTS-1:0] 		 i_tvalid,
     input [NUM_INPUTS-1:0] 		 i_tlast,
     output [NUM_INPUTS-1:0] 		 i_tready,
     // Forwarding Flags
     input [NUM_INPUTS-1:0] 		 forward_valid,
     output reg [NUM_INPUTS-1:0] 	 forward_ack,
     // Output
     output [FIFO_WIDTH-1:0] 		 o_tdata,
     output 				 o_tvalid,
     output 				 o_tlast,
     input 				 o_tready
     );

   wire [FIFO_WIDTH-1:0] i_tdata_array [0:NUM_INPUTS-1];
   
   reg [`LOG2(NUM_INPUTS):0] select;
   reg 			     enable;


   reg 			     state;

   localparam CHECK_THIS_INPUT = 0;
   localparam WAIT_LAST = 1;
   

   always @(posedge clk)
     if (reset | clear) begin
	state <= CHECK_THIS_INPUT;
	select <= 0;
	enable <= 0;
	forward_ack <= 0;	
     end else begin
	case(state)
	  // Is the currently selected input addressing this slave with a ready packet?
	  CHECK_THIS_INPUT:  begin
	     if (forward_valid[select]) begin
		enable <= 1;
		forward_ack[select] <= 1;
		state <= WAIT_LAST;
	     end else if (select == NUM_INPUTS - 1 ) begin
		select <= 0;
	     end else begin
		select <= select + 1;
	     end
	  end
	  // Assert ACK immediately to forwarding logic and then wait for end of packet.
	  WAIT_LAST: begin
	    
	     if (i_tlast[select] && i_tvalid[select] && o_tready) begin
		if (select == NUM_INPUTS - 1 ) begin
		   select <= 0;
		end else begin
		   select <= select + 1;
		end
		state <= CHECK_THIS_INPUT;
		forward_ack <= 0;
		enable <= 0;
	     end else begin
		forward_ack[select] <= 1;
		enable <= 1;
	     end
	  end
	endcase // case(state)
     end
	
   //
   // Combinatorial mux
   //
   genvar m;
     
   generate
      for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_buses
	 assign i_tdata_array[m] = i_tdata[(m*FIFO_WIDTH)+FIFO_WIDTH-1:m*FIFO_WIDTH];
      end
   endgenerate

   assign 	o_tdata = i_tdata_array[select];
   assign 	o_tvalid = enable && i_tvalid[select];
   assign 	o_tlast = enable && i_tlast[select];
 //  assign 	i_tready = {NUM_INPUTS{o_tready}} & (enable << select);

   generate
      for (m = 0; m < NUM_INPUTS; m = m + 1) begin: form_ready
	 assign i_tready[m] = o_tready && enable && (select == m);
      end
   endgenerate

    
endmodule // axi_slave_mux