module mdio_rsp_to_uart_tx #(
parameter [15:0] TC_HEADER = 16'h5418,
parameter [7:0] RD_RSP = 8'h01,
parameter [7:0] WR_RSP = 8'h02,
parameter [7:0] WR_OK = 8'h55,
parameter [7:0] WR_ERR = 8'hAA
)(
input wire sys_clk,
input wire sys_rst, // 同步高有效
input wire rd_rsp_valid_i, // 读返回有效
input wire [15:0] rd_addr_i, // 读地址
input wire [15:0] rd_data_i, // 读数据
output wire rd_rsp_ready_o, // 读返回接收
input wire wr_rsp_valid_i, // 写返回有效
input wire wr_rsp_err_i, // 写返回错误
output wire wr_rsp_ready_o, // 写返回接收
output reg uart_tx_valid_o, // 串口发送valid
input wire uart_tx_ready_i, // 串口发送ready
output reg [7:0] uart_tx_data_o, // 串口发送数据
output reg uart_tx_last_o // 串口发送最后1字节
);
localparam [3:0] ST_IDLE = 4'b0001,
ST_SEND = 4'b0010,
ST_DONE = 4'b0100;
localparam [7:0] RD_LEN = 8'd11;
localparam [7:0] WR_LEN = 8'd8;
reg [3:0] state_r, state_n; // 状态
reg is_rd_r, is_rd_n; // 当前为读响应
reg [15:0] addr_r, addr_n; // 地址锁存
reg [15:0] data_r, data_n; // 数据锁存
reg err_r, err_n; // 错误锁存
reg [3:0] byte_cnt_r, byte_cnt_n; // 发送字节计数
reg [15:0] sum_r, sum_n; // 校验和
wire uart_handshake = uart_tx_valid_o & uart_tx_ready_i;
wire idle_accept_rd = (state_r == ST_IDLE) & rd_rsp_valid_i;
wire idle_accept_wr = (state_r == ST_IDLE) & (~rd_rsp_valid_i) & wr_rsp_valid_i;
assign rd_rsp_ready_o = (state_r == ST_IDLE);
assign wr_rsp_ready_o = (state_r == ST_IDLE) & (~rd_rsp_valid_i);
// 时序
always @(posedge sys_clk) begin
if (sys_rst) begin
state_r <= ST_IDLE;
is_rd_r <= 1'b0;
addr_r <= 16'd0;
data_r <= 16'd0;
err_r <= 1'b0;
byte_cnt_r <= 4'd0;
sum_r <= 16'd0;
end else begin
state_r <= state_n;
is_rd_r <= is_rd_n;
addr_r <= addr_n;
data_r <= data_n;
err_r <= err_n;
byte_cnt_r <= byte_cnt_n;
sum_r <= sum_n;
end
end
// 状态切换
always @(*) begin
state_n = state_r;
case (state_r)
ST_IDLE: begin
if (rd_rsp_valid_i | wr_rsp_valid_i)
state_n = ST_SEND;
end
ST_SEND: begin
if (uart_handshake && uart_tx_last_o)
state_n = ST_DONE;
end
ST_DONE: begin
state_n = ST_IDLE;
end
default: begin
state_n = ST_IDLE;
end
endcase
end
// 数据锁存与计数
always @(*) begin
is_rd_n = is_rd_r;
addr_n = addr_r;
data_n = data_r;
err_n = err_r;
byte_cnt_n = byte_cnt_r;
sum_n = sum_r;
if (state_r == ST_IDLE) begin
byte_cnt_n = 4'd0;
sum_n = 16'd0;
if (idle_accept_rd) begin
is_rd_n = 1'b1;
addr_n = rd_addr_i;
data_n = rd_data_i;
err_n = 1'b0;
end else if (idle_accept_wr) begin
is_rd_n = 1'b0;
addr_n = 16'd0;
data_n = 16'd0;
err_n = wr_rsp_err_i;
end
end else if (state_r == ST_SEND && uart_handshake) begin
byte_cnt_n = byte_cnt_r + 1'b1;
if (!uart_tx_last_o && byte_cnt_r >= 4'd2)
sum_n = sum_r + uart_tx_data_o;
end
end
// 输出数据
always @(*) begin
uart_tx_valid_o = (state_r == ST_SEND);
uart_tx_data_o = 8'd0;
uart_tx_last_o = 1'b0;
if (is_rd_r) begin
case (byte_cnt_r)
4'd0: uart_tx_data_o = TC_HEADER[15:8];
4'd1: uart_tx_data_o = TC_HEADER[7:0];
4'd2: uart_tx_data_o = 8'h00;
4'd3: uart_tx_data_o = 8'h05;
4'd4: uart_tx_data_o = RD_RSP_TY;
4'd5: uart_tx_data_o = addr_r[15:8];
4'd6: uart_tx_data_o = addr_r[7:0];
4'd7: uart_tx_data_o = data_r[15:8];
4'd8: uart_tx_data_o = data_r[7:0];
4'd9: uart_tx_data_o = sum_r[15:8];
4'd10: begin
uart_tx_data_o = sum_r[7:0];
uart_tx_last_o = 1'b1;
end
default: uart_tx_data_o = 8'd0;
endcase
end else begin
case (byte_cnt_r)
4'd0: uart_tx_data_o = TC_HEADER[15:8];
4'd1: uart_tx_data_o = TC_HEADER[7:0];
4'd2: uart_tx_data_o = 8'h00;
4'd3: uart_tx_data_o = 8'h02;
4'd4: uart_tx_data_o = WR_RSP_TY;
4'd5: uart_tx_data_o = err_r ? WR_ERR : WR_OK;
4'd6: uart_tx_data_o = sum_r[15:8];
4'd7: begin
uart_tx_data_o = sum_r[7:0];
uart_tx_last_o = 1'b1;
end
default: uart_tx_data_o = 8'd0;
endcase
end
end
endmodule