hdmi_phy_4x.v 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * hdmi_phy_4x.v
  3. *
  4. * vim: ts=4 sw=4
  5. *
  6. * HDMI PHY using 4x serdes to push 4 pixels at once allowing FPGA code
  7. * to run at a quarter of the pixel clock.
  8. *
  9. * Copyright (C) 2020 Sylvain Munaut <tnt@246tNt.com>
  10. * All rights reserved.
  11. *
  12. * BSD 3-clause, see LICENSE.bsd
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. * * Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. * * Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in the
  20. * documentation and/or other materials provided with the distribution.
  21. * * Neither the name of the <organization> nor the
  22. * names of its contributors may be used to endorse or promote products
  23. * derived from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  27. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28. * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  29. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  30. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  32. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  34. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. */
  36. `default_nettype none
  37. module hdmi_phy_4x #(
  38. parameter integer DW = 4
  39. )(
  40. // HDMI pads
  41. output wire [DW-1:0] hdmi_data,
  42. output wire hdmi_hsync,
  43. output wire hdmi_vsync,
  44. output wire hdmi_de,
  45. output wire hdmi_clk,
  46. // Input from fabric
  47. input wire [DW-1:0] in_data0,
  48. input wire [DW-1:0] in_data1,
  49. input wire [DW-1:0] in_data2,
  50. input wire [DW-1:0] in_data3,
  51. input wire in_hsync,
  52. input wire in_vsync,
  53. input wire in_de,
  54. // Clocks
  55. input wire clk_1x,
  56. input wire clk_4x,
  57. input wire clk_sync
  58. );
  59. genvar i;
  60. // Clock
  61. // -----
  62. SB_IO #(
  63. .PIN_TYPE(6'b0100_11)
  64. ) io_clk_I (
  65. .PACKAGE_PIN(hdmi_clk),
  66. .D_OUT_0(1'b0),
  67. .D_OUT_1(1'b1),
  68. .OUTPUT_CLK(clk_4x)
  69. );
  70. // Control signals
  71. // ---------------
  72. wire [11:0] ctrl_d;
  73. wire [ 2:0] ctrl_iob_o;
  74. wire [ 2:0] ctrl_pad;
  75. assign ctrl_d = {
  76. { 4{in_hsync} },
  77. { 4{in_vsync} },
  78. { 4{in_de} }
  79. };
  80. generate
  81. for (i=0; i<3; i=i+1)
  82. begin
  83. wire dummy;
  84. ice40_oserdes #(
  85. .MODE("DATA"),
  86. .SERDES_GRP(1024 + (i<<4))
  87. ) oserdes_ctrl_I (
  88. .d(ctrl_d[4*i+:4]),
  89. .q({dummy, ctrl_iob_o[i]}),
  90. .sync(clk_sync),
  91. .clk_1x(clk_1x),
  92. .clk_4x(clk_4x)
  93. );
  94. end
  95. endgenerate
  96. SB_IO #(
  97. .PIN_TYPE(6'b0101_11)
  98. ) io_ctrl_I[2:0] (
  99. .PACKAGE_PIN(ctrl_pad),
  100. .D_OUT_0(ctrl_iob_o),
  101. .OUTPUT_CLK(clk_4x)
  102. );
  103. assign hdmi_hsync = ctrl_pad[2];
  104. assign hdmi_vsync = ctrl_pad[1];
  105. assign hdmi_de = ctrl_pad[0];
  106. // Data signals
  107. // ------------
  108. wire [4*DW-1:0] data_d;
  109. wire [ DW-1:0] data_iob_o;
  110. wire [ DW-1:0] data_pad;
  111. generate
  112. for (i=0; i<DW; i=i+1)
  113. begin
  114. wire dummy;
  115. assign data_d[4*i+:4] = {
  116. in_data0[i],
  117. in_data1[i],
  118. in_data2[i],
  119. in_data3[i]
  120. };
  121. ice40_oserdes #(
  122. .MODE("DATA"),
  123. .SERDES_GRP(1024 + 64 + (i<<4))
  124. ) oserdes_data_I (
  125. .d(data_d[4*i+:4]),
  126. .q({dummy, data_iob_o[i]}),
  127. .sync(clk_sync),
  128. .clk_1x(clk_1x),
  129. .clk_4x(clk_4x)
  130. );
  131. end
  132. endgenerate
  133. SB_IO #(
  134. .PIN_TYPE(6'b 0101_11)
  135. ) io_data_I[DW-1:0] (
  136. .PACKAGE_PIN(data_pad),
  137. .D_OUT_0(data_iob_o),
  138. .OUTPUT_CLK(clk_4x)
  139. );
  140. assign hdmi_data = data_pad;
  141. endmodule