Menu Close

高速通信分层设计—PRA006开发板实验(Altera)

在之前的章节中,我们学习了高速通信的发送,接收等模块的设计, 同时展示了仿真程序的使用。这节课我们在FII-PRA006 Altera FPGA 开发板上做一个综合实验,验证高速通信的数据发送和接收。

之前的高速通信工程设计:

图1

在之前的工程设计中, 我们使用仿真程序来发送数据,检查算法的实现。 本节课程将对工程进行改造。

实验目的:

  1. 用FII-PRA006 FPGA开发板验证高速串行通信工程
  2. 学习IP核开发流程:分析需求,设计IP核,仿真验证,到真实的下板验证,最后封装
  3. 用示波器观察实际电路上的波形
  4. 使用SignalTap Logic Analyzer工具来抓取通信中的数据包

 

1.设计顶层模块

顶层模块是由前面工程的仿真文件tb_8b10b.v修改生成的,新添加了板载的时钟输入inclk,系统pll_rst 信号, 以及 tx,rx 的LVDS信号。使用宏在仿真和下板验证之间切换,详情见下列代码。

 

图2

重新设计的顶层模块,top.v 将包括hs_txrx.v 文件。

代码如下:

`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_rx;   			// 收发在testbench的回环信号

    
initial begin
    pll_rst=1'b1;
    #50 pll_rst=1'b0;
    
    #50000;
    $stop;
end	
`else
(
    input  inclk,

    output tx,
    input  rx,

    input  pll_rst
);
`endif

wire pll_locked;

wire reset = !pll_locked;

wire tx_rdy;
reg [ 7: 0 ] tx_data;
reg tx_en;

reg tx_vld;
wire tx_vld_ack;

wire rx_data_vld;
wire rx_data_rdy;
wire ko;
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


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),
`ifdef SIM
    .tx         (tx_rx),
    .rx         (tx_rx),
`else
    .tx         (tx),
    .rx         (rx),
`endif
    .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)
);

endmodule

 

打开SIM宏后,仿真结果如图3所示:

图3

图3中显示出修改后仿真结果和之前课程介绍的一致。

 

2.增加recv_data_link.v模块

之前的工程中PCS层的信号直接穿透到应用层。本节内容添加了接收端的数据链路层模块,代码如下:

module recv_data_link
#(
    parameter SYNC_START1 = 10'b0011111010,     //K28.5 with dipin=0;
    parameter SYNC_START2 = 10'b1100000101,     //K28.5 with dispin=1

    parameter SYNC_END1 = 10'b0011111001,       //K28.1 with dipin=0;
    parameter SYNC_END2 = 10'b1100000110        //K28.1  with dispin=1
)

(
    input rst,
    input clk_100M ,
    input clk_400M ,
    input rx,
    output rx_ko,
    output [ 7: 0 ] rx_data,
    output rx_data_rdy,
    output rx_data_vld
);

wire phy_rx_ko;
wire [ 7: 0 ] phy_rx_data;
wire phy_rx_data_rdy;
wire phy_rx_data_vld;        

assign rx_ko       = phy_rx_ko;
assign rx_data     = phy_rx_data;
assign rx_data_rdy = phy_rx_data_rdy;
assign rx_data_vld = phy_rx_data_vld;        



recv_data_pcs #
(
    .SYNC_START1    ( 10'b0011111010 ),       //K28.5 with dipin=0;
    .SYNC_START2    ( 10'b1100000101 ),       //K28.5 with dispin=1

    .SYNC_END1      ( 10'b0011111001 ),       //K28.1 with dipin=0;
    .SYNC_END2      ( 10'b1100000110 )        //K28.1 with dispin=1
)
recv_data_pcs_inst
(
    .rst            ( rst ),
    .clk_100M       ( clk_100M ),
    .clk_400M       ( clk_400M ),
    .rx             ( rx ),
    .pcs_rx_data_rdy ( phy_rx_data_rdy ),
    .pcs_ko         ( phy_rx_ko ),
    .pcs_rx_data    ( phy_rx_data ),
    .pcs_rx_data_vld ( phy_rx_data_vld )
);


endmodule

 

3.hs_rxtx.v模块修改

因为接收端新添加了数据链路层,所以hs_txrx.v模块也需要做出相应的修改,代码如下:

module hs_txrx
#(
    parameter IDLE = 10'b1010_1010_10
)
(
    input inclk,
    input pll_rst,

    output tx_rdy,
    input tx_vld,
    input [ 7: 0 ] tx_data,
    input tx_en,
    output tx_vld_ack,

    output tx,
    input rx,


    output rx_data_vld,
    output rx_data_rdy,
    output ko,
    output [ 7: 0 ] rx_data,

    output clk_100M,
    output pll_locked
);


wire clk_400M;
wire rst = !pll_locked;


trans_data_link
#(
    .IDLE       ( IDLE )
)
trans_data_link_inst
(
    .rst        ( rst ),
    .clk_100M   ( clk_100M ),
    .tx_rdy     ( tx_rdy ),
    .tx_vld     ( tx_vld ),
    .tx_data    ( tx_data ),
    .tx_en      ( tx_en ),
    .tx_vld_ack ( tx_vld_ack ),
    .tx_out     ( tx )
);

recv_data_link #
(
    .SYNC_START1    ( 10'b0011111010 ),       //K28.5 with dipin=0;
    .SYNC_START2    ( 10'b1100000101 ),       //K28.5 with dispin=1

    .SYNC_END1      ( 10'b0011111001 ),       //K28.1 with dipin=0;
    .SYNC_END2      ( 10'b1100000110 )        //K28.1 with dispin=1
)
recv_data_link_inst
(
    .rst            ( rst ),
    .clk_100M       ( clk_100M ),
    .clk_400M       ( clk_400M ),
    .rx             ( rx ),
    .rx_data_rdy    ( rx_data_rdy ),
    .rx_ko          ( ko ),
    .rx_data        ( rx_data ),
    .rx_data_vld    ( rx_data_vld )
);

pll1 pll1_inst
(
    .areset     ( pll_rst ),    //1'b0;
    .inclk0     ( inclk ),
    .c0         ( clk_100M ),
    .c1         ( clk_400M ),
    .locked     ( pll_locked )

);


endmodule

 

4.增加管脚约束

图4-1

注意图4-1中分配管脚时,tx和tx(n)的I/O Standard不是LVDS而是LVDS_E_3R。LVDS_E_3R中的“E”表示Emulated LVDS,“3R”指Emulated LVDS外接电阻网络。

The Intel Cyclone 10 LP left and right I/O banks (row I/Os) support true LVDS transmitters. The top and bottom I/O banks support emulated LVDS transmitters with external resistors.

图4-2

本工程使用的的LVDS输出,输入方式。 所以,我们需要对管脚进行约束。包括inclk, pll_rst, tx (txn), rx (rxn)。 其中tx , rx 为LVDS标准。

根据FII-PRA006 原理图,我们使用:

  • FII-PRA006板载时钟,
  • 开发板中的down key 作为pll_rst 信号。
  • PMOD GPIO2 接口 IO8_p,IO8_n,作为tx 的LVDS
  • PMOD GPIO2 接口 IO10_p,IO10_n,作为rx 的LVDS

 

图5

注意: 在选择LVDS的时候, 需要将FII-PRA006的硬件FPGA Bank 电压设置为2.5V。

图6

图7

图8

查看原理图,根据图5-图8 ,确定FPGA的输入输出管脚。

 

在板载实验中, 我们使用杜邦线,链接tx,rx LVDS对。在一块FPGA板上实现LVDS高速通信, 当然,也可以使用2块FPGA板,使用杜邦线链接。 注意, 在距离比较远的2个板子之间通信, 尽量使用双绞线。

 

图9

5.添加SignalTap Logic Analyzer

图10

在SignalTap 中增加我们需要测试的信号,包括:

  • tx_rdy
  • tx_vld
  • tx_data[7:0]
  • tx_en
  • tx_vld_ack
  • rx_data[7:0]
  • rx_data_rdy
  • ko
  • rx_data_vld
  • rx
  • tx

同时设置trigger 条件为 tx_vld。

 

图11

在SignalTap 采样时, 我们使用clk_100M 时钟, 采样深度为1k。

6.板载测试结果

FII-PRA006 开发板回环实验

 

图12

根据图12,1)选择JTAG驱动,2)选择sof文件,3)下载sof文件。

图13

从实际实验的结果中, 可以看出, 发送端的数据被接收端正确的接收。 这一点和仿真程序中测试的结果相同。证明我们设计的整个算法是正确的。

板对板的LVDS高速通讯实验

图14

 

图15

图15 中可以看出, 在一个包结束的时候, k28.1 的结束标识,不同的包, 产生不同的k28.1 (正码,反码)。

图16

图16 为示波器抓取的LVDS差分信号当中的一根信号,可以看出所发送出来的数据流。

总结:

我们使用了开发板内的回环测试, 和板对板的高速串行通讯实验, 可以看出, 在不同的2个板子之间, 也是可以正常通讯的。有条件的同学可以试试逐步加长传输线的距离, 比如使用5m, 10m , 100m 的线长, 再次观察实验的结果。

 

Quartus工程下载(Quartus 20.1):

[content_control]

high_speed_txrx_pcs8b10b.zip

[/content_control]

Posted in FPGA, FPGA 教材教案, Verilog, Verilog, 教材与教案, 文章

发表回复

相关链接