之前的课程中,我们实现了高速通信分层设计–FII-PRA006 开发板(Altera)的实验。 这一节课,我们要将整个工程移植到Xilinx FPGA上。 这里,我们选用FII-PRX100-D 开发板。
实验目的:
工程环境:
Vivado 2018.2
FII-PRX100-D 开发板 (ARTIX 100T XILINX FPGA)
本实验在高速通信分层设计—PRA006开发板实验(Altera)的基础上做出修改而成的,通篇以修改后的源代码呈现给大家,在每个程序后面有对应的相关修改的解释。
1 顶层工程代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
`timescale 1 ns / 1 ps //`define SIM module top #( parameter IDLE = 10'b1010_1010_10 ) `ifdef SIM (); parameter PERIOD = 20 ; //周期20 reg inclk ; // 模拟板级提供的输入时钟 initial begin inclk = 1'b0; #(PERIOD/2); forever #(PERIOD/2) inclk = ~inclk; end reg pll_rst; //实体模块PLL的rst信号 wire tx_p; wire tx_n; wire rx_p; wire rx_n; assign rx_p = tx_p; assign rx_n = tx_n; initial begin pll_rst=1'b1; #50 pll_rst=1'b0; #50000; $stop; end `else ( input inclk, output tx_p, output tx_n, input rx_p, input rx_n, output LED ); `endif wire pll_locked; wire reset = !pll_locked; (* mark_debug = "true" *)wire tx_rdy; (* mark_debug = "true" *)reg [ 7: 0 ] tx_data; (* mark_debug = "true" *)reg tx_en; (* mark_debug = "true" *)reg tx_vld; (* mark_debug = "true" *)wire tx_vld_ack; (* mark_debug = "true" *)wire rx_data_vld; (* mark_debug = "true" *)wire rx_data_rdy; (* mark_debug = "true" *)wire ko; (* mark_debug = "true" *)wire [ 7: 0 ] rx_data; wire clk_100M; localparam LEN = 16; reg [ 7: 0 ] frame_len; reg [ 2: 0 ] tx_st; always@( posedge clk_100M or posedge reset ) if ( reset ) begin tx_vld <= 1'b0; tx_en <= 1'b0; frame_len <= 0; tx_data <= 0; tx_st <= 0; end else begin case ( tx_st ) 0: begin tx_vld <= 1'b0; tx_en <= 1'b0; tx_data <= 0; frame_len <= 0; tx_st <= 1; end 1: begin tx_en <= 1'b0; tx_vld <= 1'b1; if ( frame_len == LEN ) begin tx_vld <= 1'b0; tx_st <= 3; end else if ( tx_rdy ) begin tx_en <= 1'b1; tx_st <= 2; end end 2: begin tx_en <= 1'b0; frame_len <= frame_len + 1; tx_data <= tx_data + 1; tx_st <= 1; end 3: begin frame_len <= 0; tx_vld <= 1'b0; tx_en <= 1'b0; if ( tx_vld_ack ) tx_st <= 1; end default: tx_st <= 0; endcase end //======================================================================================= (* mark_debug = "true" *)wire tx; (* mark_debug = "true" *)wire rx; IBUFDS #( .DIFF_TERM ("TRUE"), // Differential Termination .IBUF_LOW_PWR ("TRUE"), // Low power="TRUE", Highest performance="FALSE" .IOSTANDARD ("LVDS_25") // Specify the input I/O standard ) IBUFDS_rx_inst ( .O (rx), // Buffer output .I (rx_p), // Diff_p buffer input (connect directly to top-level port) .IB (rx_n) // Diff_n buffer input (connect directly to top-level port) ); OBUFDS #( .IOSTANDARD ("LVDS_25"),// Specify the output I/O standard .SLEW ("SLOW") // Specify the output slew rate ) OBUFDS_tx_inst ( .O (tx_p), // Diff_p output (connect directly to top-level port) .OB (tx_n), // Diff_n output (connect directly to top-level port) .I (tx) // Buffer input ); hs_txrx #( .IDLE (IDLE) ) hs_txrx_inst ( .inclk (inclk), .pll_rst (pll_rst), .tx_rdy (tx_rdy), .tx_vld (tx_vld), .tx_data (tx_data), .tx_en (tx_en), .tx_vld_ack (tx_vld_ack), .tx (tx), .rx (rx), .rx_data_vld(rx_data_vld), .rx_data_rdy(rx_data_rdy), .ko (ko), .rx_data (rx_data), .clk_100M (clk_100M), .pll_locked (pll_locked) ); `ifndef SIM reg [31:0] led_cnt = 0; always @ (posedge clk_100M) led_cnt <= led_cnt + 1; assign LED = led_cnt[25]; `endif endmodule |
Vivado工程的顶层代码中对外端口与Quartus工程中的对外端口设计不同。 Xilinx FPGA 使用IBUFDS,OBUFDS 原语实现单端信号rx,tx 到差分信号的转换,所以在端口上的定义为tx_p, tx_n; rx_p, rx_n。单端信号到差分信号的转换也可以使用Xilinx SelectIO IP 核实现。 本文使用IBUFDS,OBUFDS 原语。
在仿真程序中, 不再使用tx_rx 信号连接 发送和接收端口, 而是使用 assign rx_p = tx_p; assign rx_n = tx_n; 来实现。
2 修改hs_txrx.v代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* pll1 pll1_inst ( .areset ( pll_rst ), //1'b0; .inclk0 ( inclk ), .c0 ( clk_100M ), .c1 ( clk_400M ), .locked ( pll_locked ) ); */ pll1 pll1_inst ( // Clock out ports .clk_out1 (clk_100M), // output clk_out1 .clk_out2 (clk_400M), // output clk_out2 // Status and control signals .reset (pll_rst), // input reset .locked (pll_locked), // output locked // Clock in ports .clk_in1 (inclk) // input clk_in1 ); |
将Altera PLL替换为Xilinx clock IP。
Xilinx clock IP 例化如下:

图1

图2
3 修改tx_pmd.v代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module tx_PMD ( input tx_in, output tx_out ); assign tx_out = tx_in; /* IO_TX IO_TX_INST ( .tx_in ( tx_in ), .tx_out ( tx_out ) ); */ endmodule |
在Quartus 工程中, 使用IO_TX IP 核, 当移植到Xilinx FPGA 时, 这里将不再使用IP核, 而是在top.v 文件中使用 OBUFDS 来实现.
4 修改recv_bit_pmd.v代码:
|
1 2 3 4 5 6 7 8 |
assign rx_out = rx; /* IO_RX IO_RX_inst ( .rx_in ( rx ), .rx_out ( rx_out ) ); */ |
同样, 注释Quartus 工程中的IO_RX IP , 而是在top.v 文件中使用 IBUFDS 原语实现。
5 对比移植altera IP 到 Xilinx IP:
Quartus 工程 , 使用PLL IP核, IO_TX和IO_RX IP核 。 其中PLL 输入50M 时钟, 输出 100M, 400M 时钟。
Vivado 工程: 使用PLL IP核,IBUFDS 和 OBUFDS 原语。 其中PLL 也是输入50M 时钟, 输出为100M,400M 时钟,Xilinx需要使用xBUFDS (x 表示 I 或者 O)原语实现单端信号到差分信号的转换。
6 实现相关的管脚约束:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#================================================== #clk set_property -dict {PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports inclk] create_clock -period 20.000 -name OSC_CLK -waveform {0.000 10.000} [get_ports inclk] set_property -dict {PACKAGE_PIN R7 IOSTANDARD LVCMOS33} [get_ports pll_rst] set_property -dict {PACKAGE_PIN N23 IOSTANDARD LVCMOS33} [get_ports LED] set_property -dict {PACKAGE_PIN J6 IOSTANDARD LVDS_25 } [get_ports tx_p] set_property -dict {PACKAGE_PIN J5 IOSTANDARD LVDS_25 } [get_ports tx_n] set_property -dict {PACKAGE_PIN K7 IOSTANDARD LVDS_25 DIFF_TERM 1} [get_ports rx_p] set_property -dict {PACKAGE_PIN K6 IOSTANDARD LVDS_25 DIFF_TERM 1} [get_ports rx_n] |
Xilinx文档中相关阻抗匹配部分如下所示:

图3
|
1 |
set_property -dict {PACKAGE_PIN K7 IOSTANDARD <span style="color: #0000ff;">LVDS_25</span> <span style="color: #0000ff;">DIFF_TERM</span> <span style="color: #0000ff;">1</span>} [get_ports rx_p] |
在管脚约束文件中定义管脚为lvds_25 标准, 同时使用DIFF_TERM 1或者DIFF_TERM TRUE,表示使用内部差分电阻。
注:在使用Artix 系列FPGA 使用LVDS差分功能时, 需要管脚连接的bank 电压 <= 2.5v 。 目前,我们使用tx_p, tx_n, rx_p, rx_n 都是连接在bank35中。 所以需要将bank35 的电压设置为 <= 2.5v ,否则FPGA 不会工作,因此这里选择bank35电压为1.8V。如图4所示:

图4
7 . FII-PRX100-D高速通信回环实验设置
- 原理图部分如图5,图6所示:

图5

图6
- 开发板硬件连线如图7所示:

图7
8 使用ILA (mark_debug)调试高速通信信号:

图8

图9
示波器波形:

图10
其中 紫色信号连接tx_p, 黄色信号连接 tx_n。 白色信号为 tx_p – tx_n 得到相关的差分信号。
由于通信工程当中的逻辑验证部分在之前的文章中已经介绍过,这里只演示了在线的硬件调试部分内容。
关于详细的实验内容,请参见对应的视频。
vivado 2018.2 工程代码:
[content_control]
[/content_control]