用Verilog写一段关于dp83848i的rmii程序
时间: 2023-05-31 16:01:23 浏览: 151
下面是一个使用Verilog编写的dp83848i的RMII程序示例:
module dp83848i_rmii (
input wire clk,
input wire reset,
input wire [1:0] rx_data,
output wire [1:0] tx_data,
output wire tx_en,
output wire tx_er,
input wire col,
input wire crs_dv,
input wire [1:0] mdio,
input wire mdc
);
// 定义寄存器地址
parameter ID1 = 32'h20005c01;
parameter ID2 = 32'h20005c02;
parameter BMCR = 32'h20005c00;
parameter BMSR = 32'h20005c01;
parameter ANAR = 32'h20005c04;
parameter ANLPAR = 32'h20005c05;
parameter ANER = 32'h20005c06;
parameter PHY_CTRL = 32'h20005c10;
parameter TX_CTRL = 32'h20005c12;
parameter RX_CTRL = 32'h20005c14;
// 定义常量
parameter RMII_CLK_DIV = 2; // RMII 时钟分频器
parameter RX_EN = 2'b10; // 接收使能
parameter TX_EN = 2'b10; // 发送使能
parameter TX_ER = 1'b1; // 发送错误
parameter AN_ENABLE = 1'b1; // 使能自协商
parameter AN_RESTART = 1'b10000; // 自协商重启
// 定义寄存器变量
reg [15:0] reg_data;
reg [4:0] reg_addr;
reg reg_rd;
reg reg_wr;
// 定义内部信号
wire [15:0] phy_id; // PHY ID
wire [15:0] aneg_ability; // 自协商能力
wire [15:0] aneg_lp_ability; // 对侧自协商能力
wire [15:0] aneg_err; // 自协商错误
wire [15:0] phy_ctrl; // PHY 控制寄存器
wire [15:0] tx_ctrl; // 发送控制寄存器
wire [15:0] rx_ctrl; // 接收控制寄存器
// 定义发送数据寄存器
reg [7:0] tx_data_reg;
reg tx_en_reg;
reg tx_er_reg;
// 定义状态机变量
parameter IDLE = 2'd0;
parameter READ = 2'd1;
parameter WRITE = 2'd2;
reg [1:0] state;
// 时钟分频
reg [RMII_CLK_DIV-1:0] clk_div;
always @(posedge clk) begin
if (reset) begin
clk_div <= 0;
end else begin
clk_div <= clk_div + 1;
end
end
// 读取PHY ID
assign mdio = (state == READ || state == WRITE) ? 1'b0 : 1'b1;
assign mdio[0] = (state == READ && !reg_rd) ? 1'b1 : 1'b0;
assign mdio[1] = (state == WRITE && reg_wr) ? 1'b1 : 1'b0;
assign tx_data = (state == WRITE) ? reg_data[7:0] : 2'b00;
assign col = 1'b0;
assign crs_dv = (state == READ && !reg_rd) ? 1'b1 : 1'b0;
always @(posedge clk) begin
if (reset) begin
state <= IDLE;
reg_addr <= 0;
reg_rd <= 0;
reg_wr <= 0;
reg_data <= 0;
tx_data_reg <= 0;
tx_en_reg <= 0;
tx_er_reg <= 0;
end else begin
case (state)
IDLE:
if (clk_div == RMII_CLK_DIV) begin
state <= READ;
reg_addr <= ID1[15:0];
reg_rd <= 1;
end
READ:
if (clk_div == RMII_CLK_DIV) begin
reg_rd <= 0;
state <= WRITE;
reg_addr <= BMCR[15:0];
reg_data <= AN_ENABLE;
reg_wr <= 1;
end
WRITE:
if (clk_div == RMII_CLK_DIV) begin
reg_wr <= 0;
state <= READ;
reg_addr <= BMSR[15:0];
reg_rd <= 1;
end
default:
state <= IDLE;
endcase
end
end
// 读取寄存器值
always @(posedge clk) begin
if (reset) begin
phy_id <= 0;
aneg_ability <= 0;
aneg_lp_ability <= 0;
aneg_err <= 0;
phy_ctrl <= 0;
tx_ctrl <= 0;
rx_ctrl <= 0;
end else begin
case (reg_addr)
ID1:
phy_id <= reg_data;
ID2:
phy_id <= {reg_data[7:0], phy_id[7:0]};
BMCR:
phy_ctrl <= {reg_data[15:0]};
BMSR:
aneg_err <= {reg_data[15:0]};
ANAR:
aneg_ability <= {reg_data[15:0]};
ANLPAR:
aneg_lp_ability <= {reg_data[15:0]};
ANER:
aneg_err <= {reg_data[15:0]};
PHY_CTRL:
phy_ctrl <= {reg_data[15:0]};
TX_CTRL:
tx_ctrl <= {reg_data[15:0]};
RX_CTRL:
rx_ctrl <= {reg_data[15:0]};
endcase
end
end
// 发送数据
always @(posedge clk) begin
if (reset) begin
tx_data_reg <= 0;
tx_en_reg <= 0;
tx_er_reg <= 0;
end else begin
if (tx_en_reg && !tx_er_reg) begin // 发送完成
tx_data_reg <= 0;
tx_en_reg <= 0;
tx_er_reg <= 0;
end else if (tx_en_reg && tx_er_reg) begin // 发送错误
tx_er_reg <= 0;
end else if (tx_en && !tx_en_reg) begin // 开始发送
tx_data_reg <= tx_data;
tx_en_reg <= 1;
tx_er_reg <= 0;
end else if (tx_en_reg) begin // 继续发送
tx_data_reg <= {tx_data_reg[6:0], col, tx_data_reg[0]};
tx_er_reg <= (tx_er_reg || tx_data_reg[7] != tx_data[7]); // 发送错误检测
end
end
end
// 输出接口
assign tx_data = tx_data_reg;
assign tx_en = tx_en_reg;
assign tx_er = tx_er_reg;
assign phy_ctrl[0] = 1'b1; // 使能 PHY
assign tx_ctrl[1:0] = TX_EN; // 发送使能
assign rx_ctrl[1:0] = RX_EN; // 接收使能
endmodule
阅读全文