e1_rx_deframer.v 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. * e1_rx_deframer.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * E1 Frame alignement recovery and checking as described G.706
  7. *
  8. *
  9. * Copyright (C) 2019 Sylvain Munaut <tnt@246tNt.com>
  10. * All rights reserved.
  11. *
  12. * LGPL v3+, see LICENSE.lgpl3
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU Lesser General Public
  16. * License as published by the Free Software Foundation; either
  17. * version 3 of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * Lesser General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU Lesser General Public License
  25. * along with this program; if not, write to the Free Software Foundation,
  26. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  27. */
  28. `default_nettype none
  29. module e1_rx_deframer #(
  30. parameter integer TS0_START = 0
  31. )(
  32. // Input
  33. input wire in_bit,
  34. input wire in_valid,
  35. // Output
  36. output reg [7:0] out_data,
  37. output reg [3:0] out_frame,
  38. output reg [4:0] out_ts,
  39. output reg out_ts_is0,
  40. output reg out_first,
  41. output reg out_last,
  42. output reg out_valid,
  43. output wire out_err_crc,
  44. output wire out_err_mfa,
  45. output wire out_err_fas,
  46. output wire out_err_nfas,
  47. output reg aligned,
  48. // Common
  49. input wire clk,
  50. input wire rst
  51. );
  52. // FSM defines
  53. // -----------
  54. localparam
  55. ST_FRAME_SEARCH = 0,
  56. ST_FRAME_VALIDATE = 1,
  57. ST_MULTIFRAME_SEARCH = 2,
  58. ST_MULTIFRAME_VALIDATE = 3,
  59. ST_ALIGNED = 4;
  60. reg [2:0] fsm_state;
  61. reg [2:0] fsm_state_nxt;
  62. // Signals
  63. // -------
  64. // Input
  65. reg strobe;
  66. reg [7:0] data;
  67. reg data_match_fas;
  68. // Position tracking
  69. reg [2:0] bit;
  70. reg bit_first;
  71. reg bit_last;
  72. reg [4:0] ts;
  73. reg ts_is_ts0;
  74. reg ts_is_ts31;
  75. reg [3:0] frame;
  76. reg frame_smf_first; // First of a sub-multiframe
  77. reg frame_smf_last; // Last of a sub-multiframe
  78. reg frame_mf_first; // First of the multiframe
  79. reg frame_mf_last; // Last of the multiframe
  80. // Alignement control signal
  81. wire align_frame;
  82. wire align_mframe;
  83. // Helpers
  84. reg fas_pos;
  85. reg [6:0] mfa_timeout;
  86. reg [15:0] ts0_msbs;
  87. wire [5:0] ts0_msbs_sync;
  88. wire [3:0] ts0_msbs_crc;
  89. reg ts0_msbs_match_mf;
  90. reg ts0_msbs_match_crc;
  91. wire crc_in_bit;
  92. wire crc_in_first;
  93. wire crc_in_valid;
  94. wire crc_capture;
  95. wire [3:0] crc_out;
  96. reg [3:0] crc_smf;
  97. reg ed_fas, ep_fas;
  98. reg ed_nfas, ep_nfas;
  99. reg ed_crc, ep_crc;
  100. reg ed_mfa, ep_mfa;
  101. reg [1:0] ec_fas;
  102. reg [1:0] ec_nfas;
  103. reg [1:0] ec_crc;
  104. reg [1:0] ec_mfa;
  105. reg error;
  106. // Input shift register
  107. // --------------------
  108. // Strobe signal
  109. always @(posedge clk)
  110. if (rst)
  111. strobe <= 1'b0;
  112. else
  113. strobe <= in_valid;
  114. // Actual data
  115. always @(posedge clk)
  116. if (in_valid)
  117. data <= { data[6:0], in_bit };
  118. // Pre-matching of FAS
  119. always @(posedge clk)
  120. if (in_valid)
  121. data_match_fas <= (data[5:0] == 6'b001101) & in_bit;
  122. // FSM logic
  123. // ---------
  124. // State register
  125. always @(posedge clk)
  126. if (rst | error)
  127. fsm_state <= ST_FRAME_SEARCH;
  128. else if (strobe)
  129. fsm_state <= fsm_state_nxt;
  130. // State transitions
  131. always @(*)
  132. begin
  133. // Default is to stay on the current state
  134. fsm_state_nxt <= fsm_state;
  135. // Act depending on current state
  136. case (fsm_state)
  137. ST_FRAME_SEARCH: begin
  138. // As soon as we have a FAS, we assume we're byte align
  139. // and check it's the right one
  140. if (data_match_fas)
  141. fsm_state_nxt <= ST_FRAME_VALIDATE;
  142. end
  143. ST_FRAME_VALIDATE: begin
  144. // We expect a non-FAS then a FAS, any error and we retry
  145. // frame search
  146. if (bit_last & ts_is_ts0)
  147. if (fas_pos)
  148. fsm_state_nxt <= data_match_fas ? ST_MULTIFRAME_SEARCH : ST_FRAME_SEARCH;
  149. else
  150. fsm_state_nxt <= data[6] ? ST_FRAME_VALIDATE : ST_FRAME_SEARCH;
  151. end
  152. ST_MULTIFRAME_SEARCH: begin
  153. // Either we find a possible alignement and we proceed to
  154. // validate it, or we timeout and fall back to frame search
  155. if (bit_last & ts_is_ts0)
  156. if (mfa_timeout[6])
  157. fsm_state_nxt <= ST_FRAME_SEARCH;
  158. else if (ts0_msbs_match_mf)
  159. fsm_state_nxt <= ST_MULTIFRAME_VALIDATE;
  160. end
  161. ST_MULTIFRAME_VALIDATE: begin
  162. // If we get a second alignement of the MSBs at the right
  163. // position before the timeout, we're good and aligned !
  164. if (bit_last & ts_is_ts0)
  165. if (mfa_timeout[6])
  166. fsm_state_nxt <= ST_FRAME_SEARCH;
  167. else if (frame_mf_first & ts0_msbs_match_mf)
  168. fsm_state_nxt <= ST_ALIGNED;
  169. end
  170. ST_ALIGNED: begin
  171. // Nothing to do. Only error case cas get us out and they're
  172. // handled separately
  173. end
  174. endcase
  175. end
  176. // Position tracking
  177. // -----------------
  178. // Bit position
  179. always @(posedge clk)
  180. if (align_frame) begin
  181. bit <= 3'b000;
  182. bit_first <= 1'b1;
  183. bit_last <= 1'b0;
  184. end else if (strobe) begin
  185. bit <= bit + 1;
  186. bit_first <= (bit == 3'b111);
  187. bit_last <= (bit == 3'b110);
  188. end
  189. // Time Slot
  190. always @(posedge clk)
  191. if (align_frame) begin
  192. ts <= 5'h01;
  193. ts_is_ts0 <= 1'b0;
  194. ts_is_ts31 <= 1'b0;
  195. end else if (strobe & bit_last) begin
  196. ts <= ts + 1;
  197. ts_is_ts0 <= ts_is_ts31;
  198. ts_is_ts31 <= (ts == 5'h1e);
  199. end
  200. // Frame
  201. always @(posedge clk)
  202. if (align_mframe) begin
  203. frame <= 4'h0;
  204. frame_smf_first <= 1'b1;
  205. frame_smf_last <= 1'b0;
  206. frame_mf_first <= 1'b1;
  207. frame_mf_last <= 1'b0;
  208. end else if (strobe & bit_last & ts_is_ts31) begin
  209. frame <= frame + 1;
  210. frame_smf_first <= frame_smf_last;
  211. frame_smf_last <= (frame[2:0] == 3'h6);
  212. frame_mf_first <= frame_mf_last;
  213. frame_mf_last <= (frame == 4'he);
  214. end
  215. // Control for alignement
  216. assign align_frame = (fsm_state == ST_FRAME_SEARCH);
  217. assign align_mframe = (fsm_state == ST_MULTIFRAME_SEARCH);
  218. // Helpers
  219. // -------
  220. // Frame Alignement Signal position tracking
  221. // During ST_FRAME_SEARCH, the frame counter is still locked until we
  222. // have multi-frame alignement. So just track the LSB of the frame
  223. // number independently so we can check the next FAS
  224. always @(posedge clk)
  225. if (align_frame)
  226. fas_pos <= 1'b0;
  227. else
  228. fas_pos <= fas_pos ^ (strobe & bit_last & ts_is_ts0);
  229. // Multi Frame Alignement timout
  230. // We have 8 ms = 64 frames to acquire multi frame alignement
  231. always @(posedge clk)
  232. if (align_frame)
  233. mfa_timeout <= 7'h3f;
  234. else if (strobe & bit_last & ts_is_ts0)
  235. mfa_timeout <= mfa_timeout - 1;
  236. // Track the history of all 16 TS0 MSBs
  237. // and also update some pre-matching flags
  238. always @(posedge clk)
  239. if (fsm_state == ST_FRAME_SEARCH) begin
  240. // If we're not aligned =>avoid spurious matches
  241. ts0_msbs <= 16'hffff;
  242. ts0_msbs_match_mf <= 1'b0;
  243. ts0_msbs_match_crc <= 1'b0;
  244. end else if (strobe & ts_is_ts0 & bit_first) begin
  245. // We register it ASAP so that when we have the full byte (i.e.
  246. // when the FSM updates), the history is up to date
  247. ts0_msbs <= { ts0_msbs[14:0], data[0] };
  248. ts0_msbs_match_mf <= (ts0_msbs_sync == 6'b001011);
  249. ts0_msbs_match_crc <= (crc_smf == ts0_msbs_crc);
  250. end
  251. assign ts0_msbs_sync = { ts0_msbs[14], ts0_msbs[12], ts0_msbs[10], ts0_msbs[8], ts0_msbs[6], ts0_msbs[4] };
  252. assign ts0_msbs_crc = { ts0_msbs[6], ts0_msbs[4], ts0_msbs[2], ts0_msbs[0] };
  253. // CRC4 computation
  254. assign crc_in_bit = (bit_first & ts_is_ts0 & fas_pos) ? 1'b0 : data[0];
  255. assign crc_in_first = bit_first & ts_is_ts0 & frame_smf_first;
  256. assign crc_in_valid = strobe;
  257. assign crc_capture = crc_in_first;
  258. e1_crc4 crc_I (
  259. .in_bit(crc_in_bit),
  260. .in_first(crc_in_first),
  261. .in_valid(crc_in_valid),
  262. .out_crc4(crc_out),
  263. .clk(clk),
  264. .rst(rst)
  265. );
  266. always @(posedge clk)
  267. if (crc_capture)
  268. crc_smf <= crc_out;
  269. // Track errors of FAS, non-FAS, CRC
  270. // We register these detection bits and so the counter will be 'late'
  271. // but they're used as LOS detection which is pretty much async to the
  272. // rest and used to go back to ST_SEARCH_BIT anyway ...
  273. always @(posedge clk)
  274. // Only track when we're frame aligned
  275. if ((fsm_state != ST_MULTIFRAME_SEARCH) && (fsm_state != ST_ALIGNED)) begin
  276. ep_fas <= 1'b0;
  277. ed_fas <= 1'b0;
  278. ep_nfas <= 1'b0;
  279. ed_nfas <= 1'b0;
  280. end else begin
  281. ep_fas <= strobe & bit_last & ts_is_ts0 & fas_pos;
  282. ed_fas <= strobe & bit_last & ts_is_ts0 & fas_pos & ~data_match_fas;
  283. ep_nfas <= strobe & bit_last & ts_is_ts0 & ~fas_pos;
  284. ed_nfas <= strobe & bit_last & ts_is_ts0 & ~fas_pos & ~data[6];
  285. end
  286. always @(posedge clk)
  287. // CRC and MultiFrameAlign errors tracked only when properly
  288. // aligned to the multiframe
  289. if (fsm_state != ST_ALIGNED) begin
  290. ep_crc <= 1'b0;
  291. ed_crc <= 1'b0;
  292. ep_mfa <= 1'b0;
  293. ed_mfa <= 1'b0;
  294. end else begin
  295. ep_crc <= strobe & bit_last & ts_is_ts0 & frame_smf_last;
  296. ed_crc <= strobe & bit_last & ts_is_ts0 & frame_smf_last & ~ts0_msbs_match_crc;
  297. ep_mfa <= strobe & bit_last & ts_is_ts0 & frame_mf_first;
  298. ed_mfa <= strobe & bit_last & ts_is_ts0 & frame_mf_first & ~ts0_msbs_match_mf;
  299. end
  300. always @(posedge clk)
  301. if (fsm_state == ST_FRAME_SEARCH) begin
  302. ec_fas <= 0;
  303. ec_nfas <= 0;
  304. ec_crc <= 0;
  305. ec_mfa <= 0;
  306. end else begin
  307. ec_fas <= (ep_fas & ~ed_fas) ? 0 : (ec_fas + ed_fas);
  308. ec_nfas <= (ep_nfas & ~ed_nfas) ? 0 : (ec_nfas + ed_nfas);
  309. ec_crc <= (ep_crc & ~ed_crc) ? 0 : (ec_crc + ed_crc);
  310. ec_mfa <= (ep_mfa & ~ed_mfa) ? 0 : (ec_mfa + ed_mfa);
  311. end
  312. always @(posedge clk)
  313. error <= (ec_fas == 2'b11) | (ec_nfas == 2'b11) | (ec_crc == 2'b11) | (ec_mfa == 2'b11);
  314. // Output
  315. // ------
  316. // Data output
  317. always @(posedge clk)
  318. if (rst) begin
  319. out_valid <= 1'b0;
  320. out_data <= 8'h00;
  321. out_frame <= 4'h0;
  322. out_ts <= 5'h00;
  323. out_ts_is0 <= 1'b1;
  324. out_first <= 1'b1;
  325. out_last <= 1'b0;
  326. end else begin
  327. if (TS0_START)
  328. out_valid <= strobe && bit_last && (
  329. (fsm_state == ST_ALIGNED) || (
  330. (fsm_state == ST_MULTIFRAME_VALIDATE) &&
  331. (ts_is_ts0 && ~mfa_timeout[6] && frame_mf_first && ts0_msbs_match_mf)
  332. )
  333. );
  334. else
  335. out_valid <= strobe & bit_last & (fsm_state == ST_ALIGNED);
  336. out_data <= data;
  337. out_frame <= frame;
  338. out_ts <= ts;
  339. out_ts_is0 <= ts_is_ts0;
  340. out_first <= ts_is_ts0 & frame_mf_first;
  341. out_last <= ts_is_ts31 & frame_mf_last;
  342. end
  343. // Error indicators
  344. assign out_err_crc = ed_crc;
  345. assign out_err_mfa = ed_mfa;
  346. assign out_err_fas = ed_fas;
  347. assign out_err_nfas = ed_nfas;
  348. // Status
  349. always @(posedge clk)
  350. if (rst)
  351. aligned <= 1'b0;
  352. else
  353. aligned <= fsm_state == ST_ALIGNED;
  354. endmodule // e1_rx_deframer