当前位置:   article > 正文

10G MAC层设计系列-(3)CRC Process 模块

10G MAC层设计系列-(3)CRC Process 模块

一、前言

前面已经讲述了在Xilinx 10G PCS/PMA IP核的基础上设计的PHY层,已经xgmii接口的MAC_RX模块,本节主要描述MAC_RX之后的CRC_Process模块。

CRC_Prcess的主要作用就是利用RAM地址“返回初始状态”的方式将crc错误的帧丢掉,并将正确的传递到上级。

二、模块设计

首先,将数据帧、最后一次传输的KEEP信号存入RAM

  1. BRAM_DATA_64X512 u_BRAM_DATA_64X512 (
  2. .clka (i_clk ), // input wire clka
  3. .wea (rs_axis_valid ), // input wire [0 : 0] wea
  4. .addra (r_bram_wdata_addr ), // input wire [8 : 0] addra
  5. .dina (rs_axis_data ), // input wire [63 : 0] dina
  6. .clkb (i_clk ), // input wire clkb
  7. .enb (r_bram_data_rden ), // input wire enb
  8. .addrb (r_bram_rdata_addr ), // input wire [8 : 0] addrb
  9. .doutb (w_bram_data_out ) // output wire [63 : 0] doutb
  10. );
  11. //将每一帧的最后一次传输的KEEP信号存入到RAM
  12. BRAM_KEEP_8X128 your_instance_name (
  13. .clka (i_clk ), // input wire clka
  14. .wea (rs_axis_last ), // input wire [0 : 0] wea
  15. .addra (r_bram_wkeep_addr ), // input wire [6 : 0] addra
  16. .dina (rs_axis_keep ), // input wire [7 : 0] dina
  17. .clkb (i_clk ), // input wire clkb
  18. .enb (r_bram_keep_rden ), // input wire enb
  19. .addrb (r_bram_rkeep_addr ), // input wire [6 : 0] addrb
  20. .doutb (w_bram_rkeep ) // output wire [7 : 0] doutb
  21. );

在此过程中存在一个初始化的地址信号,只有检测到CRC校验正确之后才会更新初始的地址信号。

  1. //写数据初始化地址,当CRC校验正确的时候才会改变
  2. always@(posedge i_clk,posedge i_rst)begin
  3. if(i_rst)
  4. r_init_wdata_addr <= 'd0;
  5. else
  6. if(w_crc_correct)
  7. r_init_wdata_addr <= r_bram_wdata_addr + 1;
  8. else
  9. r_init_wdata_addr <= r_init_wdata_addr;
  10. end
  11. //写数据地址
  12. always@(posedge i_clk,posedge i_rst)begin
  13. if(i_rst)
  14. r_bram_wdata_addr <= 'd0;
  15. else
  16. if(s_axis_valid && !rs_axis_valid)
  17. r_bram_wdata_addr <= r_init_wdata_addr;
  18. else if(rs_axis_valid && !rs_axis_last)
  19. r_bram_wdata_addr <= r_bram_wdata_addr + 1;
  20. else
  21. r_bram_wdata_addr <= r_bram_wdata_addr;
  22. end
  23. //写KEEP信号的初始化地址,当CRC校验正确的时候才会改变
  24. always@(posedge i_clk,posedge i_rst)begin
  25. if(i_rst)
  26. r_init_wkeep_addr <= 'd0;
  27. else
  28. if(w_crc_correct)
  29. r_init_wkeep_addr <= r_bram_wkeep_addr + 1;
  30. else
  31. r_init_wkeep_addr <= r_init_wkeep_addr;
  32. end
  33. //写KEEP信号地址
  34. always@(posedge i_clk,posedge i_rst)begin
  35. if(i_rst)
  36. r_bram_wkeep_addr <= 'd0;
  37. else
  38. if(s_axis_last)
  39. r_bram_wkeep_addr <= r_init_wkeep_addr;
  40. else
  41. r_bram_wkeep_addr <= r_bram_wkeep_addr;
  42. end

最后的帧长等信息只有在CRC校验正确之后存入FIFO,用FIFO的empty信号判断RAM中是否有正确的数据。

  1. FIFO_USER_INFO_80X128 u_FIFO_USER_INFO_80X128 (
  2. .clk (i_clk ), // input wire clk
  3. .srst (i_rst ), // input wire srst
  4. .din (r_user_info ), // input wire [79 : 0] din
  5. .wr_en (w_crc_correct ), // input wire wr_en
  6. .rd_en (r_fifo_user_info_rden ), // input wire rd_en
  7. .dout (w_fifo_user_out ), // output wire [79 : 0] dout
  8. .full (w_fifo_user_info_full ), // output wire full
  9. .empty (w_fifo_user_info_empty ) // output wire empty
  10. );

在读数据的过程中,便是根据FIFO是否为空判断是否有有效数据,之后读出FIFO帧长等信息,根据帧长去读取RAM中的数据。

  1. //读取USER_INFO FIFO中的信息
  2. always@(posedge i_clk,posedge i_rst)begin
  3. if(i_rst)
  4. r_fifo_user_info_rden <= 'd0;
  5. else
  6. if(!w_fifo_user_info_empty && !r_fifo_rden_lock)
  7. r_fifo_user_info_rden <= 1'b1;
  8. else
  9. r_fifo_user_info_rden <= 1'b0;
  10. end
  11. //锁存信号
  12. always@(posedge i_clk,posedge i_rst)begin
  13. if(i_rst)
  14. r_fifo_rden_lock <= 'd0;
  15. else
  16. if(!w_fifo_user_info_empty)
  17. r_fifo_rden_lock <= 1'b1;
  18. else if(rm_axis_last)
  19. r_fifo_rden_lock <= 1'b0;
  20. else
  21. r_fifo_rden_lock <= r_fifo_rden_lock;
  22. end
  23. //读USER INFO
  24. always@(posedge i_clk,posedge i_rst)begin
  25. if(i_rst)
  26. rm_axis_user <= 'd0;
  27. else
  28. rm_axis_user <= w_fifo_user_out;
  29. end
  30. //读数据的使能慢读USER INFO的使能一拍
  31. always@(posedge i_clk,posedge i_rst)begin
  32. if(i_rst)
  33. r_bram_data_rden <= 'd0;
  34. else
  35. if(r_fifo_user_info_rden)
  36. r_bram_data_rden <= 1'b1;
  37. else if(r_data_cnt == w_fifo_user_out[79:64])
  38. r_bram_data_rden <= 'd0;
  39. else
  40. r_bram_data_rden <= r_bram_data_rden;
  41. end
  42. //读数据地址
  43. always@(posedge i_clk,posedge i_rst)begin
  44. if(i_rst)
  45. r_bram_rdata_addr <= 'd0;
  46. else
  47. if(r_fifo_user_info_rden)
  48. r_bram_rdata_addr <= r_init_rdata_addr;
  49. else if((r_data_cnt < w_fifo_user_out[79:64]) && r_data_cnt)
  50. r_bram_rdata_addr <= r_bram_rdata_addr + 1;
  51. else
  52. r_bram_rdata_addr <= r_bram_rdata_addr ;
  53. end
  54. always@(posedge i_clk,posedge i_rst)begin
  55. if(i_rst)
  56. r_init_rdata_addr <= 'd0;
  57. else
  58. if((r_data_cnt == w_fifo_user_out[79:64]) && r_bram_data_rden)
  59. r_init_rdata_addr <= r_bram_rdata_addr + 1;
  60. else
  61. r_init_rdata_addr <= r_init_rdata_addr;
  62. end
  63. always@(posedge i_clk,posedge i_rst)begin
  64. if(i_rst)
  65. r_bram_data_rden_ff1 <= 'd0;
  66. else
  67. r_bram_data_rden_ff1 <= r_bram_data_rden;
  68. end
  69. //读keep使能
  70. always@(posedge i_clk,posedge i_rst)begin
  71. if(i_rst)
  72. r_bram_keep_rden <= 1'b0;
  73. else
  74. if(r_data_cnt == w_fifo_user_out[79:64] -1)
  75. r_bram_keep_rden <= 1'b1;
  76. else
  77. r_bram_keep_rden <= 1'b0;
  78. end
  79. always@(posedge i_clk,posedge i_rst)begin
  80. if(i_rst)
  81. r_bram_rkeep_addr <= 'd0;
  82. else
  83. if(r_data_cnt == w_fifo_user_out[79:64] -1)
  84. r_bram_rkeep_addr <= r_init_rkeep_addr;
  85. else
  86. r_bram_rkeep_addr <= r_bram_rkeep_addr;
  87. end
  88. always@(posedge i_clk,posedge i_rst)begin
  89. if(i_rst)
  90. r_init_rkeep_addr <= 'd0;
  91. else
  92. if((r_data_cnt == w_fifo_user_out[79:64]) && r_data_cnt)
  93. r_init_rkeep_addr <= r_bram_rkeep_addr + 1;
  94. else
  95. r_init_rkeep_addr <= r_init_rkeep_addr;
  96. end
  97. //寻找上升沿
  98. always@(posedge i_clk,posedge i_rst)begin
  99. if(i_rst)
  100. r_data_rden_pos <= 'd0;
  101. else
  102. if(r_bram_data_rden && !r_bram_data_rden_ff1)
  103. r_data_rden_pos <= 1'b1;
  104. else
  105. r_data_rden_pos <= 1'b0;
  106. end
  107. //寻找下降沿
  108. always@(posedge i_clk,posedge i_rst)begin
  109. if(i_rst)
  110. r_data_rden_nge <= 'd0;
  111. else
  112. if(!r_bram_data_rden && r_bram_data_rden_ff1)
  113. r_data_rden_nge <= 1'b1;
  114. else
  115. r_data_rden_nge <= 1'b0;
  116. end
  117. //读数据计数
  118. always@(posedge i_clk,posedge i_rst)begin
  119. if(i_rst)
  120. r_data_cnt <= 'd0;
  121. else
  122. if(r_fifo_user_info_rden || r_bram_data_rden)
  123. r_data_cnt <= r_data_cnt + 1;
  124. else
  125. r_data_cnt <= 'd0;
  126. end
  127. //数据转换成AXIS接口输出
  128. always@(posedge i_clk,posedge i_rst)begin
  129. if(i_rst)
  130. rm_axis_data <= 'd0;
  131. else
  132. rm_axis_data <= w_bram_data_out;
  133. end
  134. //Valid信号
  135. always@(posedge i_clk,posedge i_rst)begin
  136. if(i_rst)
  137. rm_axis_valid <= 1'b0;
  138. else
  139. if(rm_axis_last)
  140. rm_axis_valid <= 1'b0;
  141. else if(r_data_rden_pos)
  142. rm_axis_valid <= 1'b1;
  143. else
  144. rm_axis_valid <= rm_axis_valid;
  145. end
  146. //Last信号
  147. always@(posedge i_clk,posedge i_rst)begin
  148. if(i_rst)
  149. rm_axis_last <= 'd0;
  150. else
  151. if(!r_bram_data_rden && r_bram_data_rden_ff1)
  152. rm_axis_last <= 1'b1;
  153. else
  154. rm_axis_last <= 1'b0;
  155. end
  156. //KEEP信号
  157. always@(posedge i_clk,posedge i_rst)begin
  158. if(i_rst)
  159. rm_axis_keep <= 'd0;
  160. else
  161. if(w_fifo_user_out[79:64] == 1 && r_data_rden_pos)
  162. rm_axis_keep <= w_bram_rkeep;
  163. else if(w_fifo_user_out[79:64] > 1 && r_data_rden_pos)
  164. rm_axis_keep <= 8'hff;
  165. else if(!r_bram_data_rden && r_bram_data_rden_ff1)
  166. rm_axis_keep <= w_bram_rkeep;
  167. else
  168. rm_axis_keep <= rm_axis_keep;
  169. end

三、总结

CRC Process模块比较简单,就是实现丢掉CRC错误帧的功能

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

闽ICP备14008679号