1// 2// Copyright 2018-2019 Ettus Research, A National Instruments Company 3// 4// SPDX-License-Identifier: LGPL-3.0-or-later 5// 6// Module: ctrlport_endpoint 7// Description: 8// A bidirectional AXIS-Control to Control-Port converter. 9// Use this module in noc_shell to interface between the user 10// logic (using ctrlport) and the rfnoc infrastructure (axis_ctrl) 11// 12// Parameters: 13// - THIS_PORTID: The 10-bit ID of the control XB port that is 14// connected to this converter. 15// - SYNC_CLKS: Is rfnoc_ctrl_clk and ctrlport_clk the same clock? 16// - AXIS_CTRL_MST_EN: Enable an AXIS-Ctrl master 17// - AXIS_CTRL_SLV_EN: Enable an AXIS-Ctrl slave 18// - SLAVE_FIFO_SIZE: FIFO depth for the slave port 19// 20// Signals: 21// - *_rfnoc_ctrl_* : Input/output AXIS-Control stream (AXI-Stream) 22// - *_ctrlport_* : Input/output control-port bus 23 24module ctrlport_endpoint #( 25 parameter [9:0] THIS_PORTID = 10'd0, 26 parameter SYNC_CLKS = 0, 27 parameter [0:0] AXIS_CTRL_MST_EN = 1, 28 parameter [0:0] AXIS_CTRL_SLV_EN = 1, 29 parameter SLAVE_FIFO_SIZE = 5 30)( 31 // Clocks, Resets, Misc 32 input wire rfnoc_ctrl_clk, 33 input wire rfnoc_ctrl_rst, 34 input wire ctrlport_clk, 35 input wire ctrlport_rst, 36 // AXIS-Control Bus 37 input wire [31:0] s_rfnoc_ctrl_tdata, 38 input wire s_rfnoc_ctrl_tlast, 39 input wire s_rfnoc_ctrl_tvalid, 40 output wire s_rfnoc_ctrl_tready, 41 output wire [31:0] m_rfnoc_ctrl_tdata, 42 output wire m_rfnoc_ctrl_tlast, 43 output wire m_rfnoc_ctrl_tvalid, 44 input wire m_rfnoc_ctrl_tready, 45 // Control Port Master (Request) 46 output wire m_ctrlport_req_wr, 47 output wire m_ctrlport_req_rd, 48 output wire [19:0] m_ctrlport_req_addr, 49 output wire [31:0] m_ctrlport_req_data, 50 output wire [3:0] m_ctrlport_req_byte_en, 51 output wire m_ctrlport_req_has_time, 52 output wire [63:0] m_ctrlport_req_time, 53 // Control Port Master (Response) 54 input wire m_ctrlport_resp_ack, 55 input wire [1:0] m_ctrlport_resp_status, 56 input wire [31:0] m_ctrlport_resp_data, 57 // Control Port Slave (Request) 58 input wire s_ctrlport_req_wr, 59 input wire s_ctrlport_req_rd, 60 input wire [19:0] s_ctrlport_req_addr, 61 input wire [9:0] s_ctrlport_req_portid, 62 input wire [15:0] s_ctrlport_req_rem_epid, 63 input wire [9:0] s_ctrlport_req_rem_portid, 64 input wire [31:0] s_ctrlport_req_data, 65 input wire [3:0] s_ctrlport_req_byte_en, 66 input wire s_ctrlport_req_has_time, 67 input wire [63:0] s_ctrlport_req_time, 68 // Control Port Slave (Response) 69 output wire s_ctrlport_resp_ack, 70 output wire [1:0] s_ctrlport_resp_status, 71 output wire [31:0] s_ctrlport_resp_data 72); 73 74 // --------------------------------------------------- 75 // RFNoC Includes 76 // --------------------------------------------------- 77 `include "rfnoc_chdr_utils.vh" 78 `include "rfnoc_axis_ctrl_utils.vh" 79 80 // --------------------------------------------------- 81 // Clock Crossing 82 // --------------------------------------------------- 83 84 wire [31:0] i_ctrl_tdata, o_ctrl_tdata; 85 wire i_ctrl_tlast, o_ctrl_tlast; 86 wire i_ctrl_tvalid, o_ctrl_tvalid; 87 wire i_ctrl_tready, o_ctrl_tready; 88 89 generate 90 if (SYNC_CLKS) begin : gen_sync_fifos 91 axi_fifo #(.WIDTH(32+1), .SIZE(1)) in_fifo_i ( 92 .clk(ctrlport_clk), .reset(ctrlport_rst), .clear(1'b0), 93 .i_tdata({s_rfnoc_ctrl_tlast, s_rfnoc_ctrl_tdata}), 94 .i_tvalid(s_rfnoc_ctrl_tvalid), .i_tready(s_rfnoc_ctrl_tready), 95 .o_tdata({i_ctrl_tlast, i_ctrl_tdata}), 96 .o_tvalid(i_ctrl_tvalid), .o_tready(i_ctrl_tready), 97 .space(), .occupied() 98 ); 99 100 axi_fifo #(.WIDTH(32+1), .SIZE(1)) out_fifo_i ( 101 .clk(ctrlport_clk), .reset(ctrlport_rst), .clear(1'b0), 102 .i_tdata({o_ctrl_tlast, o_ctrl_tdata}), 103 .i_tvalid(o_ctrl_tvalid), .i_tready(o_ctrl_tready), 104 .o_tdata({m_rfnoc_ctrl_tlast, m_rfnoc_ctrl_tdata}), 105 .o_tvalid(m_rfnoc_ctrl_tvalid), .o_tready(m_rfnoc_ctrl_tready), 106 .space(), .occupied() 107 ); 108 end else begin : gen_async_fifos 109 axi_fifo_2clk #(.WIDTH(32+1), .SIZE(1), .PIPELINE("IN")) in_fifo_i ( 110 .reset(rfnoc_ctrl_rst), 111 .i_aclk(rfnoc_ctrl_clk), 112 .i_tdata({s_rfnoc_ctrl_tlast, s_rfnoc_ctrl_tdata}), 113 .i_tvalid(s_rfnoc_ctrl_tvalid), .i_tready(s_rfnoc_ctrl_tready), 114 .o_aclk(ctrlport_clk), 115 .o_tdata({i_ctrl_tlast, i_ctrl_tdata}), 116 .o_tvalid(i_ctrl_tvalid), .o_tready(i_ctrl_tready) 117 ); 118 119 axi_fifo_2clk #(.WIDTH(32+1), .SIZE(1), .PIPELINE("OUT")) out_fifo_i ( 120 .reset(ctrlport_rst), 121 .i_aclk(ctrlport_clk), 122 .i_tdata({o_ctrl_tlast, o_ctrl_tdata}), 123 .i_tvalid(o_ctrl_tvalid), .i_tready(o_ctrl_tready), 124 .o_aclk(rfnoc_ctrl_clk), 125 .o_tdata({m_rfnoc_ctrl_tlast, m_rfnoc_ctrl_tdata}), 126 .o_tvalid(m_rfnoc_ctrl_tvalid), .o_tready(m_rfnoc_ctrl_tready) 127 ); 128 129 end 130 endgenerate 131 132 // --------------------------------------------------- 133 // MUXING 134 // --------------------------------------------------- 135 wire [31:0] mst_req_tdata, mst_resp_tdata ; 136 wire mst_req_tlast, mst_resp_tlast ; 137 wire mst_req_tvalid, mst_resp_tvalid; 138 wire mst_req_tready, mst_resp_tready; 139 140 wire [31:0] slv_req_tdata, slv_req_fifo_tdata, slv_resp_tdata ; 141 wire slv_req_tlast, slv_req_fifo_tlast, slv_resp_tlast ; 142 wire slv_req_tvalid, slv_req_fifo_tvalid, slv_resp_tvalid; 143 wire slv_req_tready, slv_req_fifo_tready, slv_resp_tready; 144 145 generate 146 if (AXIS_CTRL_MST_EN == 1'b1 && AXIS_CTRL_SLV_EN == 1'b1) begin : gen_mst_slv_muxing 147 wire [31:0] in_hdr; 148 axi_demux #( 149 .WIDTH(32), .SIZE(2), .PRE_FIFO_SIZE(0), .POST_FIFO_SIZE(0) 150 ) demux_i ( 151 .clk(ctrlport_clk), .reset(ctrlport_rst), .clear(1'b0), 152 .header(in_hdr), .dest(axis_ctrl_get_is_ack(in_hdr)), 153 .i_tdata (i_ctrl_tdata ), 154 .i_tlast (i_ctrl_tlast ), 155 .i_tvalid(i_ctrl_tvalid), 156 .i_tready(i_ctrl_tready), 157 .o_tdata ({mst_resp_tdata, slv_req_tdata }), 158 .o_tlast ({mst_resp_tlast, slv_req_tlast }), 159 .o_tvalid({mst_resp_tvalid, slv_req_tvalid}), 160 .o_tready({mst_resp_tready, slv_req_tready}) 161 ); 162 163 axi_mux #( 164 .WIDTH(32), .SIZE(2), .PRIO(0), .PRE_FIFO_SIZE(0), .POST_FIFO_SIZE(0) 165 ) mux_i ( 166 .clk(ctrlport_clk), .reset(ctrlport_rst), .clear(1'b0), 167 .i_tdata ({mst_req_tdata, slv_resp_tdata }), 168 .i_tlast ({mst_req_tlast, slv_resp_tlast }), 169 .i_tvalid({mst_req_tvalid, slv_resp_tvalid}), 170 .i_tready({mst_req_tready, slv_resp_tready}), 171 .o_tdata (o_ctrl_tdata ), 172 .o_tlast (o_ctrl_tlast ), 173 .o_tvalid(o_ctrl_tvalid), 174 .o_tready(o_ctrl_tready) 175 ); 176 177 end else if (AXIS_CTRL_MST_EN == 1'b1) begin : gen_mst_muxing 178 179 assign mst_resp_tdata = i_ctrl_tdata; 180 assign mst_resp_tlast = i_ctrl_tlast; 181 assign mst_resp_tvalid = i_ctrl_tvalid; 182 assign i_ctrl_tready = mst_resp_tready; 183 184 assign o_ctrl_tdata = mst_req_tdata; 185 assign o_ctrl_tlast = mst_req_tlast; 186 assign o_ctrl_tvalid = mst_req_tvalid; 187 assign mst_req_tready = o_ctrl_tready; 188 189 end else begin : gen_no_mst_muxing 190 191 assign slv_req_tdata = i_ctrl_tdata; 192 assign slv_req_tlast = i_ctrl_tlast; 193 assign slv_req_tvalid = i_ctrl_tvalid; 194 assign i_ctrl_tready = slv_req_tready; 195 196 assign o_ctrl_tdata = slv_resp_tdata; 197 assign o_ctrl_tlast = slv_resp_tlast; 198 assign o_ctrl_tvalid = slv_resp_tvalid; 199 assign slv_resp_tready = o_ctrl_tready; 200 201 end 202 endgenerate 203 204 // --------------------------------------------------- 205 // AXIS Control Master and Slave 206 // --------------------------------------------------- 207 208 generate 209 if (AXIS_CTRL_MST_EN == 1'b1) begin : gen_ctrl_master 210 axis_ctrl_master #( .THIS_PORTID(THIS_PORTID) ) axis_ctrl_mst_i ( 211 .clk (ctrlport_clk), 212 .rst (ctrlport_rst), 213 .s_axis_ctrl_tdata (mst_resp_tdata), 214 .s_axis_ctrl_tlast (mst_resp_tlast), 215 .s_axis_ctrl_tvalid (mst_resp_tvalid), 216 .s_axis_ctrl_tready (mst_resp_tready), 217 .m_axis_ctrl_tdata (mst_req_tdata), 218 .m_axis_ctrl_tlast (mst_req_tlast), 219 .m_axis_ctrl_tvalid (mst_req_tvalid), 220 .m_axis_ctrl_tready (mst_req_tready), 221 .ctrlport_req_wr (s_ctrlport_req_wr), 222 .ctrlport_req_rd (s_ctrlport_req_rd), 223 .ctrlport_req_addr (s_ctrlport_req_addr), 224 .ctrlport_req_portid (s_ctrlport_req_portid), 225 .ctrlport_req_rem_epid (s_ctrlport_req_rem_epid), 226 .ctrlport_req_rem_portid(s_ctrlport_req_rem_portid), 227 .ctrlport_req_data (s_ctrlport_req_data), 228 .ctrlport_req_byte_en (s_ctrlport_req_byte_en), 229 .ctrlport_req_has_time (s_ctrlport_req_has_time), 230 .ctrlport_req_time (s_ctrlport_req_time), 231 .ctrlport_resp_ack (s_ctrlport_resp_ack), 232 .ctrlport_resp_status (s_ctrlport_resp_status), 233 .ctrlport_resp_data (s_ctrlport_resp_data) 234 ); 235 end else begin : gen_no_ctrl_master 236 assign mst_resp_tready = 1'b1; 237 assign mst_req_tlast = 1'b0; 238 assign mst_req_tvalid = 1'b0; 239 assign s_ctrlport_resp_ack = 1'b0; 240 end 241 242 if (AXIS_CTRL_SLV_EN == 1'b1) begin : gen_ctrl_slave 243 axi_fifo #(.WIDTH(32+1), .SIZE(SLAVE_FIFO_SIZE)) slv_fifo_i ( 244 .clk(ctrlport_clk), .reset(ctrlport_rst), .clear(1'b0), 245 .i_tdata({slv_req_tlast, slv_req_tdata}), 246 .i_tvalid(slv_req_tvalid), .i_tready(slv_req_tready), 247 .o_tdata({slv_req_fifo_tlast, slv_req_fifo_tdata}), 248 .o_tvalid(slv_req_fifo_tvalid), .o_tready(slv_req_fifo_tready), 249 .space(), .occupied() 250 ); 251 252 axis_ctrl_slave axis_ctrl_slv_i ( 253 .clk (ctrlport_clk), 254 .rst (ctrlport_rst), 255 .s_axis_ctrl_tdata (slv_req_fifo_tdata), 256 .s_axis_ctrl_tlast (slv_req_fifo_tlast), 257 .s_axis_ctrl_tvalid (slv_req_fifo_tvalid), 258 .s_axis_ctrl_tready (slv_req_fifo_tready), 259 .m_axis_ctrl_tdata (slv_resp_tdata), 260 .m_axis_ctrl_tlast (slv_resp_tlast), 261 .m_axis_ctrl_tvalid (slv_resp_tvalid), 262 .m_axis_ctrl_tready (slv_resp_tready), 263 .ctrlport_req_wr (m_ctrlport_req_wr), 264 .ctrlport_req_rd (m_ctrlport_req_rd), 265 .ctrlport_req_addr (m_ctrlport_req_addr), 266 .ctrlport_req_data (m_ctrlport_req_data), 267 .ctrlport_req_byte_en (m_ctrlport_req_byte_en), 268 .ctrlport_req_has_time(m_ctrlport_req_has_time), 269 .ctrlport_req_time (m_ctrlport_req_time), 270 .ctrlport_resp_ack (m_ctrlport_resp_ack), 271 .ctrlport_resp_status (m_ctrlport_resp_status), 272 .ctrlport_resp_data (m_ctrlport_resp_data) 273 ); 274 end else begin : gen_no_ctrl_slave 275 assign slv_req_fifo_tready = 1'b1; 276 assign slv_resp_tlast = 1'b0; 277 assign slv_resp_tvalid = 1'b0; 278 assign m_ctrlport_req_wr = 1'b0; 279 assign m_ctrlport_req_rd = 1'b0; 280 end 281 endgenerate 282 283endmodule // ctrlport_endpoint 284 285