AXI Memory-Mapped SRIO收发控制器

  Xilinx的SRIO IP可以用混合的接口或者分Initiator和Target的AXI4-Stream接口,数据是以Hello Format的包格式传输(SRIO IP的文档里有说明)。为了实现SRIO接口直接访问DDR数据空间,需要将Hello Format包格式转换为AXI4 master接口。
  在我们的系统中,DSP和FPGA通过x4的SRIO链路互连,单条链路最高支持3.125Gbps。为了实现高效的数据传输,一般采用写的方式,比如NWRTIE包或者SWRITE包。如果用读的方式,就需要先发读请求包,然后过一段时间才能收到响应的数据,虽然可以连续发起多个读请求,但是面对大批量的数据传输,读的过程相对来说就比较繁琐,所以在我们的系统里主要用写的方式来实现数据传输。从DSP到FPGA的数据,由DSP发写数据包;从FPGA到DSP的数据,由FPGA发写数据包。
在这里插入图片描述
  我们的DSP的SRIO外设支持DMA操作,可以将批量的数据以NWRITE包的形式发送。因此FPGA端的SRIO接收控制器主要负责解析NWRITE包;FPGA发送数据则可以采用SWRTIE包,它的额外开销最小,因此SRIO发送控制器主要发送SWRITE包,由MicroBlaze软和处理器通过AXI4-Lite接口发起启动指令。除了主要的数据传输功能,门铃中断信号的接收与发送也需要实现。

SRIO接收控制器

设计思路

  SRIO接收控制器主要负责接收门铃事务包和NWRITE事务包。
  NWRITE事务包从treq端口接收后,根据包头的目的地址和包大小,计算出所需要的AXI突发(burst)次数和每次的突发长度。AXI协议中要求突发传输不能超过4kB地址边界,所以对一包NWRITE事务包的分解需要考虑多种情况。另外需要注意的是SRIO的数据是大端模式传输,如果要配合系统中的其他小端模式的设备,需要对字节位置进行调整。
  门铃事务包的接收就相对比较简单了。一方面是对接收到的门铃事务包进行响应,注意:响应包的prio字段的值等于接收到的门铃事务的prio字段的值加一。输出的中断脉冲信号是给到MicroBlaze的中断控制器,中断控制器如果设置为边沿触发,那么要求这个中断脉冲宽度大于2个中断控制器的时钟周期。

在这里插入图片描述
  为了让treq的端口不堵塞,门铃接收引擎对于任何门铃事务包,都无条件接收,并且发送响应,即使没有使能门铃中断。通过AXI4-Lite接口使能门铃中断后,接收到的门铃信息才会存到CSR寄存器中,并且产生门铃中断脉冲。通过AXI4-Lite接口读取中断信息之后,才能接收新的门铃,所以这里要求门铃中断产生之后,MicroBlaze要尽快从CSR寄存器读取门铃信息,不然就有可能导致门铃接收堵塞。

寄存器说明

寄存器偏移地址寄存器名称
0x00Control and Status Register(CSR)

CSR寄存器的位域说明:

字段位域复位值读写权限描述
Doorbell Enable00W/R门铃中断使能,高电平有效
Doorbell Info[31:16]0x0000R上一个接收的门铃事务包携带的门铃信息

SRIO收发控制器

设计思路

  这个模块最开始的设计想法是做一个“收发控制器”,但目前只做了“发送”的功能。一开始想做收发控制器是因为,这样子不管数据怎么走,FPGA始终是主动方,这样可以减少DSP的负担。但目前我们的DSP有DMA发送NWRITE包的功能,所以这个从DSP读数据的功能就没做了(下图中的NREAD模块是虚线框)。要做的话只需要加一个NREAD引擎就好了。
在这里插入图片描述
  iresp和ireq端口的输出信号需要由多个引擎驱动,在设计中是依靠“或”的方式实现的。
  在模块顶层中,AXI4-Lite接口完成对寄存器的读写。寄存器中的信息作为驱动信号(图中未画出)施加给不同的引擎。
  DoorBell发送引擎维护了一个16bit的门铃空闲寄存器,一个门铃发送后如果没收到对应的响应,那么这个门铃对应的事务ID就不能再次发送。如果连续发送了16个门铃,但是没有收到任何响应,就无法再发送门铃了。一个门铃只有被成功发送,才能会将寄存器中的门铃启动位清零,之后才能发送新的门铃。
  SWRITE发送引擎接收MicroBlaze给出的启动命令,接着就通过AXI4接口从特定地址读数据,从ireq端口用SWRITE包格式进行发送。发送完成后还会额外发送一个门铃事务包通知对方发送完成,也会向MicroBlaze发送sw_irq中断信号告知MicroBlaze发送已完成。只有在发送完成之后才能启动新的传输,且传输不能中断。由于SRIO是大端模式,因此发送的数据也需要对字节位置进行调整。
  NREAD发送引擎没有做,等之后有需要了再做。

寄存器说明

寄存器偏移地址寄存器名称
0x00START
0x04Source Address (SRCADDR)
0x08Destination Address (DSTADDR)
0x0CDoorBell Information and Transfer Size (INFOSIZE)

START寄存器的位域说明:

字段位域复位值读写权限描述
DoorBell Start00W/R根据当前INFOSIZE寄存器中的INFO字段,发送门铃事务包;置一发送门铃,发送完成后自动清零;在该bit为1的情况下写1无效
Swrite Start10W/R根据当前SRCADDR、DSTADDR、INFOSIZE寄存器连续发送一定数量的SWRITE事务包;置一启动SWRTIE,所有数据发送完成后自动清零;在该bit为1的情况下写1无效
Nread Start20W/R(待实现功能)根据当前SRCADDR、DSTADDR、INFOSIZE寄存器连续发送一定数量的NREAD事务包;置一启动NREAD,所有数据接收完成后自动清零;在该bit为1的情况下写1无效

SRCADDR寄存器的位域说明:

字段位域复位值读写权限描述
Source Address[31:0]0x00000000W/R待传输数据的源地址。对于SWRITE来说,是FPGA端的地址;(待实现功能)对于NREAD来说,是DSP端的地址

DSTADDR寄存器的位域说明:

字段位域复位值读写权限描述
Destination Address[31:0]0x00000000W/R待传输数据的目的地址。对于SWRITE来说,是DSP端的地址;(待实现功能)对于NREAD来说,是FPGA端的地址

INFOSIZE寄存器的位域说明:

字段位域复位值读写权限描述
DoorBell Information[31:16]0x0000W/R需要发送的门铃信息
Transfer Size[15:0]0x0000W/RSwrite或Nread传输的数据大小。以双字为单位,实际传输大小为该该字段值加一

系统测试

  下图为FPGA端的Block Design,添加了SRIO接收控制器和SRIO发送控制器。SRIO IP设置为x4链路,每条链路3.125Gbps,对应的log_clk为156.25MHz,这也是两个控制器的工作频率。MIG外接1GB的DDR3,MIG输出的时钟频率为200MHz,同时作为MicroBlaze的系统时钟。目的设备ID和本地设备ID通过IP的参数设置。MB中断控制器通过concat连接SRIO接收控制器发出的门铃中断信号和SRIO发送控制器发出的SWRITE发送完成中断信号,在软件上采用fast_interrupt模式,当中断产生时,MB可以直接跳转到相应的中断服务函数处。
在这里插入图片描述

从DSP到FPGA,NWRITE波形

  下面两张图是NWRITE包接收时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。蓝色的波形是AXI接口的W通道的数据,数据正常写入DDR。
在这里插入图片描述
在这里插入图片描述

从FPGA到DSP,SWRITE波形

  下面两张图是SWRITE包发送时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。从第一包SWRITE发出包头到真正开始发送数据,经过了一段时间的等待,因为从DDR读数据需要等待;后续能够读到连续的数据是因为在AR通道已经把需要读的数据的地址都发过去了。

在这里插入图片描述
在这里插入图片描述

读写速率测试

  为了对SRIO传输的速率进行测试,在DSP端利用TSC定时,分别对DSP通过SRIO读写数据的速率和门铃功能进行测试。
在这里插入图片描述

  首先是DSP利用SRIO的DMA,从DSP向FPGA外接的DDR写数据。数据量是640×512×8bit。DSP在发送完成后会进入发送完成中断,同时会向FPGA发送一个门铃事务包,所以MicroBlaze也会进入中断。MicroBlaze读取门铃Info,判断出是收到了数据。发送数据所用时间为327891ns,可以计算数据传输速率:
640 × 512 × 8 b i t 327891 n s = 7.99 G b p s \frac{640\times512\times8bit}{327891ns}=7.99Gbps 327891ns640×512×8bit=7.99Gbps
η = 7.99 G b p s 3.125 G b p s × 4 × 100 % = 63.95 % \eta=\frac{7.99Gbps}{3.125Gbps\times4}\times100\%=63.95\% η=3.125Gbps×47.99Gbps×100%=63.95%

  接着是测试FPGA向DSP发送SWRITE的速率,从DSP向FPGA发送门铃信息为“0xAAAA”的门铃,MicroBlaze收到之后就发起一个较少数据量的SWRITE包,利用这次传输计算额外开销;DSP接着发送门铃信息为“0xBBBB”的门铃,MicroBlaze收到之后就发起640×512×8bit的数据传输。传输完成后,DSP和MicroBlaze都会进入中断,DSP收到门铃中断,MicroBlaze收到sw_irq的中断脉冲。可以看到FPGA向DSP发送同样大小的数据所用的时间为296036ns
640 × 512 × 8 b i t 296036 n s = 8.85 G b p s \frac{640\times512\times8bit}{296036ns}=8.85Gbps 296036ns640×512×8bit=8.85Gbps
η = 8.85 G b p s 3.125 G b p s × 4 × 100 % = 70.83 % \eta=\frac{8.85Gbps}{3.125Gbps\times4}\times100\%=70.83\% η=3.125Gbps×48.85Gbps×100%=70.83%
  最后是单独对门铃接收的测试,可以看到DSP发送的门铃信息都被MicroBlaze正确接收。

FPGA工程及IP源代码

  • 6
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个简单的Xilinx AXI4-lite接口控制SPI接口的控制器的示例代码: ```verilog module spi_controller( input wire aclk, //AXI4-lite时钟 input wire aresetn, //AXI4-lite复位信号,低电平有效 input wire sclk, //SPI时钟 output wire cs_n, //SPI片选信号 output wire mosi, //SPI主机数据输出 input wire miso, //SPI从机数据输入 input wire [3:0] addr, //AXI4-lite地址 input wire [31:0] wdata, //AXI4-lite写入数据 output wire [31:0] rdata, //AXI4-lite读出数据 input wire write_enable, //AXI4-lite写使能 input wire read_enable //AXI4-lite读使能 ); reg [7:0] tx_data; //SPI发送数据 reg [7:0] rx_data; //SPI接收数据 reg [31:0] axi_reg; //AXI4-lite寄存器 assign cs_n = axi_reg[0]; //将AXI4-lite的第0位寄存器赋值给SPI的片选信号 assign mosi = tx_data[7]; //将发送数据的最高位赋值给SPI的主机数据输出 assign rdata = axi_reg; //将AXI4-lite寄存器赋值给读取数据输出 always@(negedge aresetn or posedge aclk) begin if (!aresetn) begin axi_reg <= 32'h00000000; //AXI4-lite寄存器复位为0 tx_data <= 8'h00; //发送数据清零 rx_data <= 8'h00; //接收数据清零 end else begin if (write_enable) begin //AXI4-lite写使能 case(addr) 4'h0: axi_reg[7:0] <= wdata[7:0]; //将AXI4-lite写入数据的最低8位赋值给SPI的片选信号 4'h4: begin //将AXI4-lite写入数据的第8位到第15位赋值给发送数据 tx_data[7:0] <= wdata[15:8]; axi_reg[31:8] <= 24'h000000; //将AXI4-lite的第1到第23位清零 end 4'h8: begin //将AXI4-lite写入数据的第16位到第23位赋值给发送数据 tx_data[7:0] <= wdata[23:16]; axi_reg[31:8] <= 24'h000000; //将AXI4-lite的第1到第23位清零 end default: axi_reg <= axi_reg; //如果没有匹配到地址,则AXI4-lite寄存器不变 endcase end else if (read_enable) begin //AXI4-lite读使能 case(addr) 4'h0: axi_reg <= axi_reg; //将SPI片选信号赋值给AXI4-lite寄存器的最低8位 4'h4, 4'h8: axi_reg <= {24'h000000, rx_data}; //将接收数据赋值给AXI4-lite寄存器的第8位到第31位 default: axi_reg <= axi_reg; //如果没有匹配到地址,则AXI4-lite寄存器不变 endcase end end end always@(negedge aresetn or posedge sclk) begin //SPI控制 if (!aresetn) begin tx_data <= 8'h00; //发送数据清零 rx_data <= 8'h00; //接收数据清零 end else begin if (cs_n == 1'b0) begin //SPI片选信号有效 rx_data[7:0] <= miso; //将SPI从机数据输入赋值给接收数据 tx_data[6:0] <= tx_data[7:1]; //发送数据左移一位 tx_data[7] <= axi_reg[0]; //将AXI4-lite的第0位寄存器赋值给发送数据的最高位 end end end endmodule ``` 该控制器包含一个AXI4-lite接口和一个SPI接口。AXI4-lite接口用于控制SPI接口,并且可以通过读取和写入AXI4-lite寄存器来控制SPI片选信号和发送数据。SPI接口用于发送和接收数据。在SPI片选信号有效时,发送数据会左移一位,同时将AXI4-lite的第0位寄存器赋值给发送数据的最高位,并将SPI从机数据输入赋值给接收数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小裘HUST

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值