axis转axi模块

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
posted @ 2026-06-10 08:45  Oppenic  阅读(8)  评论(0)    收藏  举报