// // Copyright 2013 Ettus Research LLC // Copyright 2018 Ettus Research, a National Instruments Company // // SPDX-License-Identifier: LGPL-3.0-or-later // module pcie_axi_wb_conv #( parameter WB_ADDRW = 16, parameter WB_DATAW = 32 )( input clk, input rst, input wb_stb_i, input wb_we_i, input [WB_ADDRW-1:0] wb_adr_i, input [WB_DATAW-1:0] wb_dat_i, output wb_ack_o, output [WB_DATAW-1:0] wb_dat_o, input [63:0] msgi_tdata, input msgi_tvalid, output msgi_tready, output [63:0] msgo_tdata, output msgo_tvalid, input msgo_tready, output wb_monitor_active, output reg wb_req_pending, output reg wb_resp_pending, output reg pcie_resp_pending ); localparam SB_ADDRW = 4; localparam SB_DATAW = 32; localparam MONITOR_TIMEOUTW = 20; //20bits@175MHz ~ 6ms localparam SR_PCIE_DATA_REG = 4'd0; localparam SR_PCIE_CTRL_REG = 4'd1; localparam RB_PCIE_DATA_REG = 4'd0; localparam RB_PCIE_CTRL_REG = 4'd1; localparam RB_PCIE_RESP_DATA_REG = 4'd2; localparam RB_PCIE_STATUS_REG = 4'd3; //------------------------------------------ // Settings and readback bus // wire [SB_DATAW-1:0] set_data, rb_data; wire [SB_ADDRW-1:0] set_addr, rb_addr; wire set_stb, rb_stb; settings_bus #(.AWIDTH(WB_ADDRW), .DWIDTH(WB_DATAW)) settings_bus ( .wb_clk(clk), .wb_rst(rst), .wb_adr_i(wb_adr_i), .wb_dat_i(wb_dat_i), .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .wb_ack_o(wb_ack_o), .strobe(set_stb), .addr(set_addr), .data(set_data) ); settings_readback #(.AWIDTH(WB_ADDRW), .DWIDTH(WB_DATAW), .RB_ADDRW(SB_ADDRW)) settings_readback ( .wb_clk(clk), .wb_rst(rst), .wb_adr_i(wb_adr_i), .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .rb_data(rb_data), .rb_addr(rb_addr), .rb_rd_stb(rb_stb), .wb_dat_o(wb_dat_o) ); //------------------------------------------ //------------------------------------------ // Settings/Readback Registers // wire [31:0] axi_out_data, axi_out_ctrl; wire axi_out_stb; setting_reg #(.my_addr(SR_PCIE_DATA_REG), .awidth(SB_ADDRW), .width(SB_DATAW)) set_pcie_out_data_reg ( .clk(clk), .rst(rst), .strobe(set_stb), .addr(set_addr), .in(set_data), .out(axi_out_data) ); setting_reg #(.my_addr(SR_PCIE_CTRL_REG), .awidth(SB_ADDRW), .width(SB_DATAW)) set_pcie_out_ctrl_reg ( .clk(clk), .rst(rst), .strobe(set_stb), .addr(set_addr), .in(set_data), .out(axi_out_ctrl), .changed(axi_out_stb) ); reg [31:0] axi_in_data_reg, axi_in_ctrl_reg, axi_in_resp_reg; wire msgo_fifo_tready; // Readback MUX assign rb_data = ( (rb_addr == RB_PCIE_STATUS_REG) ? {27'h0, ~msgo_fifo_tready, 1'b0, wb_resp_pending, wb_req_pending, pcie_resp_pending} : ( (rb_addr == RB_PCIE_RESP_DATA_REG) ? axi_in_resp_reg : ( (rb_addr == RB_PCIE_DATA_REG) ? axi_in_data_reg : ( (rb_addr == RB_PCIE_CTRL_REG) ? axi_in_ctrl_reg : 32'h0)))); //------------------------------------------ //------------------------------------------ // Output message handler // wire [63:0] msgo_fifo_tdata; wire axi_out_rd, axi_out_wr, axi_out_rr; assign msgo_fifo_tdata = {axi_out_ctrl, axi_out_data}; axi_fifo_short #(.WIDTH(64)) wb_out_msg_fifo ( .clk(clk), .reset(rst), .clear(1'b0), .i_tdata(msgo_fifo_tdata), .i_tvalid(axi_out_stb), .i_tready(msgo_fifo_tready), .o_tdata(msgo_tdata), .o_tvalid(msgo_tvalid), .o_tready(msgo_tready), .space(), .occupied()); ioport2_msg_decode axi_out_decoder ( .message(msgo_fifo_tdata), .rd_response(axi_out_rr), .wr_request(axi_out_wr), .rd_request(axi_out_rd) ); //------------------------------------------ //------------------------------------------ // Input message handler // wire [63:0] msgi_fifo_tdata; wire axi_in_valid, axi_in_stb; wire [31:0] axi_in_data, axi_in_ctrl; wire axi_in_rd, axi_in_wr, axi_in_rr; axi_fifo_short #(.WIDTH(64)) wb_in_msg_fifo ( .clk(clk), .reset(rst), .clear(1'b0), .i_tdata(msgi_tdata), .i_tvalid(msgi_tvalid), .i_tready(msgi_tready), .o_tdata(msgi_fifo_tdata), .o_tvalid(axi_in_valid), .o_tready(axi_in_stb), .space(), .occupied()); ioport2_msg_decode axi_in_decoder ( .message(msgi_fifo_tdata), .rd_response(axi_in_rr), .wr_request(axi_in_wr), .rd_request(axi_in_rd), .data(axi_in_data), .control(axi_in_ctrl) ); assign axi_in_stb = axi_in_valid & (axi_in_rr | ((axi_in_wr | axi_in_rd) & ~(wb_req_pending | wb_resp_pending))); always @(posedge clk) begin if (rst) begin axi_in_data_reg <= 32'h0; axi_in_ctrl_reg <= 32'h0; axi_in_resp_reg <= 32'h0; end else begin if (axi_in_stb & axi_in_rr) begin axi_in_resp_reg <= axi_in_data; end else if (axi_in_stb & (axi_in_wr | axi_in_rd)) begin axi_in_data_reg <= axi_in_data; axi_in_ctrl_reg <= axi_in_ctrl; end end end //------------------------------------------ //------------------------------------------ // State handler // //wb_monitor_active reg [MONITOR_TIMEOUTW-1:0] wb_monitor_timeout; assign wb_monitor_active = (wb_monitor_timeout != {(MONITOR_TIMEOUTW){1'b0}}); always @(posedge clk) begin if (rst) wb_monitor_timeout <= {(MONITOR_TIMEOUTW){1'b0}}; //Monitor disabled on rst else if (rb_stb && (rb_addr == RB_PCIE_STATUS_REG)) wb_monitor_timeout <= {(MONITOR_TIMEOUTW){1'b1}}; //Reset counter when the ZPU queries the status reg else if (wb_monitor_active) wb_monitor_timeout <= wb_monitor_timeout - 1; //Decrement counter when idle end //wb_req_pending always @(posedge clk) begin if (rst || (rb_stb && (rb_addr == RB_PCIE_CTRL_REG))) wb_req_pending <= 1'b0; else if (axi_in_stb & (axi_in_rd | axi_in_wr)) wb_req_pending <= 1'b1; end //wb_resp_pending always @(posedge clk) begin if (rst | (axi_out_stb & msgo_fifo_tready & axi_out_rr)) wb_resp_pending <= 1'b0; else if (axi_in_stb & axi_in_rd) wb_resp_pending <= 1'b1; end //pcie_resp_pending always @(posedge clk) begin if (rst | (axi_in_stb & axi_in_rr)) pcie_resp_pending <= 1'b0; else if (axi_out_stb & msgo_fifo_tready & axi_out_rd) pcie_resp_pending <= 1'b1; end //------------------------------------------ endmodule