1// 2// Copyright 2013 Ettus Research LLC 3// Copyright 2018 Ettus Research, a National Instruments Company 4// 5// SPDX-License-Identifier: LGPL-3.0-or-later 6// 7 8 9module pcie_iop2_msg_arbiter #( 10 parameter E0_ADDR = 20'h0, 11 parameter E0_MASK = 20'h0, 12 parameter E1_ADDR = 20'h0, 13 parameter E1_MASK = 20'h0, 14 parameter E2_ADDR = 20'h0, 15 parameter E2_MASK = 20'h0, 16 parameter E3_ADDR = 20'h0, 17 parameter E3_MASK = 20'h0 18) ( 19 //Clocks and resets 20 input clk, 21 input reset, 22 23 input [63:0] regi_tdata, 24 input regi_tvalid, 25 output regi_tready, 26 output [63:0] rego_tdata, 27 output rego_tvalid, 28 input rego_tready, 29 30 output [63:0] e0_regi_tdata, 31 output e0_regi_tvalid, 32 input e0_regi_tready, 33 input [63:0] e0_rego_tdata, 34 input e0_rego_tvalid, 35 output e0_rego_tready, 36 37 output [63:0] e1_regi_tdata, 38 output e1_regi_tvalid, 39 input e1_regi_tready, 40 input [63:0] e1_rego_tdata, 41 input e1_rego_tvalid, 42 output e1_rego_tready, 43 44 output [63:0] e2_regi_tdata, 45 output e2_regi_tvalid, 46 input e2_regi_tready, 47 input [63:0] e2_rego_tdata, 48 input e2_rego_tvalid, 49 output e2_rego_tready, 50 51 output [63:0] e3_regi_tdata, 52 output e3_regi_tvalid, 53 input e3_regi_tready, 54 input [63:0] e3_rego_tdata, 55 input e3_rego_tvalid, 56 output e3_rego_tready 57); 58 59 //******************************************************************************* 60 // PCIe output message arbiter 61 // 62 axi_mux4 #(.PRIO(0), .WIDTH(64), .BUFFER(0)) rego_arbiter_mux ( 63 .clk(clk), .reset(reset), .clear(1'b0), 64 .i0_tdata(e0_rego_tdata), .i0_tlast(e0_rego_tvalid), .i0_tvalid(e0_rego_tvalid), .i0_tready(e0_rego_tready), 65 .i1_tdata(e1_rego_tdata), .i1_tlast(e1_rego_tvalid), .i1_tvalid(e1_rego_tvalid), .i1_tready(e1_rego_tready), 66 .i2_tdata(e2_rego_tdata), .i2_tlast(e2_rego_tvalid), .i2_tvalid(e2_rego_tvalid), .i2_tready(e2_rego_tready), 67 .i3_tdata(e3_rego_tdata), .i3_tlast(e3_rego_tvalid), .i3_tvalid(e3_rego_tvalid), .i3_tready(e3_rego_tready), 68 .o_tdata(rego_tdata), .o_tlast(), .o_tvalid(rego_tvalid), .o_tready(rego_tready) 69 ); 70 // 71 //******************************************************************************* 72 73 //******************************************************************************* 74 // PCIe input message arbiter 75 // 76 wire [63:0] regi_msg; 77 wire regi_rc; 78 wire [19:0] regi_addr; 79 wire e0_rego_rd, e1_rego_rd, e2_rego_rd, e3_rego_rd; 80 81 ioport2_msg_decode e0_rego_decoder (.message(e0_rego_tdata), .rd_request(e0_rego_rd)); 82 ioport2_msg_decode e1_rego_decoder (.message(e1_rego_tdata), .rd_request(e1_rego_rd)); 83 ioport2_msg_decode e2_rego_decoder (.message(e2_rego_tdata), .rd_request(e2_rego_rd)); 84 ioport2_msg_decode e3_rego_decoder (.message(e3_rego_tdata), .rd_request(e3_rego_rd)); 85 86 localparam DEST_E0 = 2'd0; 87 localparam DEST_E1 = 2'd1; 88 localparam DEST_E2 = 2'd2; 89 localparam DEST_E3 = 2'd3; 90 91 reg [1:0] regi_resp_dest; 92 wire [1:0] regi_req_dest, regi_dest; 93 94 assign regi_req_dest = 95 ((regi_addr & E0_MASK) == E0_ADDR) ? DEST_E0 : ( 96 ((regi_addr & E1_MASK) == E1_ADDR) ? DEST_E1 : ( 97 ((regi_addr & E2_MASK) == E2_ADDR) ? DEST_E2 : ( 98 ((regi_addr & E3_MASK) == E3_ADDR) ? DEST_E3 : ( 99 DEST_E0)))); 100 101 //A response must be routed to the port with the last read request 102 always @(posedge clk) begin 103 if (reset) 104 regi_resp_dest <= DEST_E0; //Default 0 105 else if (e0_rego_tvalid & e0_rego_tready & e0_rego_rd) 106 regi_resp_dest <= DEST_E0; 107 else if (e1_rego_tvalid & e1_rego_tready & e1_rego_rd) 108 regi_resp_dest <= DEST_E1; 109 else if (e2_rego_tvalid & e2_rego_tready & e2_rego_rd) 110 regi_resp_dest <= DEST_E2; 111 else if (e3_rego_tvalid & e3_rego_tready & e3_rego_rd) 112 regi_resp_dest <= DEST_E3; 113 end 114 115 ioport2_msg_decode regi_decoder ( 116 .message(regi_msg), .rd_response(regi_rc), .address(regi_addr)); 117 118 //If request, get destination from msg. 119 //If response, get destination from last read location. 120 assign regi_dest = regi_rc ? regi_resp_dest : regi_req_dest; 121 122 axi_demux4 #(.ACTIVE_CHAN(4'b1111), .WIDTH(64), .BUFFER(0)) regi_arbiter_demux ( 123 .clk(clk), .reset(reset), .clear(1'b0), 124 .header(regi_msg), .dest(regi_dest), 125 .i_tdata(regi_tdata), .i_tlast(regi_tvalid), .i_tvalid(regi_tvalid), .i_tready(regi_tready), 126 .o0_tdata(e0_regi_tdata), .o0_tlast(), .o0_tvalid(e0_regi_tvalid), .o0_tready(e0_regi_tready), 127 .o1_tdata(e1_regi_tdata), .o1_tlast(), .o1_tvalid(e1_regi_tvalid), .o1_tready(e1_regi_tready), 128 .o2_tdata(e2_regi_tdata), .o2_tlast(), .o2_tvalid(e2_regi_tvalid), .o2_tready(e2_regi_tready), 129 .o3_tdata(e3_regi_tdata), .o3_tlast(), .o3_tvalid(e3_regi_tvalid), .o3_tready(e3_regi_tready) 130 ); 131 // 132 //******************************************************************************* 133 134endmodule 135