e1_wb.v 9.3 KB

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