vivado SRIO 学习

一、SRIO例化IP模块接口

        用于后面讲解的参考:

srio_gen2_0 your_instance_name (
  .log_clk_in(log_clk_in),                                        // input wire 
  .buf_rst_in(buf_rst_in),                                        // input wire 
  .log_rst_in(log_rst_in),                                        // input wire 
  .gt_pcs_rst_in(gt_pcs_rst_in),                                  // input wire 
  .gt_pcs_clk_in(gt_pcs_clk_in),                                  // input wire 
  .cfg_rst_in(cfg_rst_in),                                        // input wire 
  .deviceid(deviceid),                                            // output wire [15 : 0] 
  .port_decode_error(port_decode_error),                          // output wire 
  .s_axis_ireq_tvalid(s_axis_ireq_tvalid),                        // input wire 
  .s_axis_ireq_tready(s_axis_ireq_tready),                        // output wire 
  .s_axis_ireq_tlast(s_axis_ireq_tlast),                          // input wire 
  .s_axis_ireq_tdata(s_axis_ireq_tdata),                          // input wire [63 : 0] 
  .s_axis_ireq_tkeep(s_axis_ireq_tkeep),                          // input wire [7 : 0] 
  .s_axis_ireq_tuser(s_axis_ireq_tuser),                          // input wire [31 : 0] 
  .m_axis_iresp_tvalid(m_axis_iresp_tvalid),                      // output wire 
  .m_axis_iresp_tready(m_axis_iresp_tready),                      // input wire 
  .m_axis_iresp_tlast(m_axis_iresp_tlast),                        // output wire 
  .m_axis_iresp_tdata(m_axis_iresp_tdata),                        // output wire [63 : 0] 
  .m_axis_iresp_tkeep(m_axis_iresp_tkeep),                        // output wire [7 : 0] 
  .m_axis_iresp_tuser(m_axis_iresp_tuser),                        // output wire [31 : 0] 
  .m_axis_treq_tvalid(m_axis_treq_tvalid),                        // output wire 
  .m_axis_treq_tready(m_axis_treq_tready),                        // input wire 
  .m_axis_treq_tlast(m_axis_treq_tlast),                          // output wire 
  .m_axis_treq_tdata(m_axis_treq_tdata),                          // output wire [63 : 0] 
  .m_axis_treq_tkeep(m_axis_treq_tkeep),                          // output wire [7 : 0] 
  .m_axis_treq_tuser(m_axis_treq_tuser),                          // output wire [31 : 0] 
  .s_axis_tresp_tvalid(s_axis_tresp_tvalid),                      // input wire 
  .s_axis_tresp_tready(s_axis_tresp_tready),                      // output wire 
  .s_axis_tresp_tlast(s_axis_tresp_tlast),                        // input wire 
  .s_axis_tresp_tdata(s_axis_tresp_tdata),                        // input wire [63 : 0] 
  .s_axis_tresp_tkeep(s_axis_tresp_tkeep),                        // input wire [7 : 0] 
  .s_axis_tresp_tuser(s_axis_tresp_tuser),                        // input wire [31 : 0] 
  .s_axi_maintr_rst(s_axi_maintr_rst),                            // input wire 
  .s_axi_maintr_awvalid(s_axi_maintr_awvalid),                    // input wire 
  .s_axi_maintr_awready(s_axi_maintr_awready),                    // output wire 
  .s_axi_maintr_awaddr(s_axi_maintr_awaddr),                      // input wire [31 : 0] 
  .s_axi_maintr_wvalid(s_axi_maintr_wvalid),                      // input wire 
  .s_axi_maintr_wready(s_axi_maintr_wready),                      // output wire 
  .s_axi_maintr_wdata(s_axi_maintr_wdata),                        // input wire [31 : 0] 
  .s_axi_maintr_bvalid(s_axi_maintr_bvalid),                      // output wire 
  .s_axi_maintr_bready(s_axi_maintr_bready),                      // input wire 
  .s_axi_maintr_bresp(s_axi_maintr_bresp),                        // output wire [1 : 0] 
  .s_axi_maintr_arvalid(s_axi_maintr_arvalid),                    // input wire 
  .s_axi_maintr_arready(s_axi_maintr_arready),                    // output wire 
  .s_axi_maintr_araddr(s_axi_maintr_araddr),                      // input wire [31 : 0] 
  .s_axi_maintr_rvalid(s_axi_maintr_rvalid),                      // output wire 
  .s_axi_maintr_rready(s_axi_maintr_rready),                      // input wire 
  .s_axi_maintr_rdata(s_axi_maintr_rdata),                        // output wire [31 : 0] 
  .s_axi_maintr_rresp(s_axi_maintr_rresp),                        // output wire [1 : 0] 
  .gt_clk_in(gt_clk_in),                                          // input wire gt_clk_in
  .drpclk_in(drpclk_in),                                          // input wire drpclk_in
  .refclk_in(refclk_in),                                          // input wire refclk_in
  .buf_lcl_response_only_out(buf_lcl_response_only_out),          // output wire 
  .buf_lcl_tx_flow_control_out(buf_lcl_tx_flow_control_out),      // output wire 
  .idle2_selected(idle2_selected),                                // output wire 
  .idle_selected(idle_selected),                                  // output wire 
  .buf_lcl_phy_buf_stat_out(buf_lcl_phy_buf_stat_out),            // output wire [5 : 0] 
  .phy_clk_in(phy_clk_in),                                        // input wire 
  .gt0_qpll_clk_in(gt0_qpll_clk_in),                              // input wire 
  .gt0_qpll_out_refclk_in(gt0_qpll_out_refclk_in),                // input wire 
  .phy_rst_in(phy_rst_in),                                        // input wire 
  .sim_train_en(sim_train_en),                                    // input wire 
  .phy_mce(phy_mce),                                              // input wire phy_mce
  .phy_link_reset(phy_link_reset),                                // input wire 
  .force_reinit(force_reinit),                                    // input wire 
  .phy_lcl_phy_next_fm_out(phy_lcl_phy_next_fm_out),              // output wire [5 : 0] 
  .phy_lcl_phy_last_ack_out(phy_lcl_phy_last_ack_out),            // output wire [5 : 0] 
  .link_initialized(link_initialized),                            // output wire 
  .phy_lcl_phy_rewind_out(phy_lcl_phy_rewind_out),                // output wire 
  .phy_lcl_phy_rcvd_buf_stat_out(phy_lcl_phy_rcvd_buf_stat_out),  // output wire [5 : 0] 
  .phy_rcvd_mce(phy_rcvd_mce),                                    // output wire 
  .phy_rcvd_link_reset(phy_rcvd_link_reset),                      // output wire 
  .port_error(port_error),                                        // output wire 
  .port_initialized(port_initialized),                            // output wire 
  .clk_lock_in(clk_lock_in),                                      // input wire 
  .mode_1x(mode_1x),                                              // output wire mode_1x
  .port_timeout(port_timeout),                                    // output wire [23 : 0] 
  .srio_host(srio_host),                                          // output wire 
  .phy_lcl_master_enable_out(phy_lcl_master_enable_out),          // output wire 
  .phy_lcl_maint_only_out(phy_lcl_maint_only_out),                // output wire 
  .gtrx_disperr_or(gtrx_disperr_or),                              // output wire 
  .gtrx_notintable_or(gtrx_notintable_or),                        // output wire 
  .phy_debug(phy_debug),                                          // output wire[223 : 0] 
  .srio_txn0(srio_txn0),                                          // output wire 
  .srio_txp0(srio_txp0),                                          // output wire 
  .srio_rxn0(srio_rxn0),                                          // input wire srio_rxn0
  .srio_rxp0(srio_rxp0),                                          // input wire srio_rxp0
  .srio_txn1(srio_txn1),                                          // output wire 
  .srio_txp1(srio_txp1),                                          // output wire 
  .srio_rxn1(srio_rxn1),                                          // input wire srio_rxn1
  .srio_rxp1(srio_rxp1),                                          // input wire srio_rxp1
  .srio_rxn2(srio_rxn2),                                          // input wire srio_rxn2
  .srio_rxp2(srio_rxp2),                                          // input wire srio_rxp2
  .srio_txn2(srio_txn2),                                          // output wire 
  .srio_txp2(srio_txp2),                                          // output wire 
  .srio_rxn3(srio_rxn3),                                          // input wire srio_rxn3
  .srio_rxp3(srio_rxp3),                                          // input wire srio_rxp3
  .srio_txn3(srio_txn3),                                          // output wire 
  .srio_txp3(srio_txp3)                                          // output wire srio_txp3
);

二、例化IP核

        这里只介绍Basic Mode,Advanced Mode我没有用到过,应该也很少用,就不介绍了。

1.Basic Mode

vivado SRIO 学习_第1张图片

vivado SRIO 学习_第2张图片

 (1)Link Width:链路通道数量。

(2)Transfer Frequency:每条通道的波特率。
(3)Reference Clock Frequency :外部输入的参考时钟。
(4)Buffer Configuration: 传输和接收缓冲区的深度可以定制为8、16或32。这个数字表示缓冲区能够存储的数据包数量。选择较小的缓冲区深度可以节省资源(主要是块ram和lut),而最大的缓冲区深度可以获得最大的吞吐量。
(5)Component Device ID :配置设备ID。
(6)Device ID Width:设备ID宽度,应与链接伙伴的设备ID宽度匹配,
(7)Unified Clock:如果用户设计为log_clk(主用户时钟)和phy_clk,使用相同的时钟,请勾选此复选框。选择此选项可以显著降低延迟和资源利用率。
(8)Flow Control:这些选项表明了变送器使用的流量控制类型。
         Transmitter Controlled:选择此选项,core首次尝试使用发射机控制的流控制,如果链接伙伴不支持这种方式,会切换到接收机控制。
        Receiver Controlled:仅接收控制流量控制时选择此选项。该模式采用盲目传输和重试协议的方式控制报文的流量。
(9)Additional transceiver control and status ports:选中此框可启用额外的收发器控制和状态端口。这些端口对应于相应设备GTX/GTP用户指南中同名的收发器端口。这些端口在调试收发链路时很有用。

2.Shared Logic Tab

vivado SRIO 学习_第3张图片
        Include Shared Logic in Example Design:MMCM, Reset logic 和GT COMMON block作为共享逻辑被包含在example design。
        Include Shared Logic in Core:MMCM, Reset logic 和GT COMMON block作为共享逻辑被包含在core当中。

三、Clocks

1.Core Clocks

       通过例化的IP模块我们可以看到,时钟端口简直太多了,log_clk、phy_clk、gt_pcs_clk、gt_clk、refclk、cfg_clk是应该要好好捋清楚一下。

        (1)串行收发器还需要使用收发器专用时钟引脚的参考时钟(refclk),参考时钟频率是在core生成时选择的(可用选项取决于架构和line rate),如下图:(x是可选)。

vivado SRIO 学习_第4张图片

         (2)Serial RapidIO 的 Line Rate 和 Internal Data Width,无论 Line Rate 是多少Internal Data Width都是20b,gt_clk是收发器的时钟信号,那么就有gt_clk = Line Rate / Internal Data Width,如下图:

vivado SRIO 学习_第5张图片

        gt_clk = Line Rate /  20b,PHY在两个时钟域上运行:phy_clk,这是主要的核心时钟,gt_pcs_clk,这是用于串行收发器接口。gt_clk不被PHY使用,但被串行收发器接口使用。gt_pcs_clk的速率是gt_clk的一半。一般情况下,phy_clk等于(gt_clk *Link Width)/4,core运行2x的话,phy_clk的频率是gt_clk的一半。如果core训练成1x mode,phy_clk必须切换到gt_clk速率的四分之一。具体如下图:LOG层运行在log_clk域上。为了获得最佳吞吐量,log_clk至少应该与phy_clk一样快

vivado SRIO 学习_第6张图片

        (3) MMCM乘法器和分法器的值取决于reference clock frequencyline rate。在4x配置中,log_clk和gt_clk共享一个BUFG。在1x配置中,log_clk和phy_clk共享一个BUFG(不需要BUFGMUX,因为phy_clk速率只有一种可能)。此外,如果在Vivado IDE中选择了Unified Clock选项,log_clk和phy_clk需要相同的速率。这意味着可以删除log_clk/cfg_clk的BUFG,并且log_clk/cfg_clk被绑定到phy_clk。如下图:

vivado SRIO 学习_第7张图片

 四、Initiator/Target

        SRIO分两种事务处理方式,事务目标是远端的放置在Initiator port 上(本地是事务发起者),事务的目标是本地的放置在Target port 上(远端是事务发起者)。由本地端点生成的请求被放置在启动器请求(ireq)通道上,在链路上传输。从远端设备接收到的响应会在启动器响应(iresp)通道上呈现给用户设计。core接收到的来自远程设备的请求会在目标请求(treq)通道上呈现给用户设计。对这些请求的响应(由用户设计生成)放置在Target Response (trep)通道上。

vivado SRIO 学习_第8张图片

五、Transaction Types (常用的)

vivado SRIO 学习_第9张图片

vivado SRIO 学习_第10张图片

六、HELLO Packet Format 

vivado SRIO 学习_第11张图片

vivado SRIO 学习_第12张图片

vivado SRIO 学习_第13张图片

         HELLO报文的size字段为传输的字节数减1(有效范围是0 ~ 255,对应真实的1 ~ 256字节)。就是说SRIO一包数据量最大为256B

         TID从0开始,每产生一个请求,增加1

七、Protocol Description

       1. FTYPE2 - Request Class

        所有请求事务都是AXI4-Stream接口上的一个节拍,并且只是编码的报头

      (1)NREAD (TTYPE = 4'b0100). 标准的读事务。相关的响应是size字段中提供的大小。

       2.FTYPE5 - Write Class

        在AXI4-Stream接口上,所有写事务都在2到33拍之间,由编码的报头和最多32个dwords(每个dwords是8个bytes)的数据组成。

        (1)NWRITE (TTYPE = 4'b0100).写事务,没有响应。标准写事务允许少于dword或多于dword写入(不是8bytes的整数倍)。接收端点应该执行写入到指定地址。由于这种数据包类型的无响应特性,TID被忽略。

        (2)NWRITE_R (TTYPE = 4'b0101).写事务,等待响应。标准写事务允许子dword或多dword写入。接收端点应该执行写入到指定地址,然后将状态为OK或ERROR的单拍响应发送回发起端点。

        3.FTYPE6 - Streaming Write Class

        Streaming write 包允许端点元素在链接伙伴内存空间内修改大量数据。SWrite事务是跨链路接口的SRIO事务中最高效的,因此缺少其他事务中许多字段。SWrite只使用ftype、priority和address字段,不需要TID,因为对该报文类型不发送响应。不需要Size,因为所有事务都需要
dwords倍数(SWrite 包携带的数据量只能是dwords倍数)。在AXI4-Stream接口上,Streaming write事务在2到33节拍之间,由编码头之后跟一个最大值32dwords数据字组成。

        4.FTYPE10 - Doorbell Class

Doorbell包包含一个16位的信息字段,但没有地址或数据。为了使HELLO接口尽可能高效,HELLO地址字段的一部分用于传递 Doorbell信息。在AXI用户界面上, Doorbell包及其相关的响应都是一个节拍(仅包含编码的报头)。

八、状态信号

        在进行数据传输之前要先看core输出的状态是否正常,正常的话才能开始传输数据。

        port_decode_error :有效时表示收到不支持的事务,由于未启用User-Defined port而删除该事务。当下一个受支持的包类型到达任何用户界面时,该信号失效。这个信号在log_clk中是同步的。

         port_error:表示端口收到了不可恢复的错误,处于错误状态。这个信号生效说明PHY层链接出现了问题。必须用sys_rst复位(sys_rst复位整个core,所有的状态进行复位),core进行初始化。

        mode_1x:表示链路已经训练到1x。对于2x或4x的链路,该信号表明核心已经训练到一个通道,在port_initialized生效之后有效。
        port_initialized:端口已初始化成功。 phy_link_reset可复位。
         link_initialized:链路已初始化成功。具体地说,已发送至少15个状态控制符号,并已接收到8个无错误的状态控制符号,core已经完全训练完毕,现在可以传输数据了。使用phy_link_reset可复位。

九、AXI4-Stream接口时序

        

vivado SRIO 学习_第14张图片

                tuser:HELLO格式:在报文的第一个节拍有效,该信号由报文的源ID(31:16)和目的ID(15:0)组成。如果使用8位设备id,则每个设备id的最高位字节ID应该用0填充。

                tkeep:字节限定符,指示数据的相关字节的内容是否有效。如果端口被配置为使用HELLO格式,这必须绑定到8'hFF。第7位对应于数据的最高有效字节(tdata[63:56]),位0对应最低有效字节(tdata[7:0])。

十、SRIO规范 

vivado SRIO 学习_第15张图片

       vivado SRIO 学习_第16张图片

 

你可能感兴趣的:(FPGA,学习,fpga开发)