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

news2024/11/20 21:34:04

文章目录

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

前言

本文将通过使用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通道发送)
在这里插入图片描述

总结

完整工程可参考:https://github.com/shun6-6/SRIO_IP_design

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 秋招必知必会(六、Socket 网络编程)

二、Socket 编程 13. 什么是 Socket&#xff1f; Socket 本身有 “插座” 的意思&#xff0c;在 Linux 环境下&#xff0c;用于表示进程间网络通信的特殊文件类型 本质为内核借助缓冲区形成的伪文件 既然是文件&#xff0c;那么可以使用文件描述符引用套接字 与管道类似&…

机器人路径规划:基于Q-learning算法的移动机器人路径规划(可以更改地图,起点,终点),MATLAB代码

一、Q-learning算法 Q-learning算法是强化学习算法中的一种&#xff0c;该算法主要包含&#xff1a;Agent、状态、动作、环境、回报和惩罚。Q-learning算法通过机器人与环境不断地交换信息&#xff0c;来实现自我学习。Q-learning算法中的Q表是机器人与环境交互后的结果&#…

AIGC 探究:人工智能生成内容的技术原理、广泛应用、创新应用、版权问题与未来挑战

AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;即人工智能生成内容&#xff0c;其核心在于利用深度学习技术&#xff0c;尤其是基于神经网络的模型&#xff0c;来模拟人类创作过程&#xff0c;自主生成高质量的文本、图像、音频、视频等各类内容。神经…

MySQL8.0的下载、安装配置教程、连接数据可视图形化界面和卸载及MySQL基本使用教程

文章目录 MySQL8.0下载安装MySQL卸载常见问题解决方式MySQL基本使用教程&#xff08;使用MySQLworkbench&#xff09; 1、创建数据库2、创建表、删除表3、修改表的名字4、为数据表增加、修改、删除字段5、关于修改数据库名字6、拓展&#xff1a;pycharm操作MySQL 首先&#…

Diagrams:Show Me​

大家好&#xff0c;今天给大家介绍的 GPTs 叫 Diagrams:Show Me。 首先&#xff0c;让Diagrams:Show Me介绍一下自己&#xff0c;了解一下他的基本功能 然后&#xff0c;让他告诉我们&#xff0c;我们要怎么与他进行交互。 按照他给出的例子来体验一下他的功能。先来第一个例子…

cog predict docker unknown flag: --file

如图&#xff1a; 使用cog predict -i image“link-to-image” 出现docker unknown flag: --file的问题。 解决方法&#xff08;对我可行&#xff09;&#xff1a;切换cog版本。 这个是我一开始的cog安装命令&#xff08;大概是下的最新版&#xff1f;&#xff09;&#xff1…

StarUML笔记之从UML图生成C++代码

StarUML笔记之从UML图生成C代码 —— 2024-04-14 文章目录 StarUML笔记之从UML图生成C代码1.Add Diagram2.在TOOLBOX中左键点击Class,松开,然后在中间画面再左键点击&#xff0c;即可出现UML3.修改类图&#xff0c;并添加接口&#xff0c;方法&#xff0c;属性&#xff0c;我…

12-LINUX--进程间的通信

进程间通信&#xff1a;采用IPC机制&#xff08;进程间的用户空间相互独立&#xff0c;内核空间共享&#xff09;&#xff0c;有管道&#xff0c;信号量&#xff0c;共享内存&#xff0c;消息队列&#xff0c;套接字。 一.管道 管道可以用来在两个进程之间传递数据&#xff0c…

C语言入门(第三天:函数、指针)

一、函数 1.1 函数概述 作用&#xff1a;提高代码的编写效率&#xff0c;实现对代码的重用 函数使用步骤 定义函数 理解为制作工具&#xff0c;工具只需要制作1次即可 调用函数 理解为使用工具 1.2 无参无返回值 1.3 有参无返回值(重点) 函数参数的作用&#xff1a;增加…

怎么提升公众号上限

正常可以申请多少个公众号&#xff1f;目前如果我们是企业主体的话&#xff08;包括个体户&#xff09;&#xff0c;申请公众号默认是可以申请2个公众号数量的。不过对于很多公司来说&#xff0c;2个公众号的数量肯定是远远不够用的&#xff0c;不同的产品不同品牌不同部门都可…

基于R语言实现的beta二项回归模型【理解与实现】

本实验&#xff0c;创建一组使用二项分布模拟的数据&#xff08;不带额外的随机性&#xff09;&#xff0c;和另一组使用Beta二项分布模拟的数据&#xff08;引入了随机成功概率 p&#xff0c;从而增加了数据的离散性。 现在假设我们站在上帝视角&#xff0c;有两组不知道分布…

【可能是全网最丝滑的LangChain教程】七、LCEL表达式语言

系列文章地址 【可能是全网最丝滑的LangChain教程】一、LangChain介绍-CSDN博客 【可能是全网最丝滑的LangChain教程】二、LangChain安装-CSDN博客 【可能是全网最丝滑的LangChain教程】三、快速入门LLM Chain-CSDN博客 【可能是全网最丝滑的LangChain教程】四、快速入门Re…

Oracle ORA-28547:connection to server failed,probable Oracle Net admin error

使用Navicat连接oracle数据库时报ORA-28547错误 因为Navicat自带的oci.dll并不支持oracle11g&#xff0c;需要去官网下载支持的版本。 1.去oracle下载对应的oci.dll文件 下载地址&#xff1a;Oracle Instant Client Downloads 可以用 11.2.0.4 2. 复制刚下载下来的instant…

【无人机/平衡车/机器人】详解STM32+MPU6050姿态解算—卡尔曼滤波+四元数法+互补滤波(文末附3个算法源码)

效果: MPU6050姿态解算-卡尔曼滤波+四元数+互补滤波 目录 基础知识详解 欧拉角

嵌入式第三天:(C语言入门)

目录 一、跳转关键字 break&#xff1a; continue&#xff1a; goto&#xff1a; 二、函数 概述&#xff1a; 函数的使用&#xff1a; 无参无返回值&#xff1a; 有参无返回值&#xff1a; 有参有返回值&#xff1a; 返回值注意点&#xff1a; 函数的声明&#xff…

微信跳转页面时发生报错

报错如下图所示&#xff1a; 解决方法&#xff1a;&#xff08;从下面四种跳转方式中任选一种&#xff0c;哪种能实现效果就用哪个&#xff09; 带历史回退 wx.navigateTo() //不能跳转到tabbar页面 不带历史回退 wx.redirectTo() //跳转到另一个页面wx.switchTab() //只能…

Linux: softirq 简介

文章目录 1. 前言2. softirq 实现2.1 softirq 初始化2.1.1 注册各类 softirq 处理接口2.1.2 创建 softirq 处理线程 2.2 softirq 的 触发 和 处理2.1.1 softirq 触发2.1.2 softirq 处理2.1.2.1 在 中断上下文 处理 softirq2.1.2.2 在 ksoftirqd 内核线程上下文 处理 softirq 3.…

[lesson26]类的静态成员函数

类的静态成员函数 静态成员函数 在C中可以定义静态成员函数 静态成员函数是类中特殊的成员函数静态成员函数属于整个类所有可以通过类名直接访问公有静态成员函数可以通过对象名访问公有静态成员函数 静态成员函数的定义 直接通过static关键字修饰成员函数 静态成员函数 vs…

4.Godot图片素材的获取和编辑

游戏开发中经常遇到图片素材的需求 1. 图片素材的准备 术语&#xff1a;Sprite 精灵&#xff0c;游戏开发中指一张图片来源不明的图片&#xff0c;切勿在商业用途使用&#xff0c;以免引起版权风险。 1. 在学习阶段&#xff0c;可以百度或者从一些资源网站获取&#xff0c;这…

Unity类银河恶魔城学习记录12-13 p135 Merge Skill Tree with Dogge skill源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​​​​​​ Inventory.cs using System.Collections.Generic; using Un…