SRIO系列-仿真测试

news2024/11/24 11:37:13

一、前言

前两篇已经讲述了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协议,需要涉及的理论还是挺多的。

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

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

相关文章

【C++题解】1607. 两位数运算

问题&#xff1a;1607. 两位数运算 类型&#xff1a;基本运算、拆位求解 题目描述&#xff1a; 小丽在编程课上学会了拆位运算&#xff0c;她已经可以拆出一个两位整数的十位和个位了&#xff0c;她想知道这个整数的十位 / 个位的结果是多少&#xff0c;请编程帮她实现&#…

异地网络如何在线共享文件夹?

信息的传输和共享变得异常便利。而对于拥有异地办公或分布式团队的公司或组织来说&#xff0c;跨地域的文件共享变得尤为重要。在这个背景下&#xff0c;“异地网络在线共享文件夹”应运而生。 异地网络在线共享文件夹的意义 对于异地办公的团队来说&#xff0c;共享文件夹是一…

《Super Simple Skybox》天空盒 -- 创造绝美天空的神奇工具!限时免费!

《Super Simple Skybox》天空盒 -- 创造绝美天空的神奇工具&#xff01;限时免费&#xff01; 前言内容介绍资源特色动态&#xff0c;美丽的天空在几秒钟内即插即用 功能列表领取兑换码 前言 ^^在这个充满创意与想象的世界里&#xff0c;Unity 免费资源犹如一颗璀璨的明珠&…

信息系统项目管理师0055:优化和持续改进(4信息系统管理—4.1管理方法—4.1.5优化和持续改进)

点击查看专栏目录 文章目录 4.1.5优化和持续改进1.定义阶段2.度量阶段3.分析阶段4.改进/设计阶段5.控制/验证阶段4.1.5优化和持续改进 优化和持续改进是信息系统管理活动中的一个环节,良好的优化和持续改进管理活动能够有效保障信息系统的性能和可用性等,延长整体系统的有效使…

redis的数据结构报错

文章目录 redis的数据结构报错Redis使用LocalDateTime报错问题 redis的数据结构报错 Redis使用LocalDateTime报错问题 SpringBoot整合Redis时&#xff0c;使用LocalDate以下报错 org.springframework.data.redis.serializer.SerializationException: Could not read JSON: C…

统一SQL-支持cast函数

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;Postgresql&#xff0c;TDSQL-MySQL&#xff0c;达梦8&#xff0c;LightDB-Oracle 操作目标 在Oracle中&#xff0c;cast函数允许将一种…

CSS:filter(滤镜)属性

用途 可以用于img标签&#xff0c;div标签等 图像&#xff0c;背景&#xff0c;边框的调整 常用属性 1. 灰度 grayscale()&#xff0c;默认是0&#xff0c;100%就是黑白 2. blux 给图像设置高斯模糊的程度&#xff0c;radius值设定高斯模糊的程序&#xff0c;表示像素点…

android studio gradle 下载不下来的问题

有时候由于网络问题&#xff0c;会发现 android-studio 或 idea 下载不懂 gradle&#xff0c;可以修改 gradle-wrapper.properties 配置文件中的 distributionUrl 选项来解决这个问题。 distributionUrlhttps\://mirrors.cloud.tencent.com/gradle/gradle-5.1.1-all.zip 这个选…

遥感图像分割 | 基于一种类似UNet的Transformer算法实现遥感城市场景图像的语义分割_适用于卫星图像+航空图像+无人机图像

项目应用场景 面向遥感城市场景图像语义分割场景&#xff0c;项目采用类似 UNet 的 Transformer 深度学习算法来实现&#xff0c;项目适用于卫星图像、航空图像、无人机图像等。 项目效果 项目细节 > 具体参见项目 README.md (1) 安装依赖 conda create -n airs python3.8…

常用的7个免费ChatGPT网站

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

OpenCV从入门到精通实战(六)——多目标追踪

基于原生的追踪 使用OpenCV库实现基于视频的对象追踪。通过以下步骤和Python代码&#xff0c;您将能够选择不同的追踪器&#xff0c;并对视频中的对象进行实时追踪。 步骤 1: 导入必要的库 首先&#xff0c;我们需要导入一些必要的Python库&#xff0c;包括argparse、time、…

Debian12 中重新安装MSSQL 并指定服务器、数据库、数据表字段的字符排序规则和默认语言等参数

在 Linux 上配置 SQL Server 设置 - SQL Server | Microsoft Learn 零、查看sql server 服务器支持的字符排序规则 SELECT Name from sys.fn_helpcollations() where name Like Chinese% go------ Chinese_PRC_CI_AI Chinese_PRC_CI_AI_WS Chinese_PRC_CI_AI_KS Chinese_PRC_…

读所罗门的密码笔记21_读后总结与感想兼导读

1. 基本信息 所罗门的密码&#xff1a;AI时代的价值、权力与信任 Solomons Code 奥拉夫格罗思 马克尼兹伯格 著 中信出版社,2022年5月出版 1.1. 读薄率 书籍总字数257千字&#xff0c;笔记总字数37780字。 读薄率37780257000≈14.7% 1.2. 读厚方向 千脑智能 脑机穿越 …

政安晨:【Keras机器学习示例演绎】(一)—— 利用类 U-Net 架构进行图像分割

目录 下载数据 准备输入图像的路径和目标分割掩码 一幅输入图像和相应的分割掩码是什么样子的&#xff1f; 准备数据集&#xff0c;以加载和矢量化成批数据 准备 U-Net Xception 风格模型 预留验证分割 训练模型 可视化预测 政安晨的个人主页&#xff1a;政安晨 欢迎 &…

SpringBoot整合零一万物模型API进行多轮对话

前期准备工作 零一万物官网&#xff1a;https://www.01.ai/cn 零一万物大模型开放平台&#xff1a;https://platform.lingyiwanwu.com/ 选择理由 性价比高很高&#xff0c;模型整体不错&#xff0c;新用户送60元&#xff0c;非常适合研究学习。 开发 只提供了http接口和p…

OpenHarmony UI动画-lottie

简介 lottie是一个适用于OpenHarmony的动画库&#xff0c;它可以解析Adobe After Effects软件通过Bodymovin插件导出的json格式的动画&#xff0c;并在移动设备上进行本地渲染。 下载安裝 ohpm install ohos/lottieOpenHarmony ohpm 环境配置等更多内容&#xff0c;请参考如何…

机器视觉【1】-机械臂视觉

文章目录 Eye-to-HandEye-in-Hand基于Eye-in-Hand型机械臂单目视觉定位单目相机标定针孔相机模型畸变标定方法机械臂手眼标定手眼标定求解图像预处理图像灰度化与二值化图像滤波图像特征匹配机械臂单目视觉定位目标物体图像深度信息目标物体中心定位参考文献根据机械臂与相机所…

python来实现nmap扫描

今天分享一个用python实现nmap扫描的方法&#xff0c;以下是实现步骤 代码如下&#xff1a; import subprocessmissing_ips {166.139.144.163, 31.47.8.35, 58.242.86.191, 212.178.135.62, 103.1.35.114} port "7" for missing_ip in missing_ips:# 构造nmap命令…

数学建模--蒙特卡罗法MATLAB代码保姆式解析

1.简单介绍 2.思想的实际运用 我们利用蒙特卡罗法的思想求解圆周率π的值&#xff0c;这里求得的肯定是近似值&#xff0c;我们是通过大量的模拟实验&#xff0c;利用概率求解的&#xff0c;但是这个值和我们的精确值之间还是有一定的误差的&#xff1b; 我们的思想就是在半径为…

智慧化赋能园区新未来:探讨智慧园区如何以科技创新为引擎,推动产业转型升级

随着科技的飞速发展&#xff0c;智慧化已成为推动园区产业升级和转型的重要引擎。智慧园区&#xff0c;以其高效、便捷、智能的特性&#xff0c;正逐步改变传统的产业园区模式&#xff0c;为产业发展注入新的活力。本文旨在探讨智慧园区如何以科技创新为引擎&#xff0c;推动产…