难点:
多时钟的切换
相位偏移的数据同步
原语的使用
RTL结构视图与时钟网络
工程文件的路径:
其中RGMII_tx_ctrl模块为FPGA测试发送数据模块,依赖于仿真
RGMII_tx_ctrl的原语调用:
module RGMII_tx_ctrl(
input wire sclk,//125M
input wire rst_n,
//
input wire [7:0] tx_d,//仿真提供的数据输入data_in
input wire tx_en,//使能信号
input wire tx_c,//相移时钟
//
output [3:0]tx_data,
output tx_dv,//en
output tx_clk//PHY采集数据时钟
);
//tx_clk
ODDR2 #(
.DDR_ALIGNMENT("C0"), // Sets output alignment to "NONE", "C0" or "C1"
.INIT(1'b0), // Sets initial state of the Q output to 1’b0 or 1’b1
.SRTYPE("ASYNC") // Specifies "SYNC" or "ASYNC" set/reset
)
ODDR2_TXC(
.Q(tx_clk), // 1-bit DDR output data
.C0(tx_c), // 1-bit clock input
.C1(~tx_c), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D0(1'b1), // 1-bit data input (associated with C0)
.D1(1'b0), // 1-bit data input (associated with C1)
.R(1'b0), // 1-bit reset input
.S(~rst_n) // 1-bit set input
);
//tx_data
genvar i;
generate
for(i=0;i<4;i=i+1)begin
ODDR2 #(
.DDR_ALIGNMENT("C0"), // Sets output alignment to "NONE", "C0" or "C1"
.INIT(1'b0), // Sets initial state of the Q output to 1’b0 or 1’b1
.SRTYPE("ASYNC") // Specifies "SYNC" or "ASYNC" set/reset
)
ODDR2_TDATA(
//tx_data是和sclk同步的
.Q(tx_data[i]), // 1-bit DDR output data
.C0(sclk), // 1-bit clock input
.C1(~sclk), // 1-bit clock input
//
.CE(1'b1), // 1-bit clock enable input
.D0(tx_d[i]), // 1-bit data input (associated with C0)
.D1(tx_d[i+4]), // 1-bit data input (associated with C1)
.R(1'b0), // 1-bit reset input
.S(~rst_n) // 1-bit set input
);
end
endgenerate
//tx_dv
ODDR2 #(
.DDR_ALIGNMENT("C0"), // Sets output alignment to "NONE", "C0" or "C1"
.INIT(1'b0), // Sets initial state of the Q output to 1’b0 or 1’b1
.SRTYPE("ASYNC") // Specifies "SYNC" or "ASYNC" set/reset
)
ODDR2_TXEN(
.Q(tx_dv), // 1-bit DDR output data
.C0(sclk), // 1-bit clock input
.C1(~sclk), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D0(tx_en), // 1-bit data input (associated with C0)
.D1(tx_en), // 1-bit data input (associated with C1)
.R(1'b0), // 1-bit reset input
.S(~rst_n) // 1-bit set input
);
endmodule
module top_RGMII(
input wire sclk,
input wire rst_n,
//
input wire rx_clk,
input wire rx_dv,
input wire [3:0]rx_data,
output wire phy_rst_n
//output wire tout
);
reg [21:0]rst_cnt;
wire [7:0]o_data,rd_data;
wire rx_en;
wire clk_50M,clk_125M,clk_125M_90;
wire rd_flag_r;
//assign tout = rx_en|(&o_data);//for test
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
gen_clk gen_clk_inst
(// Clock in ports
.clkin(sclk), // IN
// Clock out ports
.clk_125M(clk_125M), // OUT
.clk_125M_90(clk_125M_90), // OUT
.clk_50M(clk_50M)
); // OUT
// INST_TAG_END ------ End INSTANTIATION Template ---------
always @(posedge clk_125M)//clk_50M
if(!rst_n)
rst_cnt <= 'd0;
else if(rst_cnt[21]== 'd0)//
rst_cnt <= rst_cnt + 'd1;
assign phy_rst_n = rst_cnt[21];//上电复位延时大于4ms
RGMII_rx_ctrl RGMII_rx_ctrl_inst(
//from phy
.rx_clk(rx_clk), //125M
.rst_n(rst_n),
.rx_dv(rx_dv),//千兆网同步有效信号,双沿采样 上升沿=dv 下降沿=deer
.rx_data(rx_data),
.rx_en(rx_en),
.o_data(o_data)//单沿采样数据
);
SYNC_ctrl SYNC_ctrl_inst(
.rx_clk(rx_clk),
.ddr_clk(clk_125M),
.rst_n(rst_n),
//
.rx_en(rx_en),
.data_in(o_data),//o_d=ata
//
.rd_data(rd_data),
.rd_flag_r(rd_flag_r)
);
endmodule
测试模块
module tb_RGMII();
reg sclk,rst_n;
wire rx_clk;
wire rx_dv;
wire [3:0] rx_data;
wire phy_rst_n;
reg clk;
reg tx_c;
reg [7:0] tx_d;
reg tx_en;
wire [3:0]tx_data;
initial begin
sclk =0;
rst_n =0;
#1000
rst_n=1;
end
always #10 sclk = ~sclk;
initial begin
force clk = top_RGMII_inst.clk_125M;
force tx_c = top_RGMII_inst.clk_125M_90;
end
initial begin
tx_d=0;
tx_en =0;
gen_frame();
end
RGMII_tx_ctrl RGMII_tx_ctrl_inst(
.sclk(clk),
.rst_n(rst_n),
.tx_d(tx_d),//仿真提供的数据输入data_in
.tx_en(tx_en),//使能信号
.tx_c(tx_c),//相移时钟
.tx_data(tx_data),
.tx_dv(tx_dv),//en
.tx_clk(tx_clk)//PHY采集数据时钟
);
top_RGMII top_RGMII_inst(
.sclk(sclk),
.rst_n(rst_n),
.rx_clk(tx_clk),
.rx_dv(tx_dv),
.rx_data(tx_data),
.phy_rst_n(phy_rst_n),
.tout(tout)
);
task gen_frame();
integer i;
begin
@(posedge phy_rst_n);
for(i =0 ; i<128 ;i=i+1)
begin
@(posedge clk);
tx_en <= 1'b1;
if(i<7)
tx_d <= 8'h55;
else if(i==7)
tx_d <= 8'hd5;
else
tx_d <= i-8;
end
@(posedge clk)
tx_en <= 1'b0;
tx_d <= 'd0;
end
endtask
endmodule