SRIO系列-仿真测试

一、前言

前两篇已经讲述了SRIO协议的概况,以及xilinx SRIO IP核的使用方式,已经在搭建工程的过程中时钟和复位的注意事项。

二、设计框图

整个框图也是按照之前的工程进行搭建,首先时SRIO_Channel,由SRIO IP核和时钟、复位模块组成,这是在之前的工程搭建中一种采用的一种Channel结构。其次,SRIO Module是按照QPLL共享的方式去管理Channel,使得多个通道能够共享QPLL。最后,用户侧逻辑采用了一个SRIO Engine一共有4次的事务传输,分别是:

  1. 写事务。写256字节的数据。
  2. 发送Doorbell。通知写完成。
  3. 读事务。读取写入的数据
  4. 发送消息,通知读完毕。(消息包一直有负载)

三、SRIO Engine 

这部分参考FPGA奇哥的系列网课。


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        
);

// assign   s_axis_iresp_tready = 0    ;
// assign   s_axis_treq_tready  = 0    ;

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_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                w_m_axi_ireq_act                  ;
wire                w_s_axi_iresp_act                 ;
wire                w_s_axi_treq_act                  ;
wire                w_m_axi_tresp_act                 ;

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_axi_ireq_act    = m_axis_ireq_tready & rm_axis_ireq_tvalid;
assign   w_s_axi_iresp_act   = s_axis_iresp_tvalid & rs_axis_iresp_tready;
assign   w_s_axi_treq_act    = s_axis_treq_tvalid & rs_axis_treq_tready;
assign   w_m_axi_tresp_act   = m_axis_tresp_tready && rm_axis_tresp_tvalid;


localparam      P_ST_IDLE    = 5'b00001               ,
                P_ST_WRITE   = 5'b00010               ,
                P_ST_DB      = 5'b00100               ,
                P_ST_READ    = 5'b01000               ,
                P_ST_MESSAGE = 5'b10000               ;

reg [4: 0]       r_st_nstate                          ;
reg [4: 0]       r_st_cstate                          ; 
reg [15:0]       r_st_cnt                             ;  

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_st_cstate <= P_ST_IDLE; 
    else
        r_st_cstate <= r_st_nstate;
end

always@(*)begin
    r_st_nstate = P_ST_IDLE;
    case(r_st_cstate)
        P_ST_IDLE:begin
            if(r_st_cnt == 1000)
                r_st_nstate =  P_ST_WRITE;
            else
                r_st_nstate =  P_ST_IDLE;
        end   
        P_ST_WRITE:begin
            if(w_m_axi_ireq_act && m_axis_ireq_tlast)
                r_st_nstate = P_ST_DB;
            else
                r_st_nstate = P_ST_WRITE;
        end  
        P_ST_DB:begin
            if(w_m_axi_ireq_act && m_axis_ireq_tlast)
                r_st_nstate = P_ST_READ;
            else
                r_st_nstate = P_ST_DB;            
        end     
        P_ST_READ:begin
            if(w_s_axi_iresp_act && s_axis_iresp_tlast)
                r_st_nstate = P_ST_MESSAGE;
            else
                r_st_nstate = P_ST_READ;              
        end   
        P_ST_MESSAGE:begin
            if(w_m_axi_ireq_act && m_axis_ireq_tlast)
                r_st_nstate = P_ST_IDLE;
            else
                r_st_nstate = P_ST_MESSAGE;              
        end
        default:begin
            r_st_nstate = P_ST_IDLE;
        end
    endcase    
end

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

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_cnt <= 'd0;
    else
        if(r_cnt == 32 && w_m_axi_ireq_act)
            r_cnt <= 'd0;
        else if(r_st_nstate == P_ST_WRITE && w_m_axi_ireq_act)//??
            r_cnt <= r_cnt + 1;
        else
            r_cnt <= r_cnt ;
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_ireq_tdata <= 'd0;
    else
        if(r_st_nstate == P_ST_WRITE && r_cnt == 0)
            rm_axis_ireq_tdata <= {8'd0,4'b0110,4'd0,1'b0,2'b00,1'b0,8'hFF,1'b0,1'b0,34'b0};//流写
        else if(r_st_nstate == P_ST_DB && r_cnt == 0)
            rm_axis_ireq_tdata <= {8'd0,4'b1010,4'd0,1'b0,2'b00,1'b0,8'h00,1'b0,1'b0,34'b0};//门铃
        else if(r_st_nstate == P_ST_READ && r_cnt == 0)
            rm_axis_ireq_tdata <= {8'd0,4'b0010,4'b0100,1'b0,2'b00,1'b0,8'hFF,1'b0,1'b0,34'b0};//读
        else if(r_st_nstate == P_ST_MESSAGE && r_cnt == 0)
            rm_axis_ireq_tdata <= {4'd0,4'd0,4'b1011,4'b0000,1'b0,2'b00,1'b0,8'd63,1'b0,1'b0,34'b0};//消息
        else if(w_m_axi_ireq_act)
            case(r_cnt)
                0       : rm_axis_ireq_tdata <= {4{r_cnt}}  ;
                default : rm_axis_ireq_tdata <= {4{r_cnt}}  ;
            endcase
        else
            rm_axis_ireq_tdata <= rm_axis_ireq_tdata;
end


always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_ireq_tlast <= 'd0;
    else
        if(rm_axis_ireq_tlast && w_m_axi_ireq_act)
            rm_axis_ireq_tlast <= 'd0;
        else if(r_st_nstate == P_ST_WRITE && r_cnt == 32 -1 )
            rm_axis_ireq_tlast <= 1'b1;
        else if(r_st_nstate == P_ST_DB && r_st_cnt == 0)
            rm_axis_ireq_tlast <= 1'b1;
        else if(r_st_nstate == P_ST_READ && r_st_cnt == 0)
            rm_axis_ireq_tlast <= 1'b1;
        else if(r_st_nstate == P_ST_MESSAGE && w_m_axi_ireq_act)
            rm_axis_ireq_tlast <= 1'b1;
        else
            rm_axis_ireq_tlast <= rm_axis_ireq_tlast ;
        
end


always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_ireq_tvalid <= 'd0;
    else
        if(rm_axis_ireq_tlast && w_m_axi_ireq_act)
            rm_axis_ireq_tvalid <= 'd0;
        else if(r_st_nstate == P_ST_WRITE && r_st_cnt == 0)
            rm_axis_ireq_tvalid <= 1'b1;
        else if(r_st_nstate == P_ST_DB && r_st_cnt == 0)
            rm_axis_ireq_tvalid <= 1'b1;
        else if(r_st_nstate == P_ST_READ && r_st_cnt == 0)
            rm_axis_ireq_tvalid <= 1'b1;
        else if(r_st_nstate == P_ST_MESSAGE && r_st_cnt == 0)
            rm_axis_ireq_tvalid <= 1'b1;
        else
            rm_axis_ireq_tvalid <= rm_axis_ireq_tvalid;
        
end

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_ireq_tkeep <= 'd0;
    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 <= 8'h00;
end


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

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

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_read_cmd_valid <= 'd0;
    else 
        if(r_treq_cnt == 0 && w_s_axi_treq_act)
            r_read_cmd_valid <= 1'b1;
        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 == 8'b0010_0100)
            r_read_triger <= 1'b1;
        else 
            r_read_triger <= 'd0;    
end



always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        rm_axis_tresp_tvalid <= 'd0;
    else
        if(rm_axis_tresp_tlast && w_m_axi_tresp_act)
            rm_axis_tresp_tvalid <= 'd0; 
        else if(r_read_triger)
            rm_axis_tresp_tvalid <= 1'b1;
        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(rm_axis_tresp_tlast && w_m_axi_tresp_act)
            rm_axis_tresp_tlast <= 'd0;
        else if(r_read_cnt == 31)
            rm_axis_tresp_tlast <= 1'b1;
        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'b0,2'b0,1'b0,8'd0,1'b0,1'b0,34'd0};
        else
            rm_axis_tresp_tdata <= {4{r_read_cnt - 1}};
end 

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

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

always@(posedge i_clk,posedge i_rst)begin
    if(i_rst)
        r_read_cnt <= 'd0;
    else
        if(r_read_cnt == 32 )
            r_read_cnt <= 'd0;
        else if(r_read_triger || w_m_axi_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)
        rs_axis_treq_tready <= 'd1;
    else
        rs_axis_treq_tready <= 1'b1;
end


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


    
endmodule

仿真图如下:

如图在ireq端口上首先发送写事务和数据,之后发起门铃事务,在之后发起读事务。

在iresp端口上返回读过来的数据

 最后读完数据后,可以发起消息事务,通知对端已经接收到数据

四、总结

本篇文章目的在于简单的实践一下SRIO IP核,所以操作非常简单。如果真的要去用SRIO协议,需要涉及的理论还是挺多的。

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

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

相关文章

使用yolov5训练自己的目标检测模型

使用yolov5训练自己的目标检测模型 使用yolov5训练自己的目标检测模型1. 项目的克隆2. 项目代码结构3. 环境的安装和依赖的安装4. 数据集和预训练权重的准备4.1利用labelimg标注数据和数据的准备4.1.1 **labelimg介绍:**4.1. 2 labelimg的安装 4.2 使用labelimg4.2.1 数据准备4…

[疑难杂症2024-003]如何判断一张没有头信息的dcm图像,是否是压缩图像?

本文由Markdown语法编辑器编辑完成&#xff0e; 1. 前言: DCM格式&#xff0c;是医学图像领域里面的通用格式&#xff0e;DCM图像一般分为两大部分&#xff0c;一部分是TAG信息&#xff0c;一部分是像素. 而TAG信息&#xff0c;一般又会分为两部分&#xff0c;如下图所示, 是…

编写Spark独立应用程序

执行本文之前&#xff0c;先搭建好spark的开发环境&#xff0c;我目前只搭建了standalone模式&#xff0c;参考链接 &#xff1a; Spark Standalone模式部署-CSDN博客 1. 安装sbt 1&#xff09;下载sbt 网址&#xff1a;https://www.scala-sbt.org/download.html &#xff0c…

Linux 系统下的进程间通信 IPC 入门 「下」

以下内容为本人的学习笔记&#xff0c;如需要转载&#xff0c;请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/IvPHnEsC6ZdIHaFL8Deazg 共享内存 我们在进程间传输比较大的数据块时&#xff0c;通常选用共享内存的方式。共享内存大小也是有限制的&#xff0…

Python进阶编程 --- 3.闭包、装饰器、设计模式、多线程、网络编程、正则表达式、递归

文章目录 第三章&#xff1a;3.1 闭包3.2 装饰器语法糖写法 3.3 设计模式3.3.1 单例模式3.3.2 工厂模式 3.4 多线程3.4.1 进程、线程和并行执行3.4.2 多线程编程 3.5 网络编程3.5.1 Socket3.5.2 服务端开发3.5.3 客户端开发 3.6 正则表达式3.6.1 基础匹配3.6.2 元字符匹配单字符…

风力发电自动化控制系统中的智能化技术应用研究

风力发电自动化控制系统中的智能化技术应用研究 随碳中和目标的提出和执行&#xff0c;风能发电作为新能源行业的核心部分&#xff0c;步入了它的黄金发展期。由于风能资源具有间歇性、随机性等特点&#xff0c;这给风电的高效利用带来了巨大挑战。为了增强风力发电系统的工作效…

Py深度学习基础|Numpy基础总结

注&#xff1a;本文来自菜鸟教程学习总结 一、数组属性 NumPy 的数组中比较重要 ndarray 对象属性有&#xff1a; 注意&#xff1a;使用reshape后&#xff0c;数组的结构&#xff08;即元素的排列顺序和内在连接&#xff09;没有改变&#xff0c;但因为返回的是一个视图&#…

PTA L1-009 N个数求和 【C++】【辗转相除法】【Python】

C&#xff1a; 辗转相除法&#xff1a; 每次算最小公倍数和最大公约数都是用的常规思路&#xff0c;本身是不会有错的&#xff0c;但是当数据很大时&#xff0c;就会出现错误&#xff0c;时间复杂度过高 辗转相除法&#xff0c;又称欧几里德算法&#xff08;Euclidean Algori…

接口压力测试 jmeter--增强篇(二)

前期准备 1. JMeter的插件的安装 下载Jmeter Plugins Manager对插件进行管理 &#xff08;1&#xff09;下载地址&#xff1a;https://jmeter-plugins.org/install/Install/ &#xff08;2&#xff09;下载后&#xff0c;将jar包放到jmeter包目录下/lib/ext目录下 &#xff0…

【YOLOv8改进[检测头Head]】YOLOv8的“新头”之动态头(DynamicHead)

目录 一 DynamicHead 二 YOLOv8的“新头”之动态头 1 总体修改 2 配置文件 3 训练 其他 一 DynamicHead 官方论文地址&#xff1a;https://arxiv.org/pdf/2106.08322.pdf 官方代码地址&#xff1a;GitCode - 开发者的代码家园 在计算机视觉应用中&#xff0c;目标检测…

启动appium服务的2种方法(python脚本cmd窗口)

1.通过cmd窗口命令来启动 2.通过python代码启动 2.1启动单个appium服务 2.2启动多个appium服务 3.端口说明 一.端口号设置Appium服务器端口&#xff1a;4723 bp端口&#xff1a;4724 Appium服务器端口&#xff1a;4725 bp端口&#xff1a;4726可以看到appium服务器端口和bp端…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程&#xff1a; 导入依赖&#xff08;javax.servlet-api 和 spring-webmvc&#xff09;Servlet 容器配置类&#xff…

VirtualBox虚拟机使用win11系统,忘记密码如何重置密码

1. 点击重启同时按住Shift&#xff08;按住不放&#xff09; 2. 直到出现下面的界面&#xff0c;释放Shift&#xff0c;并进入疑难解答 3. 进入高级选项 4. 进入命令提示符 5. 发现当前是在X盘&#xff1f; 6. 进入C:\Windows\System32 c: cd Windows\System32 7. 备份osk.exe…

SpringCloud系列(5)--SpringCloud微服务工程公共部分提取

前言&#xff1a;在上一章节中我们创建了两个个SpringCloud工程&#xff0c;但在两个工程中分别存在着一些重复的部分&#xff0c;例如重复的实体类&#xff08;如图所示&#xff09;&#xff0c;这样会造成系统的冗余&#xff0c;所以我们需要把公共的类提取到一个工程里&…

预约小程序新选择:强大后端管理功能一览

拥有一个功能齐全、操作便捷的小程序对于商家来说至关重要。为了满足广大商家的需求&#xff0c;乔拓云平台提供了丰富的模板资源&#xff0c;帮助用户快速搭建预约型小程序&#xff0c;并配备了强大的后端管理功能&#xff0c;让商家能够轻松管理预约订单&#xff0c;提升运营…

Centos7 ElasticSearch集群搭建

1. 服务器环境配置 1.1 配置hosts文件 3台服务器都要执行 vim /etc/hosts; # 将以下内容写入3台服务器hosts文件 192.168.226.148 es001 192.168.226.149 es002 192.168.226.150 es003 1.2 关闭防火墙 3台服务器都要执行 systemctl stop firewalld; systemctl disable…

【opencv】dnn示例-speech_recognition.cpp 使用DNN模块结合音频信号处理技术实现的英文语音识别...

模型下载地址&#xff1a; https://drive.google.com/drive/folders/1wLtxyao4ItAg8tt4Sb63zt6qXzhcQoR6 终端输出&#xff1a;&#xff08;audio6.mp3 、audio10.mp3&#xff09; [ERROR:00.002] global cap_ffmpeg_impl.hpp:1112 open VIDEOIO/FFMPEG: unsupported parameter…

# 从浅入深 学习 SpringCloud 微服务架构(一)基础知识

从浅入深 学习 SpringCloud 微服务架构&#xff08;一&#xff09;基础知识 1、系统架构演变&#xff1a; 1&#xff09;单体应用架构。如电商项目。 用户管理、商品管理、订单管理&#xff0c;在一个模块里。 优点&#xff1a;开发简单&#xff0c;快速&#xff0c;适用于…

Mac下brew安装php7.4

这里作者挂了梯子&#xff0c;所以很流畅&#xff01; brew的下载&#xff0c;可参考另外一篇博文&#xff5e;Homebrew 安装与卸载 1、将第三方仓库加入brew brew tap shivammathur/php2、安装指定版本的PHP brew install php7.43、替换Mac自带PHP环境并刷新环境变量 -> …

基于simulink的模拟锁相环和数字锁相环建模与对比仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 模拟锁相环&#xff08;PLL&#xff09;的基本原理 4.2 数字锁相环&#xff08;DPLL&#xff09;的基本原理 5.完整工程文件 1.课题概述 模拟锁相环和数字锁相环建模的simulink建模&#xff0c;对…