Files
b210-k7-fpga/lib/io_port2/pcie_axi_wb_conv.v
T
Ben Hilburn fbbc991a7d Pushing the bulk of UHD-3.7.0 code.
Original-commit: ff1546f8137f7f92bb250f685561b0c34cc0e053
2014-02-14 12:05:07 -08:00

197 lines
6.9 KiB
Verilog

//
// Copyright 2013 Ettus Research LLC
//
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