SRIO学习(3)使用SRIO IP核进行设计

文章目录

  • 前言
  • 一、设计框图
  • 二、模块介绍
  • 三、上板验证

前言

本文将通过使用SRIO IP核实现数据通信,重点在于打通数据链路,具体的协议内容设计并非重点,打通了链路大家自己根据设计需求来即可。

一、设计框图

看了前面高速接口的一些设计,大家应该也比较熟悉xilinx的高速接口设计风格了,无非就是时钟、复位、common还有IP核。
在这里插入图片描述

二、模块介绍

复位和时钟模块在上一篇介绍时钟和复位的时候进行了介绍。与之前高速接口不同的是RapidIO有一套自己的交互协议规范,所以在基于FPGA进行设计的时候,需要按照规范进行传输数据和解析数据。我们重点不在于这块,因为我没有接触过这方面的需求,所以暂时只是可以使IP核实现正常的通信即可。
以下是一个很简单的数据收发模块,参考FPGA奇哥:https://space.bilibili.com/497026889/?spm_id_from=333.999.0.0

该代码实现以下功能:

  1. 发起一次写事务
  2. 发起一次门铃事件
  3. 发起一次读事件
  4. 发起一次消息事件

由于我是在FPGA上进行通信,所以整个实验仅仅是实现了这些消息的传输过程,并没有所谓的DMA,中端处理等。

module SRIO_engine(
    input               i_clk                   ,
    input               i_rst                   ,

    output              m_axis_ireq_tvalid      , 
    input               m_axis_ireq_tready      , 
    output              m_axis_ireq_tlast       , 
    output [63:0]       m_axis_ireq_tdata       , 
    output [7 :0]       m_axis_ireq_tkeep       , 
    output [31:0]       m_axis_ireq_tuser       , 
    input               s_axis_iresp_tvalid     , 
    output              s_axis_iresp_tready     , 
    input               s_axis_iresp_tlast      , 
    input  [63:0]       s_axis_iresp_tdata      , 
    input  [7 :0]       s_axis_iresp_tkeep      , 
    input  [31:0]       s_axis_iresp_tuser      , 

    input               s_axis_treq_tvalid      , 
    output              s_axis_treq_tready      , 
    input               s_axis_treq_tlast       , 
    input  [63:0]       s_axis_treq_tdata       , 
    input  [7 :0]       s_axis_treq_tkeep       , 
    input  [31:0]       s_axis_treq_tuser       , 
    output              m_axis_tresp_tvalid     , 
    input               m_axis_tresp_tready     , 
    output              m_axis_tresp_tlast      , 
    output [63:0]       m_axis_tresp_tdata      , 
    output [7 :0]       m_axis_tresp_tkeep      , 
    output [31:0]       m_axis_tresp_tuser       
);
/******************************function*****************************/

/******************************parameter****************************/

/******************************mechine******************************/
localparam              P_ST_IDLE           = 0 ,
                        P_ST_WRITE          = 1 ,
                        P_ST_DB             = 2 ,
                        P_ST_READ           = 3 ,
                        P_ST_MESSAGE        = 4 ,
                        P_ST_END            = 5 ;

reg  [7 :0]             r_st_current            ;
reg  [7 :0]             r_st_next               ;
reg  [15:0]             r_st_cnt                ;
/******************************reg**********************************/
reg                     rm_axis_ireq_tvalid     ;
reg                     rm_axis_ireq_tlast      ;
reg  [63:0]             rm_axis_ireq_tdata      ;
reg  [7 :0]             rm_axis_ireq_tkeep      ;
reg  [31:0]             rm_axis_ireq_tuser      ;
reg                     rs_axis_iresp_tready    ;
reg                     rs_axis_treq_tready     ;
reg                     rm_axis_tresp_tvalid    ;
reg                     rm_axis_tresp_tlast     ;
reg  [63:0]             rm_axis_tresp_tdata     ;
reg  [7 :0]             rm_axis_tresp_tkeep     ;
reg  [31:0]             rm_axis_tresp_tuser     ;
reg  [15:0]             r_pkt_cnt               ;
reg  [7 :0]             r_read_cmd              ;
reg                     r_read_cmd_valid        ;
reg                     r_read_triger           ;
reg  [15:0]             r_treq_cnt              ;
reg  [15:0]             r_read_cnt              ;
/******************************wire*********************************/
wire                    w_m_axis_ireq_act       ;
wire                    w_s_axis_iresp_act      ;
wire                    w_s_axis_treq_act       ;
wire                    w_m_axis_tresp_act      ;
/******************************component****************************/

/******************************assign*******************************/
assign m_axis_ireq_tvalid  = rm_axis_ireq_tvalid    ;
assign m_axis_ireq_tlast   = rm_axis_ireq_tlast     ;
assign m_axis_ireq_tdata   = rm_axis_ireq_tdata     ;
assign m_axis_ireq_tkeep   = rm_axis_ireq_tkeep     ;
assign m_axis_ireq_tuser   = rm_axis_ireq_tuser     ;
assign s_axis_iresp_tready = rs_axis_iresp_tready   ;
assign s_axis_treq_tready  = rs_axis_treq_tready    ;
assign m_axis_tresp_tvalid = rm_axis_tresp_tvalid   ;
assign m_axis_tresp_tlast  = rm_axis_tresp_tlast    ;
assign m_axis_tresp_tdata  = rm_axis_tresp_tdata    ;
assign m_axis_tresp_tkeep  = rm_axis_tresp_tkeep    ;
assign m_axis_tresp_tuser  = rm_axis_tresp_tuser    ;
assign w_m_axis_ireq_act   = m_axis_ireq_tvalid & m_axis_ireq_tready;
assign w_s_axis_iresp_act  = s_axis_iresp_tvalid & s_axis_iresp_tready;
assign w_s_axis_treq_act   = s_axis_treq_tvalid & s_axis_treq_tready;
assign w_m_axis_tresp_act  = m_axis_tresp_tvalid & m_axis_tresp_tready;
/******************************always*******************************/
always@(posedge i_clk,posedge i_rst) 
begin
    if(i_rst) 
        r_st_current <= P_ST_IDLE;
    else 
        r_st_current <= r_st_next;
end

always@(*)
begin
    case(r_st_current)
        P_ST_IDLE       :r_st_next <= r_st_cnt == 1000                          ? P_ST_WRITE    : P_ST_IDLE     ;
        P_ST_WRITE      :r_st_next <= w_m_axis_ireq_act & rm_axis_ireq_tlast    ? P_ST_DB       : P_ST_WRITE    ;
        P_ST_DB         :r_st_next <= w_m_axis_ireq_act & rm_axis_ireq_tlast    ? P_ST_READ     : P_ST_DB       ;
        P_ST_READ       :r_st_next <= w_s_axis_iresp_act & s_axis_iresp_tlast   ? P_ST_MESSAGE  : P_ST_READ     ;
        P_ST_MESSAGE    :r_st_next <= w_m_axis_ireq_act & rm_axis_ireq_tlast    ? P_ST_END      : P_ST_MESSAGE  ;
        P_ST_END        :r_st_next <= P_ST_IDLE;
        default         :r_st_next <= P_ST_IDLE;
    endcase 
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_st_cnt <= 'd0;
    else if(r_st_current != r_st_next)
        r_st_cnt <= 'd0;
    else 
        r_st_cnt <= r_st_cnt + 1;
end

//======================Initiator===========================//
//组包逻辑
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rs_axis_treq_tready <= 'd0;
    else 
        rs_axis_treq_tready <= 'd1;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rs_axis_iresp_tready <= 'd0;
    else 
        rs_axis_iresp_tready <= 'd1;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ireq_tvalid <= 'd0;
    else if(w_m_axis_ireq_act && rm_axis_ireq_tlast)
        rm_axis_ireq_tvalid <= 'd0;
    else if(r_st_current == P_ST_WRITE && r_st_cnt == 0)
        rm_axis_ireq_tvalid <= 'd1;
    else if(r_st_current == P_ST_DB && r_st_cnt == 0)
        rm_axis_ireq_tvalid <= 'd1;
    else if(r_st_current == P_ST_READ && r_st_cnt == 0)
        rm_axis_ireq_tvalid <= 'd1;
    else if(r_st_current == P_ST_MESSAGE && r_st_cnt == 0)
        rm_axis_ireq_tvalid <= 'd1;
    else 
        rm_axis_ireq_tvalid <= rm_axis_ireq_tvalid;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ireq_tlast <= 'd0;
    else if(w_m_axis_ireq_act && rm_axis_ireq_tlast)
        rm_axis_ireq_tlast <= 'd0;
    else if(r_st_current == P_ST_DB && r_st_cnt == 0)
        rm_axis_ireq_tlast <= 'd1;
    else if(r_st_current == P_ST_MESSAGE && w_m_axis_ireq_act)
        rm_axis_ireq_tlast <= 'd1;
    else if(r_st_current == P_ST_READ && r_st_cnt == 0)
        rm_axis_ireq_tlast <= 'd1;
    else if(r_st_current == P_ST_WRITE && r_pkt_cnt == 32 - 1)
        rm_axis_ireq_tlast <= 'd1;
    else 
        rm_axis_ireq_tlast <= rm_axis_ireq_tlast;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ireq_tdata <= 'd0;
    else if(r_st_current == P_ST_WRITE && r_st_cnt == 0)
        rm_axis_ireq_tdata <=  {8'd0,4'b0101,4'b0100,1'b0,2'b1,1'b0,8'd255,2'b0,34'd0};
    else if(r_st_current == P_ST_DB && r_st_cnt == 0)
        rm_axis_ireq_tdata <= {8'd0,4'b1010,4'd0,1'b0,2'b0,1'b0,8'd0,2'b0,2'b0,8'd0,8'd0,16'd0};
    else if(r_st_current == P_ST_READ && r_st_cnt == 0)
        rm_axis_ireq_tdata <= {8'd0,4'b0010,4'd4,1'b0,2'b0,1'b0,8'd255,2'b0,34'd0};
    else if(r_st_current == P_ST_MESSAGE && r_st_cnt == 0)
        rm_axis_ireq_tdata <= {4'd0,4'd0,4'b1011,4'd0,1'b0,2'b0,1'b0,8'd63,2'b0,34'd0};
    else if(w_m_axis_ireq_act)
        case(r_pkt_cnt)
            0       :rm_axis_ireq_tdata <= {4{r_pkt_cnt}};
            default :rm_axis_ireq_tdata <= {4{r_pkt_cnt}};
        endcase 
    else 
        rm_axis_ireq_tdata <= rm_axis_ireq_tdata;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_pkt_cnt <= 'd0;
    else if(r_pkt_cnt == 32 && w_m_axis_ireq_act)
        r_pkt_cnt <= 'd0;
    else if(r_st_current == P_ST_WRITE && w_m_axis_ireq_act)
        r_pkt_cnt <= r_pkt_cnt + 1;
    else 
        r_pkt_cnt <= r_pkt_cnt;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ireq_tkeep <= 8'hff;
    else 
        rm_axis_ireq_tkeep <= 8'hff;
end     
 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_ireq_tuser <= 'd0;
    else 
        rm_axis_ireq_tuser <= 'd0;
end

//==================================Target===========================//
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_treq_cnt <= 'd0;
    else if(w_s_axis_treq_act && s_axis_treq_tlast)
        r_treq_cnt <= 'd0;
    else if(w_s_axis_treq_act)
        r_treq_cnt <= r_treq_cnt + 1;
    else 
        r_treq_cnt <= r_treq_cnt;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_cmd <= 'd0;
    else if(w_s_axis_treq_act && r_treq_cnt == 0)
        r_read_cmd <= s_axis_treq_tdata[55:48];
    else 
        r_read_cmd <= r_read_cmd;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_cmd_valid <= 'd0;
    else if(w_s_axis_treq_act && r_treq_cnt == 0)
        r_read_cmd_valid <= 'd1;
    else 
        r_read_cmd_valid <= 'd0;
end


always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_triger <= 'd0;
    else if(r_read_cmd_valid && r_read_cmd == {4'b0010,4'd4})
        r_read_triger <= 'd1;
    else 
        r_read_triger <= 'd0;
end

/*----带数据的响应报文----*/
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_tresp_tvalid <= 'd0;
    else if(w_m_axis_tresp_act && rm_axis_tresp_tlast)
        rm_axis_tresp_tvalid <= 'd0;
    else if(r_read_triger)
        rm_axis_tresp_tvalid <= 'd1;
    else
        rm_axis_tresp_tvalid <= rm_axis_tresp_tvalid;
end

 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_tresp_tlast <= 'd0;
    else if(w_m_axis_tresp_act && rm_axis_tresp_tlast)
        rm_axis_tresp_tlast <= 'd0;
    else if(r_read_cnt == 32 - 0)
        rm_axis_tresp_tlast <= 'd1;
    else
        rm_axis_tresp_tlast <= rm_axis_tresp_tlast;
end
 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_tresp_tdata <= 'd0;
    else if(r_read_triger)
        rm_axis_tresp_tdata <= {8'd0,4'b1101,4'b1000,1'b1,2'd1,1'b0,8'd0,2'd0,34'd0};
    else if(w_m_axis_tresp_act)
        rm_axis_tresp_tdata <= {4{r_read_cnt - 1}};
    else
        rm_axis_tresp_tdata <= rm_axis_tresp_tdata;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        r_read_cnt <= 'd0;
    else if(r_read_cnt == 32 && w_m_axis_tresp_act)
        r_read_cnt <= 'd0;
    else if(r_read_triger || (r_read_cnt && w_m_axis_tresp_act))
        r_read_cnt <= r_read_cnt + 1;
    else 
        r_read_cnt <= r_read_cnt;
end

always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_tresp_tkeep <= 'd0;
    else
        rm_axis_tresp_tkeep <= 8'hff;
end
 
always@(posedge i_clk,posedge i_rst)
begin
    if(i_rst)
        rm_axis_tresp_tuser <= 'd0;
    else
        rm_axis_tresp_tuser <= 'd0;
end     

endmodule

三、上板验证

三次last信号分别表示了写事务、门铃以及读事务,发起端通过ireq通道发送,目的端通过treq接收。

在这里插入图片描述
这里是发起端通过iresp通道收到来自的目的端的带数据回应(针对于发起端发起的一次读事件,在目的端是通过tresp通道发送)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/527646.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【uniapp】开发微信小程序 — 注意事项

底部导航栏 (tabBar) 图标的正确做法&#xff1a; 1、图片的标准尺寸为 81px * 81px&#xff0c;该尺寸在官方的文档中有明确的说明&#xff0c;可以参考微信小程序全局配置文档中对 iconPath 属性的说明。 2、为了保持良好的间距&#xff0c;图片的内容区域设置 60px* 比较好&…

docker最简单教程(使用dockerfile构建环境)

一 手里有的东西 安装好的dockerdockerfile 二 操作 只需要在你的dockerfile文件下执行命令 docker build -t"xianhu/centos:gitdir" . 将用户名、操作系统和tag进行修改就可以了&#xff0c;这就相当于在你本地安装了一个docker环境&#xff0c;然后执行 docker…

【c 语言】结构体的概念

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

JAVAEE——网络初始

文章目录 网络发展史独立模式网络模式局域网LAN路由器的诞生 网络通信的基础IP地址端口号 认识协议OSI七层模型TCP/IP五层模型 网络发展史 独立模式 在原始的年代中电脑间想要通信需要两台电脑连接一根网线&#xff0c;但是一台电脑基本上只有一个接口。因此想要链接更多的电…

函数重载和引用【C++】

文章目录 函数重载什么是函数重载&#xff1f;函数重载的作用使用函数重载的注意点为什么C可以函数重载&#xff0c;C语言不行&#xff1f; 引用什么是引用&#xff1f;引用的语法引用的特点引用的使用场景引用的底层实现传参时传引用和传值的效率引用和指针的区别 函数重载 什…

全国火情预报卫星遥感应用方案

一、引言 火情预报应急卫星遥感解决方案是一种利用卫星遥感技术进行火灾预警和应急响应的方法。该方案通过实时监测和分析森林、草原等地区的火情信息&#xff0c;为火灾预警和应急响应提供科学依据&#xff0c;有效减少火灾造成的损失。本技术文档将介绍火情预报应急卫…

Android-NDK的linux交叉编译环境

NDK工具包下载 NDK 下载 | Android NDK | Android Developers https://github.com/android/ndk/wiki/Unsupported-Downloads 以android-ndk-r26c下载为例&#xff0c;下载后将压缩包解压至/usr目录下 CMakeLists编译选项设置 编译平台变量判断条件中增加一下android条件…

7款公司电脑监控软件

7款公司电脑监控软件 研究证明&#xff0c;人们在家办公的效率比在办公室办公的效率低一半&#xff0c;其中原因是缺少监督&#xff0c;即便在公司办公&#xff0c;还存在员工偷闲的时刻&#xff0c;比如聊天、浏览无关网站、看剧、炒股等&#xff0c;企业想提高员工的工作效率…

TCP 三次握手与四次挥手面试题(计算机网络)

TCP 基本认识 TCP 头格式有哪些&#xff1f; 序列号&#xff1a;在建立连接时由计算机生成的随机数作为其初始值&#xff0c;通过 SYN 包传给接收端主机&#xff0c;每发送一次数据&#xff0c;就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。 确认应答号&a…

STC89C52学习笔记(二)

STC89C52学习笔记&#xff08;二&#xff09; 综述&#xff1a;本文简要介绍了51单片机以及示例了如何成功创建并运行一个程序&#xff08;点亮一个LED&#xff09;。 一、单片机介绍 单片机简称MCU&#xff0c;MCUCPURAMROM定时器中断系统通讯协议等单片机任务是信息采集、…

T-Mamba:用于牙齿 3D CBCT 分割的频率增强门控长程依赖性

T-Mamba&#xff1a;用于牙齿 3D CBCT 分割的频率增强门控长程依赖性 摘要Introduction方法T-Mamba architectureTim block T-Mamba: Frequency-Enhanced Gated Long-Range Dependendcy for Tooth 3D CBCT Segmentation 摘要 三维成像中的高效牙齿分割对于正畸诊断至关重要&am…

vue 中使 date/time/datetime 类型的 input 支持 placeholder 方法

一般在开发时&#xff0c;设置了 date/time/datetime 等类型的 input 属性 placeholder 提示文本时&#xff0c; 发现实际展示中却并不生效&#xff0c;如图&#xff1a; 处理后效果如图&#xff1a; 处理逻辑 判断表单项未设置值时&#xff0c;则设置其伪类样式&#xff0c;文…

在线免费图像处理

功能 尺寸修改(自定义和内置常用的照片尺寸)图像压缩(比较好的情况最高可以压缩 10 倍, 如果是无损压缩可以压缩 5 倍左右,参数范围 50~70 左右)图像方向修改图像格式修改修改后的效果支持实时反馈, 并且支持点击图像预览,同时保留历史修改图片(在预览中可以查看)支持修改撤回…

2024-04-08 NO.6 Quest3 自定义交互事件

文章目录 1 交互事件——更改 Cube 颜色2 交互事件——创建 Cube2.1 非代码方式2.2 代码方式 ​ 在开始操作前&#xff0c;我们导入上次操作的场景&#xff0c;相关介绍在 《2024-04-08 NO.5 Quest3 手势追踪进行 UI 交互-CSDN博客》 文章中。 1 交互事件——更改 Cube 颜色 …

Java设计模式之创建型模式(二)原型模式

原型模式 1、原型模式1-1、应用场景1-2、举个 软栗子1-3、举个 硬栗子1-3、举个实务栗子 学习原型模式的目的&#xff1a;原型模式的目的在于通过复制现有的实例来创建新的对象&#xff0c;以避免通过构造函数创建对象时可能带来的性能开销&#xff0c;同时可以控制对象的深度复…

Matlab|基于蒙特卡洛的风电功率/光伏功率场景生成方法

目录 主要内容 部分代码 结果一览 下载链接 主要内容 该模型主要用于风电功率和光伏功率场景生成与缩减&#xff0c;利用多元高斯分布构建时间相关性&#xff0c;并采用蒙特卡洛方法进行仿真&#xff0c;风电功率采用Weibull分布&#xff0c;光伏功率采用Beta分布…

浅析人工智能与数字化的特点

人工智能无疑具有数字化的特点。作为现代科技的一个重要分支&#xff0c;人工智能的发展与数字化进程紧密相连&#xff0c;数字化已经成为了人工智能发展的基础和前提。 首先&#xff0c;我们来理解一下什么是数字化。数字化是将模拟信号转换为数字信号的过程&#xff0c;即将连…

[论文阅读笔记30] (AAAI2024) UCMCTrack: Multi-Object Tracking with Uniform CMC 详细推导

这是群友的一篇工作&#xff0c;之前也没仔细看&#xff0c;正好今天放假&#xff0c;打算读一下论文陶冶情操。 这篇文章的公式比较多&#xff0c;我做一篇笔记解释一下&#xff0c;希望对大家有帮助~ 论文地址: https://ojs.aaai.org/index.php/AAAI/article/view/28493 代…

java数据结构与算法刷题-----LeetCode238. 除自身以外数组的乘积

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 动态规划&#xff1a;左右乘积列表2. 滚动数组对动态规划过程…

uni-app(H5)论坛 | 社区 表情选择 UI组件

项目源码请移步&#xff1a;bbs 效果 实现思路 表情切换 人物、动物、小黄人不同表情之间的切换实际就是组件的切换 emoji表情 emoji表情本身就是一种字符 如需其他emoji表情可参考 EmojiAll中文官方网站 需要注意的就是数据库的存储格式需要支持emoji表情&#xff0c;我项…