module mdio_cmd_fifo_to_axi (
input wire clk,
input wire rst,
input wire [32:0] s_axis_tdata_i, // 命令FIFO数据
input wire s_axis_tvalid_i, // 命令FIFO有效
output wire s_axis_tready_o, // 命令FIFO就绪
output reg [15:0] m_axi_awaddr_o, // AXI写地址
output reg m_axi_awvalid_o, // AXI写地址有效
input wire m_axi_awready_i, // AXI写地址就绪
output reg [15:0] m_axi_wdata_o, // AXI写数据
output reg m_axi_wlast_o, // AXI写最后一拍
output reg m_axi_wvalid_o, // AXI写数据有效
input wire m_axi_wready_i, // AXI写数据就绪
output reg m_axi_bready_o, // AXI写响应就绪
input wire m_axi_bvalid_i, // AXI写响应有效
input wire [1:0] m_axi_bresp_i, // AXI写响应
output reg [15:0] m_axi_araddr_o, // AXI读地址
output reg m_axi_arvalid_o, // AXI读地址有效
input wire m_axi_arready_i, // AXI读地址就绪
output reg m_axi_rready_o, // AXI读数据就绪
input wire [15:0] m_axi_rdata_i, // AXI读数据
input wire m_axi_rlast_i, // AXI读最后一拍
input wire m_axi_rvalid_i, // AXI读数据有效
output reg [31:0] rd_axis_tdata_o, // 读返回:{addr, data}
output reg rd_axis_tvalid_o, // 读返回有效
output reg rd_axis_tlast_o, // 读返回帧尾
input wire rd_axis_tready_i, // 读返回就绪
output reg axi_err_o // AXI响应错误
);
localparam ST_IDLE = 7'b0000001;
localparam ST_AW = 7'b0000010;
localparam ST_W = 7'b0000100;
localparam ST_B = 7'b0001000;
localparam ST_AR = 7'b0010000;
localparam ST_R = 7'b0100000;
localparam ST_RSP = 7'b1000000;
reg [6:0] state_r, state_n; // 状态
reg wr_r, wr_n; // 读写标志
reg [15:0] addr_r, addr_n; // 地址锁存
reg [15:0] data_r, data_n; // 数据锁存
reg [15:0] rdata_r, rdata_n; // 读数据锁存
reg err_r, err_n; // 错误锁存
wire cmd_handshake = s_axis_tvalid_i & s_axis_tready_o;
wire aw_handshake = m_axi_awvalid_o & m_axi_awready_i;
wire w_handshake = m_axi_wvalid_o & m_axi_wready_i;
wire b_handshake = m_axi_bvalid_i & m_axi_bready_o;
wire ar_handshake = m_axi_arvalid_o & m_axi_arready_i;
wire r_handshake = m_axi_rvalid_i & m_axi_rready_o;
wire rsp_handshake = rd_axis_tvalid_o & rd_axis_tready_i;
assign s_axis_tready_o = (state_r == ST_IDLE);
// 时序寄存器
always @(posedge clk) begin
if (rst) begin
state_r <= ST_IDLE;
wr_r <= 1'b0;
addr_r <= 16'd0;
data_r <= 16'd0;
rdata_r <= 16'd0;
err_r <= 1'b0;
end else begin
state_r <= state_n;
wr_r <= wr_n;
addr_r <= addr_n;
data_r <= data_n;
rdata_r <= rdata_n;
err_r <= err_n;
end
end
// 状态切换
always @(*) begin
state_n = state_r;
case (state_r)
ST_IDLE: begin
if (cmd_handshake)
state_n = s_axis_tdata_i[32] ? ST_AW : ST_AR;
end
ST_AW: begin
if (aw_handshake)
state_n = ST_W;
end
ST_W: begin
if (w_handshake)
state_n = ST_B;
end
ST_B: begin
if (b_handshake)
state_n = ST_IDLE;
end
ST_AR: begin
if (ar_handshake)
state_n = ST_R;
end
ST_R: begin
if (r_handshake && m_axi_rlast_i)
state_n = ST_RSP;
end
ST_RSP: begin
if (rsp_handshake)
state_n = ST_IDLE;
end
default: begin
state_n = ST_IDLE;
end
endcase
end
// 数据锁存
always @(*) begin
wr_n = wr_r;
addr_n = addr_r;
data_n = data_r;
rdata_n = rdata_r;
err_n = err_r;
if (state_r == ST_IDLE) begin
err_n = 1'b0;
if (cmd_handshake) begin
wr_n = s_axis_tdata_i[32];
addr_n = s_axis_tdata_i[31:16];
data_n = s_axis_tdata_i[32] ? s_axis_tdata_i[15:0] : 16'h0000;
end
end
if (b_handshake)
err_n = (m_axi_bresp_i != 2'b00);
if (r_handshake)
rdata_n = m_axi_rdata_i;
end
// AXI输出
always @(*) begin
m_axi_awaddr_o = addr_r;
m_axi_awvalid_o = (state_r == ST_AW);
m_axi_wdata_o = data_r;
m_axi_wlast_o = (state_r == ST_W);
m_axi_wvalid_o = (state_r == ST_W);
m_axi_bready_o = (state_r == ST_B);
m_axi_araddr_o = addr_r;
m_axi_arvalid_o = (state_r == ST_AR);
m_axi_rready_o = (state_r == ST_R);
rd_axis_tdata_o = {addr_r, rdata_r};
rd_axis_tvalid_o = (state_r == ST_RSP);
rd_axis_tlast_o = (state_r == ST_RSP);
axi_err_o = err_r;
end
endmodule