赞
踩
前两篇已经讲述了SRIO协议的概况,以及xilinx SRIO IP核的使用方式,已经在搭建工程的过程中时钟和复位的注意事项。
整个框图也是按照之前的工程进行搭建,首先时SRIO_Channel,由SRIO IP核和时钟、复位模块组成,这是在之前的工程搭建中一种采用的一种Channel结构。其次,SRIO Module是按照QPLL共享的方式去管理Channel,使得多个通道能够共享QPLL。最后,用户侧逻辑采用了一个SRIO Engine一共有4次的事务传输,分别是:
这部分参考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协议,需要涉及的理论还是挺多的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。