e1_wb.v 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * e1_wb.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * E1 wishbone top-level
  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_wb #(
  30. parameter integer MFW = 7
  31. )(
  32. // IO pads
  33. input wire pad_rx_hi_p,
  34. input wire pad_rx_hi_n,
  35. input wire pad_rx_lo_p,
  36. input wire pad_rx_lo_n,
  37. output wire pad_tx_hi,
  38. output wire pad_tx_lo,
  39. // Buffer interface
  40. // E1 RX (write)
  41. output wire [7:0] buf_rx_data,
  42. output wire [4:0] buf_rx_ts,
  43. output wire [3:0] buf_rx_frame,
  44. output wire [MFW-1:0] buf_rx_mf,
  45. output wire buf_rx_we,
  46. input wire buf_rx_rdy,
  47. // E1 TX (read)
  48. input wire [7:0] buf_tx_data,
  49. output wire [4:0] buf_tx_ts,
  50. output wire [3:0] buf_tx_frame,
  51. output wire [MFW-1:0] buf_tx_mf,
  52. output wire buf_tx_re,
  53. input wire buf_tx_rdy,
  54. // Wishbone slave
  55. input wire [ 3:0] bus_addr,
  56. input wire [15:0] bus_wdata,
  57. output reg [15:0] bus_rdata,
  58. input wire bus_cyc,
  59. input wire bus_we,
  60. output wire bus_ack,
  61. // External strobes
  62. output reg irq,
  63. output wire tick_tx,
  64. output wire tick_rx,
  65. // Common
  66. input wire clk,
  67. input wire rst
  68. );
  69. // Signals
  70. // -------
  71. // CSRs and bus access
  72. wire bus_clr;
  73. reg bus_ack_i;
  74. reg crx_wren;
  75. reg crx_clear;
  76. reg ctx_wren;
  77. reg ctx_clear;
  78. wire [15:0] bus_rd_rx_status;
  79. wire [15:0] bus_rd_rx_bdout;
  80. wire [15:0] bus_rd_tx_status;
  81. wire [15:0] bus_rd_tx_bdout;
  82. // FIFOs
  83. // BD RX In
  84. wire [MFW-1:0] bri_di;
  85. wire [MFW-1:0] bri_do;
  86. reg bri_wren;
  87. wire bri_rden;
  88. wire bri_full;
  89. wire bri_empty;
  90. // BD RX Out
  91. wire [MFW+1:0] bro_di;
  92. wire [MFW+1:0] bro_do;
  93. wire bro_wren;
  94. reg bro_rden;
  95. wire bro_full;
  96. wire bro_empty;
  97. // BD TX In
  98. wire [MFW+1:0] bti_di;
  99. wire [MFW+1:0] bti_do;
  100. reg bti_wren;
  101. wire bti_rden;
  102. wire bti_full;
  103. wire bti_empty;
  104. // BD TX Out
  105. wire [MFW-1:0] bto_di;
  106. wire [MFW-1:0] bto_do;
  107. wire bto_wren;
  108. reg bto_rden;
  109. wire bto_full;
  110. wire bto_empty;
  111. // RX
  112. // Control
  113. reg rx_rst;
  114. reg rx_enabled;
  115. reg [1:0] rx_mode;
  116. wire rx_aligned;
  117. reg rx_overflow;
  118. // BD interface
  119. wire [MFW-1:0] bdrx_mf;
  120. wire [1:0] bdrx_crc_e;
  121. wire bdrx_valid;
  122. wire bdrx_done;
  123. wire bdrx_miss;
  124. // Loopback path
  125. wire lb_bit;
  126. wire lb_valid;
  127. // Timing
  128. wire ext_tick;
  129. wire int_tick;
  130. // TX
  131. // Control
  132. reg tx_rst;
  133. reg tx_enabled;
  134. reg [1:0] tx_mode;
  135. reg tx_time_src;
  136. reg tx_alarm;
  137. reg tx_loopback;
  138. reg tx_underflow;
  139. reg [1:0] tx_crc_e_auto;
  140. // BD interface
  141. wire [MFW-1:0] bdtx_mf;
  142. wire [1:0] bdtx_crc_e;
  143. wire bdtx_valid;
  144. wire bdtx_done;
  145. wire bdtx_miss;
  146. // CSRs & FIFO bus access
  147. // ----------------------
  148. // Ack is always 1 cycle after access
  149. always @(posedge clk)
  150. bus_ack_i <= bus_cyc & ~bus_ack_i;
  151. assign bus_ack = bus_ack_i;
  152. assign bus_clr = ~bus_cyc | bus_ack_i;
  153. // Control WrEn
  154. always @(posedge clk)
  155. if (bus_clr | ~bus_we) begin
  156. crx_wren <= 1'b0;
  157. crx_clear <= 1'b0;
  158. ctx_wren <= 1'b0;
  159. ctx_clear <= 1'b0;
  160. end else begin
  161. crx_wren <= (bus_addr == 4'h0);
  162. crx_clear <= (bus_addr == 4'h0) & bus_wdata[12];
  163. ctx_wren <= (bus_addr == 4'h4);
  164. ctx_clear <= (bus_addr == 4'h4) & bus_wdata[12];
  165. end
  166. // Control regs
  167. always @(posedge clk or posedge rst)
  168. if (rst) begin
  169. rx_mode <= 2'b00;
  170. rx_enabled <= 1'b0;
  171. tx_loopback <= 1'b0;
  172. tx_alarm <= 1'b0;
  173. tx_time_src <= 1'b0;
  174. tx_mode <= 2'b00;
  175. tx_enabled <= 1'b0;
  176. end else begin
  177. if (crx_wren) begin
  178. rx_mode <= bus_wdata[2:1];
  179. rx_enabled <= bus_wdata[0];
  180. end
  181. if (ctx_wren) begin
  182. tx_loopback <= bus_wdata[5];
  183. tx_alarm <= bus_wdata[4];
  184. tx_time_src <= bus_wdata[3];
  185. tx_mode <= bus_wdata[2:1];
  186. tx_enabled <= bus_wdata[0];
  187. end
  188. end
  189. // Status data
  190. assign bus_rd_rx_status = {
  191. 3'b000,
  192. rx_overflow,
  193. bro_full,
  194. bro_empty,
  195. bri_full,
  196. bri_empty,
  197. 6'b000000,
  198. rx_aligned,
  199. rx_enabled
  200. };
  201. assign bus_rd_tx_status = {
  202. 3'b000,
  203. tx_underflow,
  204. bto_full,
  205. bto_empty,
  206. bti_full,
  207. bti_empty,
  208. 7'b0000000,
  209. tx_enabled
  210. };
  211. // BD FIFO WrEn / RdEn
  212. // (note we must mask on full/empty here to be consistent with what we
  213. // return in the data !)
  214. always @(posedge clk)
  215. if (bus_clr) begin
  216. bri_wren <= 1'b0;
  217. bti_wren <= 1'b0;
  218. bro_rden <= 1'b0;
  219. bto_rden <= 1'b0;
  220. end else begin
  221. bri_wren <= bus_we & ~bri_full & (bus_addr == 4'h2);
  222. bti_wren <= bus_we & ~bti_full & (bus_addr == 4'h6);
  223. bro_rden <= ~bus_we & ~bro_empty & (bus_addr == 4'h2);
  224. bto_rden <= ~bus_we & ~bto_empty & (bus_addr == 4'h6);
  225. end
  226. // BD FIFO Data
  227. assign bri_di = bus_wdata[MFW-1:0];
  228. assign bti_di = { bus_wdata[14:13], bus_wdata[MFW-1:0] };
  229. assign bus_rd_rx_bdout = { ~bro_empty, bro_do[MFW+1:MFW], {(13-MFW){1'b0}}, bro_do[MFW-1:0] };
  230. assign bus_rd_tx_bdout = { ~bto_empty, {(15-MFW){1'b0}}, bto_do[MFW-1:0] };
  231. // Read MUX
  232. always @(posedge clk)
  233. if (bus_clr)
  234. bus_rdata <= 16'h0000;
  235. else
  236. case (bus_addr[3:0])
  237. 4'h0: bus_rdata <= bus_rd_rx_status; // RX Status
  238. 4'h2: bus_rdata <= bus_rd_rx_bdout; // RX BD Out
  239. 4'h4: bus_rdata <= bus_rd_tx_status; // TX Status
  240. 4'h6: bus_rdata <= bus_rd_tx_bdout; // TX BD Out
  241. default: bus_rdata <= 16'h0000;
  242. endcase
  243. // BD fifos
  244. // --------
  245. // BD RX In
  246. fifo_sync_shift #(
  247. .DEPTH(4),
  248. .WIDTH(MFW)
  249. ) bd_rx_in_I (
  250. .wr_data(bri_di),
  251. .wr_ena(bri_wren),
  252. .wr_full(bri_full),
  253. .rd_data(bri_do),
  254. .rd_ena(bri_rden),
  255. .rd_empty(bri_empty),
  256. .clk(clk),
  257. .rst(rst)
  258. );
  259. // BD RX Out
  260. fifo_sync_shift #(
  261. .DEPTH(4),
  262. .WIDTH(MFW+2)
  263. ) bd_rx_out_I (
  264. .wr_data(bro_di),
  265. .wr_ena(bro_wren),
  266. .wr_full(bro_full),
  267. .rd_data(bro_do),
  268. .rd_ena(bro_rden),
  269. .rd_empty(bro_empty),
  270. .clk(clk),
  271. .rst(rst)
  272. );
  273. // BD TX In
  274. fifo_sync_shift #(
  275. .DEPTH(4),
  276. .WIDTH(MFW+2)
  277. ) bd_tx_in_I (
  278. .wr_data(bti_di),
  279. .wr_ena(bti_wren),
  280. .wr_full(bti_full),
  281. .rd_data(bti_do),
  282. .rd_ena(bti_rden),
  283. .rd_empty(bti_empty),
  284. .clk(clk),
  285. .rst(rst)
  286. );
  287. // BD TX Out
  288. fifo_sync_shift #(
  289. .DEPTH(4),
  290. .WIDTH(MFW)
  291. ) bd_tx_out_I (
  292. .wr_data(bto_di),
  293. .wr_ena(bto_wren),
  294. .wr_full(bto_full),
  295. .rd_data(bto_do),
  296. .rd_ena(bto_rden),
  297. .rd_empty(bto_empty),
  298. .clk(clk),
  299. .rst(rst)
  300. );
  301. // RX submodule
  302. // ------------
  303. // RX core
  304. e1_rx #(
  305. .MFW(MFW)
  306. ) rx_I (
  307. .pad_rx_hi_p(pad_rx_hi_p),
  308. .pad_rx_hi_n(pad_rx_hi_n),
  309. .pad_rx_lo_p(pad_rx_lo_p),
  310. .pad_rx_lo_n(pad_rx_lo_n),
  311. .buf_data(buf_rx_data),
  312. .buf_ts(buf_rx_ts),
  313. .buf_frame(buf_rx_frame),
  314. .buf_mf(buf_rx_mf),
  315. .buf_we(buf_rx_we),
  316. .buf_rdy(buf_rx_rdy),
  317. .bd_mf(bdrx_mf),
  318. .bd_crc_e(bdrx_crc_e),
  319. .bd_valid(bdrx_valid),
  320. .bd_done(bdrx_done),
  321. .bd_miss(bdrx_miss),
  322. .lb_bit(lb_bit),
  323. .lb_valid(lb_valid),
  324. .status_aligned(rx_aligned),
  325. .clk(clk),
  326. .rst(rx_rst)
  327. );
  328. // BD FIFO interface
  329. assign bdrx_mf = bri_do;
  330. assign bdrx_valid = ~bri_empty;
  331. assign bri_rden = bdrx_done;
  332. assign bro_di = { bdrx_crc_e, bdrx_mf };
  333. assign bro_wren = ~bro_full & bdrx_done;
  334. // Control logic
  335. // Local reset
  336. always @(posedge clk or posedge rst)
  337. if (rst)
  338. rx_rst <= 1'b1;
  339. else
  340. rx_rst <= ~rx_enabled;
  341. // Overflow
  342. always @(posedge clk or posedge rst)
  343. if (rst)
  344. rx_overflow <= 1'b0;
  345. else
  346. rx_overflow <= (rx_overflow & ~crx_clear) | bdrx_miss;
  347. // TX submodule
  348. // ------------
  349. // TX core
  350. e1_tx #(
  351. .MFW(MFW)
  352. ) tx_I (
  353. .pad_tx_hi(pad_tx_hi),
  354. .pad_tx_lo(pad_tx_lo),
  355. .buf_data(buf_tx_data),
  356. .buf_ts(buf_tx_ts),
  357. .buf_frame(buf_tx_frame),
  358. .buf_mf(buf_tx_mf),
  359. .buf_re(buf_tx_re),
  360. .buf_rdy(buf_tx_rdy),
  361. .bd_mf(bdtx_mf),
  362. .bd_crc_e(bdtx_crc_e),
  363. .bd_valid(bdtx_valid),
  364. .bd_done(bdtx_done),
  365. .bd_miss(bdtx_miss),
  366. .lb_bit(lb_bit),
  367. .lb_valid(lb_valid),
  368. .ext_tick(ext_tick),
  369. .int_tick(int_tick),
  370. .ctrl_time_src(tx_time_src),
  371. .ctrl_do_framing(tx_mode != 2'b00),
  372. .ctrl_do_crc4(tx_mode[1]),
  373. .ctrl_loopback(tx_loopback),
  374. .alarm(tx_alarm),
  375. .clk(clk),
  376. .rst(tx_rst)
  377. );
  378. assign ext_tick = lb_valid;
  379. // Auto E-bit tracking
  380. always @(posedge clk)
  381. tx_crc_e_auto <= (bdtx_done ? 2'b00 : tx_crc_e_auto) | (bdrx_done ? bdrx_crc_e : 2'b00);
  382. // BD FIFO interface
  383. assign bdtx_mf = bti_do[MFW-1:0];
  384. assign bdtx_crc_e = (tx_mode == 2'b11) ? tx_crc_e_auto : bti_do[MFW+1:MFW];
  385. assign bdtx_valid = ~bti_empty;
  386. assign bti_rden = bdtx_done;
  387. assign bto_di = bdtx_mf;
  388. assign bto_wren = ~bto_full & bdtx_done;
  389. // Control logic
  390. // Local reset
  391. always @(posedge clk or posedge rst)
  392. if (rst)
  393. tx_rst <= 1'b1;
  394. else
  395. tx_rst <= ~tx_enabled;
  396. // Underflow
  397. always @(posedge clk or posedge rst)
  398. if (rst)
  399. tx_underflow <= 1'b0;
  400. else
  401. tx_underflow <= (tx_underflow & ~ctx_clear) | bdtx_miss;
  402. // External strobes
  403. // ----------------
  404. always @(posedge clk or posedge rst)
  405. if (rst)
  406. irq <= 1'b0;
  407. else
  408. irq <= ~bro_empty | rx_overflow | ~bto_empty | tx_underflow;
  409. assign tick_tx = int_tick; /* tick used for TX */
  410. assign tick_rx = ext_tick; /* tick recovered from RX */
  411. endmodule // e1_wb