ice40_serdes_sync.v 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * ice40_serdes_sync.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
  7. * All rights reserved.
  8. *
  9. * BSD 3-clause, see LICENSE.bsd
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * * Neither the name of the <organization> nor the
  19. * names of its contributors may be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  26. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. `default_nettype none
  34. module ice40_serdes_sync #(
  35. parameter integer PHASE = 0,
  36. parameter integer NEG_EDGE = 0,
  37. parameter integer GLOBAL_BUF = 0,
  38. parameter integer LOCAL_BUF = 0,
  39. parameter BEL_COL = "X12",
  40. parameter BEL_ROW = "Y15", // Ignored if using LOCAL_BUF, Y15 used in that case
  41. parameter BEL_GB = ""
  42. )(
  43. input wire clk_slow,
  44. input wire clk_fast,
  45. input wire rst,
  46. output wire sync
  47. );
  48. localparam BEL_BASE = LOCAL_BUF ? { BEL_COL, "/Y15" } : { BEL_COL, "/", BEL_ROW };
  49. localparam PHASE_CMP = LOCAL_BUF ? ((PHASE + 3) % 4) : PHASE;
  50. wire [1:0] clk_samp;
  51. wire [1:0] edge_det;
  52. wire [1:0] edge_found;
  53. wire [1:0] cnt_next;
  54. wire [1:0] cnt_val;
  55. wire [1:0] sync_next;
  56. wire [1:0] sync_i;
  57. // Double sample of the slow clock
  58. ice40_serdes_dff #(
  59. .NEG(NEG_EDGE),
  60. .RST(1),
  61. .BEL({BEL_BASE, "/lc7"})
  62. ) ff_samp0_I (
  63. .d(clk_slow),
  64. .q(clk_samp[0]),
  65. .c(clk_fast),
  66. .r(rst)
  67. );
  68. ice40_serdes_dff #(
  69. .NEG(NEG_EDGE),
  70. .RST(1),
  71. .BEL({BEL_BASE, "/lc6"})
  72. ) ff_samp1_I (
  73. .d(clk_samp[0]),
  74. .q(clk_samp[1]),
  75. .c(clk_fast),
  76. .r(rst)
  77. );
  78. // Detect falling edge, then rising edge
  79. assign edge_det[0] = edge_found[0] | (clk_samp[1] & ~clk_samp[0]);
  80. assign edge_det[1] = edge_found[1] | (clk_samp[0] & ~clk_samp[1] & edge_found[0]);
  81. ice40_serdes_dff #(
  82. .NEG(NEG_EDGE),
  83. .RST(1),
  84. .BEL({BEL_BASE, "/lc5"})
  85. ) ff_edge0_I (
  86. .d(edge_det[0]),
  87. .q(edge_found[0]),
  88. .c(clk_fast),
  89. .r(rst)
  90. );
  91. ice40_serdes_dff #(
  92. .NEG(NEG_EDGE),
  93. .RST(1),
  94. .BEL({BEL_BASE, "/lc4"})
  95. ) ff_edge1_I (
  96. .d(edge_det[1]),
  97. .q(edge_found[1]),
  98. .c(clk_fast),
  99. .r(rst)
  100. );
  101. // 2 bit upcounter
  102. assign cnt_next[0] = cnt_val[0] ^ edge_found[1];
  103. assign cnt_next[1] = cnt_val[1] ^ (cnt_val[0] & edge_found[1]);
  104. ice40_serdes_dff #(
  105. .NEG(NEG_EDGE),
  106. .RST(1),
  107. .BEL({BEL_BASE, "/lc2"})
  108. ) ff_cnt1_I (
  109. .d(cnt_next[1]),
  110. .q(cnt_val[1]),
  111. .c(clk_fast),
  112. .r(rst)
  113. );
  114. ice40_serdes_dff #(
  115. .NEG(NEG_EDGE),
  116. .RST(1),
  117. .BEL({BEL_BASE, "/lc1"})
  118. ) ff_cnt0_I (
  119. .d(cnt_next[0]),
  120. .q(cnt_val[0]),
  121. .c(clk_fast),
  122. .r(rst)
  123. );
  124. // Final comparator
  125. SB_LUT4 #(
  126. .LUT_INIT(1 << ((4*PHASE_CMP)+2))
  127. ) lut_sync_I[1:0] (
  128. .I0(1'b0),
  129. .I1(edge_found[1]),
  130. .I2(cnt_val[0]),
  131. .I3(cnt_val[1]),
  132. .O(sync_next)
  133. );
  134. ice40_serdes_dff #(
  135. .NEG(NEG_EDGE),
  136. .RST(1),
  137. .BEL({BEL_BASE, "/lc3"})
  138. ) ff_sync1_I (
  139. .d(sync_next[1]),
  140. .q(sync_i[1]),
  141. .c(clk_fast),
  142. .r(rst)
  143. );
  144. ice40_serdes_dff #(
  145. .NEG(NEG_EDGE),
  146. .RST(1),
  147. .BEL({BEL_BASE, "/lc0"})
  148. ) ff_sync0_I (
  149. .d(sync_next[0]),
  150. .q(sync_i[0]),
  151. .c(clk_fast),
  152. .r(rst)
  153. );
  154. // Buffer ?
  155. generate
  156. if (GLOBAL_BUF)
  157. (* BEL=BEL_GB *)
  158. SB_GB gbuf_sync_I (
  159. .USER_SIGNAL_TO_GLOBAL_BUFFER(sync_i[0]),
  160. .GLOBAL_BUFFER_OUTPUT(sync)
  161. );
  162. else
  163. assign sync = sync_i[0];
  164. if (LOCAL_BUF) begin
  165. ice40_serdes_dff #(
  166. .NEG(NEG_EDGE),
  167. .BEL({BEL_COL, "/Y4/lc1"}),
  168. .SERDES_ATTR("sync_lbuf_bot")
  169. ) sync_bot (
  170. .d(sync_i[0]),
  171. .q(), // Output will be wired by the script
  172. .c(clk_fast)
  173. );
  174. ice40_serdes_dff #(
  175. .NEG(NEG_EDGE),
  176. .BEL({BEL_COL, "/Y26/lc1"}),
  177. .SERDES_ATTR("sync_lbuf_top")
  178. ) sync_top (
  179. .d(sync_i[1]),
  180. .q(),
  181. .c(clk_fast)
  182. );
  183. end
  184. endgenerate
  185. endmodule