当前位置:   article > 正文

SRIO系列-仿真测试

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奇哥的系列网课。

  1. module SRIO_Engine(
  2. input i_clk ,
  3. input i_rst ,
  4. output m_axis_ireq_tvalid ,
  5. input m_axis_ireq_tready ,
  6. output m_axis_ireq_tlast ,
  7. output [63:0] m_axis_ireq_tdata ,
  8. output [7: 0] m_axis_ireq_tkeep ,
  9. output [31:0] m_axis_ireq_tuser ,
  10. input s_axis_iresp_tvalid ,
  11. output s_axis_iresp_tready ,
  12. input s_axis_iresp_tlast ,
  13. input [63:0] s_axis_iresp_tdata ,
  14. input [7: 0] s_axis_iresp_tkeep ,
  15. input [31:0] s_axis_iresp_tuser ,
  16. input s_axis_treq_tvalid ,
  17. output s_axis_treq_tready ,
  18. input s_axis_treq_tlast ,
  19. input [63:0] s_axis_treq_tdata ,
  20. input [7: 0] s_axis_treq_tkeep ,
  21. input [31:0] s_axis_treq_tuser ,
  22. output m_axis_tresp_tvalid ,
  23. input m_axis_tresp_tready ,
  24. output m_axis_tresp_tlast ,
  25. output [63:0] m_axis_tresp_tdata ,
  26. output [7: 0] m_axis_tresp_tkeep ,
  27. output [31:0] m_axis_tresp_tuser
  28. );
  29. // assign s_axis_iresp_tready = 0 ;
  30. // assign s_axis_treq_tready = 0 ;
  31. reg rm_axis_ireq_tvalid ;
  32. reg rm_axis_ireq_tlast ;
  33. reg [63:0] rm_axis_ireq_tdata ;
  34. reg [7: 0] rm_axis_ireq_tkeep ;
  35. reg [31:0] rm_axis_ireq_tuser ;
  36. reg rs_axis_iresp_tready ;
  37. reg rs_axis_treq_tready ;
  38. reg rm_axis_tresp_tvalid ;
  39. reg rm_axis_tresp_tlast ;
  40. reg [63:0] rm_axis_tresp_tdata ;
  41. reg [7: 0] rm_axis_tresp_tkeep ;
  42. reg [31:0] rm_axis_tresp_tuser ;
  43. reg [15:0] r_cnt ;
  44. reg [7: 0] r_read_cmd ;
  45. reg r_read_cmd_valid ;
  46. reg r_read_triger ;
  47. reg [15:0] r_treq_cnt ;
  48. reg [15:0] r_read_cnt ;
  49. wire w_m_axi_ireq_act ;
  50. wire w_s_axi_iresp_act ;
  51. wire w_s_axi_treq_act ;
  52. wire w_m_axi_tresp_act ;
  53. assign m_axis_ireq_tvalid = rm_axis_ireq_tvalid ;
  54. assign m_axis_ireq_tlast = rm_axis_ireq_tlast ;
  55. assign m_axis_ireq_tdata = rm_axis_ireq_tdata ;
  56. assign m_axis_ireq_tkeep = rm_axis_ireq_tkeep ;
  57. assign m_axis_ireq_tuser = rm_axis_ireq_tuser ;
  58. assign s_axis_iresp_tready = rs_axis_iresp_tready ;
  59. assign s_axis_treq_tready = rs_axis_treq_tready ;
  60. assign m_axis_tresp_tvalid = rm_axis_tresp_tvalid ;
  61. assign m_axis_tresp_tlast = rm_axis_tresp_tlast ;
  62. assign m_axis_tresp_tdata = rm_axis_tresp_tdata ;
  63. assign m_axis_tresp_tkeep = rm_axis_tresp_tkeep ;
  64. assign m_axis_tresp_tuser = rm_axis_tresp_tuser ;
  65. assign w_m_axi_ireq_act = m_axis_ireq_tready & rm_axis_ireq_tvalid;
  66. assign w_s_axi_iresp_act = s_axis_iresp_tvalid & rs_axis_iresp_tready;
  67. assign w_s_axi_treq_act = s_axis_treq_tvalid & rs_axis_treq_tready;
  68. assign w_m_axi_tresp_act = m_axis_tresp_tready && rm_axis_tresp_tvalid;
  69. localparam P_ST_IDLE = 5'b00001 ,
  70. P_ST_WRITE = 5'b00010 ,
  71. P_ST_DB = 5'b00100 ,
  72. P_ST_READ = 5'b01000 ,
  73. P_ST_MESSAGE = 5'b10000 ;
  74. reg [4: 0] r_st_nstate ;
  75. reg [4: 0] r_st_cstate ;
  76. reg [15:0] r_st_cnt ;
  77. always@(posedge i_clk,posedge i_rst)begin
  78. if(i_rst)
  79. r_st_cstate <= P_ST_IDLE;
  80. else
  81. r_st_cstate <= r_st_nstate;
  82. end
  83. always@(*)begin
  84. r_st_nstate = P_ST_IDLE;
  85. case(r_st_cstate)
  86. P_ST_IDLE:begin
  87. if(r_st_cnt == 1000)
  88. r_st_nstate = P_ST_WRITE;
  89. else
  90. r_st_nstate = P_ST_IDLE;
  91. end
  92. P_ST_WRITE:begin
  93. if(w_m_axi_ireq_act && m_axis_ireq_tlast)
  94. r_st_nstate = P_ST_DB;
  95. else
  96. r_st_nstate = P_ST_WRITE;
  97. end
  98. P_ST_DB:begin
  99. if(w_m_axi_ireq_act && m_axis_ireq_tlast)
  100. r_st_nstate = P_ST_READ;
  101. else
  102. r_st_nstate = P_ST_DB;
  103. end
  104. P_ST_READ:begin
  105. if(w_s_axi_iresp_act && s_axis_iresp_tlast)
  106. r_st_nstate = P_ST_MESSAGE;
  107. else
  108. r_st_nstate = P_ST_READ;
  109. end
  110. P_ST_MESSAGE:begin
  111. if(w_m_axi_ireq_act && m_axis_ireq_tlast)
  112. r_st_nstate = P_ST_IDLE;
  113. else
  114. r_st_nstate = P_ST_MESSAGE;
  115. end
  116. default:begin
  117. r_st_nstate = P_ST_IDLE;
  118. end
  119. endcase
  120. end
  121. always@(posedge i_clk,posedge i_rst)begin
  122. if(i_rst)
  123. r_st_cnt <= 'd0;
  124. else
  125. if(r_st_cstate != r_st_nstate)
  126. r_st_cnt <= 'd0;
  127. else
  128. r_st_cnt <= r_st_cnt + 1;
  129. end
  130. always@(posedge i_clk,posedge i_rst)begin
  131. if(i_rst)
  132. r_cnt <= 'd0;
  133. else
  134. if(r_cnt == 32 && w_m_axi_ireq_act)
  135. r_cnt <= 'd0;
  136. else if(r_st_nstate == P_ST_WRITE && w_m_axi_ireq_act)//??
  137. r_cnt <= r_cnt + 1;
  138. else
  139. r_cnt <= r_cnt ;
  140. end
  141. always@(posedge i_clk,posedge i_rst)begin
  142. if(i_rst)
  143. rm_axis_ireq_tdata <= 'd0;
  144. else
  145. if(r_st_nstate == P_ST_WRITE && r_cnt == 0)
  146. rm_axis_ireq_tdata <= {8'd0,4'b0110,4'd0,1'b0,2'b00,1'b0,8'hFF,1'b0,1'b0,34'b0};//流写
  147. else if(r_st_nstate == P_ST_DB && r_cnt == 0)
  148. rm_axis_ireq_tdata <= {8'd0,4'b1010,4'd0,1'b0,2'b00,1'b0,8'h00,1'b0,1'b0,34'b0};//门铃
  149. else if(r_st_nstate == P_ST_READ && r_cnt == 0)
  150. rm_axis_ireq_tdata <= {8'd0,4'b0010,4'b0100,1'b0,2'b00,1'b0,8'hFF,1'b0,1'b0,34'b0};//
  151. else if(r_st_nstate == P_ST_MESSAGE && r_cnt == 0)
  152. 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};//消息
  153. else if(w_m_axi_ireq_act)
  154. case(r_cnt)
  155. 0 : rm_axis_ireq_tdata <= {4{r_cnt}} ;
  156. default : rm_axis_ireq_tdata <= {4{r_cnt}} ;
  157. endcase
  158. else
  159. rm_axis_ireq_tdata <= rm_axis_ireq_tdata;
  160. end
  161. always@(posedge i_clk,posedge i_rst)begin
  162. if(i_rst)
  163. rm_axis_ireq_tlast <= 'd0;
  164. else
  165. if(rm_axis_ireq_tlast && w_m_axi_ireq_act)
  166. rm_axis_ireq_tlast <= 'd0;
  167. else if(r_st_nstate == P_ST_WRITE && r_cnt == 32 -1 )
  168. rm_axis_ireq_tlast <= 1'b1;
  169. else if(r_st_nstate == P_ST_DB && r_st_cnt == 0)
  170. rm_axis_ireq_tlast <= 1'b1;
  171. else if(r_st_nstate == P_ST_READ && r_st_cnt == 0)
  172. rm_axis_ireq_tlast <= 1'b1;
  173. else if(r_st_nstate == P_ST_MESSAGE && w_m_axi_ireq_act)
  174. rm_axis_ireq_tlast <= 1'b1;
  175. else
  176. rm_axis_ireq_tlast <= rm_axis_ireq_tlast ;
  177. end
  178. always@(posedge i_clk,posedge i_rst)begin
  179. if(i_rst)
  180. rm_axis_ireq_tvalid <= 'd0;
  181. else
  182. if(rm_axis_ireq_tlast && w_m_axi_ireq_act)
  183. rm_axis_ireq_tvalid <= 'd0;
  184. else if(r_st_nstate == P_ST_WRITE && r_st_cnt == 0)
  185. rm_axis_ireq_tvalid <= 1'b1;
  186. else if(r_st_nstate == P_ST_DB && r_st_cnt == 0)
  187. rm_axis_ireq_tvalid <= 1'b1;
  188. else if(r_st_nstate == P_ST_READ && r_st_cnt == 0)
  189. rm_axis_ireq_tvalid <= 1'b1;
  190. else if(r_st_nstate == P_ST_MESSAGE && r_st_cnt == 0)
  191. rm_axis_ireq_tvalid <= 1'b1;
  192. else
  193. rm_axis_ireq_tvalid <= rm_axis_ireq_tvalid;
  194. end
  195. always@(posedge i_clk,posedge i_rst)begin
  196. if(i_rst)
  197. rm_axis_ireq_tkeep <= 'd0;
  198. else
  199. rm_axis_ireq_tkeep <= 8'hff;
  200. end
  201. always@(posedge i_clk,posedge i_rst)begin
  202. if(i_rst)
  203. rm_axis_ireq_tuser <= 'd0;
  204. else
  205. rm_axis_ireq_tuser <= 8'h00;
  206. end
  207. always@(posedge i_clk,posedge i_rst)begin
  208. if(i_rst)
  209. r_treq_cnt <= 'd0;
  210. else
  211. if(w_s_axi_treq_act && s_axis_treq_tlast)
  212. r_treq_cnt <= 'd0;
  213. else if(w_s_axi_treq_act)
  214. r_treq_cnt <= r_treq_cnt + 1;
  215. end
  216. always@(posedge i_clk,posedge i_rst)begin
  217. if(i_rst)
  218. r_read_cmd <= 'd0;
  219. else
  220. if(r_treq_cnt == 0 && w_s_axi_treq_act)
  221. r_read_cmd <= s_axis_treq_tdata[55:48];
  222. else
  223. r_read_cmd <= r_read_cmd + 1;
  224. end
  225. always@(posedge i_clk,posedge i_rst)begin
  226. if(i_rst)
  227. r_read_cmd_valid <= 'd0;
  228. else
  229. if(r_treq_cnt == 0 && w_s_axi_treq_act)
  230. r_read_cmd_valid <= 1'b1;
  231. else
  232. r_read_cmd_valid <= 'd0;
  233. end
  234. always@(posedge i_clk,posedge i_rst)begin
  235. if(i_rst)
  236. r_read_triger <= 'd0;
  237. else
  238. if(r_read_cmd_valid && r_read_cmd == 8'b0010_0100)
  239. r_read_triger <= 1'b1;
  240. else
  241. r_read_triger <= 'd0;
  242. end
  243. always@(posedge i_clk,posedge i_rst)begin
  244. if(i_rst)
  245. rm_axis_tresp_tvalid <= 'd0;
  246. else
  247. if(rm_axis_tresp_tlast && w_m_axi_tresp_act)
  248. rm_axis_tresp_tvalid <= 'd0;
  249. else if(r_read_triger)
  250. rm_axis_tresp_tvalid <= 1'b1;
  251. else
  252. rm_axis_tresp_tvalid <= rm_axis_tresp_tvalid;
  253. end
  254. always@(posedge i_clk,posedge i_rst)begin
  255. if(i_rst)
  256. rm_axis_tresp_tlast <= 'd0;
  257. else
  258. if(rm_axis_tresp_tlast && w_m_axi_tresp_act)
  259. rm_axis_tresp_tlast <= 'd0;
  260. else if(r_read_cnt == 31)
  261. rm_axis_tresp_tlast <= 1'b1;
  262. else
  263. rm_axis_tresp_tlast <= rm_axis_tresp_tlast;
  264. end
  265. always@(posedge i_clk,posedge i_rst)begin
  266. if(i_rst)
  267. rm_axis_tresp_tdata <= 'd0;
  268. else
  269. if(r_read_triger)
  270. rm_axis_tresp_tdata <= {8'd0,4'b1101,4'b1000,1'b0,2'b0,1'b0,8'd0,1'b0,1'b0,34'd0};
  271. else
  272. rm_axis_tresp_tdata <= {4{r_read_cnt - 1}};
  273. end
  274. always@(posedge i_clk,posedge i_rst)begin
  275. if(i_rst)
  276. rm_axis_tresp_tkeep <= 'd0;
  277. else
  278. rm_axis_tresp_tkeep <= 'd0;
  279. end
  280. always@(posedge i_clk,posedge i_rst)begin
  281. if(i_rst)
  282. rm_axis_tresp_tuser <= 'd0;
  283. else
  284. rm_axis_tresp_tuser <= 'd0;
  285. end
  286. always@(posedge i_clk,posedge i_rst)begin
  287. if(i_rst)
  288. r_read_cnt <= 'd0;
  289. else
  290. if(r_read_cnt == 32 )
  291. r_read_cnt <= 'd0;
  292. else if(r_read_triger || w_m_axi_tresp_act)
  293. r_read_cnt <= r_read_cnt + 1;
  294. else
  295. r_read_cnt <= r_read_cnt;
  296. end
  297. always@(posedge i_clk,posedge i_rst)begin
  298. if(i_rst)
  299. rs_axis_treq_tready <= 'd1;
  300. else
  301. rs_axis_treq_tready <= 1'b1;
  302. end
  303. always@(posedge i_clk,posedge i_rst)begin
  304. if(i_rst)
  305. rs_axis_iresp_tready <= 'd1;
  306. else
  307. rs_axis_iresp_tready <= 1'b1;
  308. end
  309. endmodule

仿真图如下:

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

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

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

四、总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/487980
推荐阅读
相关标签
  

闽ICP备14008679号