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,中端处理等。

c 复制代码
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

相关推荐
dbdr09013 分钟前
Linux 入门到精通,真的不用背命令!零基础小白靠「场景化学习法」,3 个月拿下运维 offer,第二十六天
linux·运维·服务器·网络·python·学习
大白的编程日记.27 分钟前
【Linux学习笔记】信号的深入理解之软件条件产生信号
linux·笔记·学习
buyutang_35 分钟前
C/C++ Linux系统编程:线程控制详解,从线程创建到线程终止
linux·c语言·c++·学习
博览鸿蒙1 小时前
成为一个年薪30W+的FPGA工程师是一种什么体验?
fpga开发
yzx9910131 小时前
图像去雾:从暗通道先验到可学习融合——一份可跑的 PyTorch 教程
人工智能·pytorch·学习
练习时长两年半的Java练习生(升级中)2 小时前
从0开始学习Java+AI知识点总结-30.前端web开发(JS+Vue+Ajax)
前端·javascript·vue.js·学习·web
Rhys..2 小时前
python + Flask模块学习 1 基础用法
python·学习·前端框架·flask
lingggggaaaa3 小时前
小迪安全v2023学习笔记(七十八讲)—— 数据库安全&Redis&CouchDB&H2database&未授权&CVE
redis·笔记·学习·算法·安全·网络安全·couchdb
Jayyih3 小时前
嵌入式系统学习Day29(tcp)
网络·学习·tcp/ip
dog2503 小时前
乐观并发: TCP 与编程实践
网络·网络协议·tcp/ip