hdmi_phy_4x.v 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. wire dummy;
  61. // Clock
  62. // -----
  63. SB_IO #(
  64. .PIN_TYPE(6'b0100_11)
  65. ) io_clk_I (
  66. .PACKAGE_PIN(hdmi_clk),
  67. .D_OUT_0(1'b0),
  68. .D_OUT_1(1'b1),
  69. .OUTPUT_CLK(clk_4x)
  70. );
  71. // Control signals
  72. // ---------------
  73. wire [11:0] ctrl_d;
  74. wire [ 2:0] ctrl_iob_o;
  75. wire [ 2:0] ctrl_pad;
  76. assign ctrl_d = {
  77. { 4{in_hsync} },
  78. { 4{in_vsync} },
  79. { 4{in_de} }
  80. };
  81. generate
  82. for (i=0; i<3; i=i+1)
  83. ice40_oserdes #(
  84. .MODE("DATA"),
  85. .SERDES_GRP(1024 + (i<<4))
  86. ) oserdes_ctrl_I (
  87. .d(ctrl_d[4*i+:4]),
  88. .q({dummy, ctrl_iob_o[i]}),
  89. .sync(clk_sync),
  90. .clk_1x(clk_1x),
  91. .clk_4x(clk_4x)
  92. );
  93. endgenerate
  94. SB_IO #(
  95. .PIN_TYPE(6'b 0101_11)
  96. ) io_ctrl_I[2:0] (
  97. .PACKAGE_PIN(ctrl_pad),
  98. .D_OUT_0(ctrl_iob_o),
  99. .OUTPUT_CLK(clk_4x)
  100. );
  101. assign hdmi_hsync = ctrl_pad[2];
  102. assign hdmi_vsync = ctrl_pad[1];
  103. assign hdmi_de = ctrl_pad[0];
  104. // Data signals
  105. // ------------
  106. wire [4*DW-1:0] data_d;
  107. wire [ DW-1:0] data_iob_o;
  108. wire [ DW-1:0] data_pad;
  109. generate
  110. for (i=0; i<DW; i=i+1)
  111. begin
  112. assign data_d[4*i+:4] = {
  113. in_data0[i],
  114. in_data1[i],
  115. in_data2[i],
  116. in_data3[i]
  117. };
  118. ice40_oserdes #(
  119. .MODE("DATA"),
  120. .SERDES_GRP(1024 + 64 + (i<<4))
  121. ) oserdes_data_I (
  122. .d(data_d[4*i+:4]),
  123. .q({dummy, data_iob_o[i]}),
  124. .sync(clk_sync),
  125. .clk_1x(clk_1x),
  126. .clk_4x(clk_4x)
  127. );
  128. end
  129. endgenerate
  130. SB_IO #(
  131. .PIN_TYPE(6'b 0101_11)
  132. ) io_data_I[DW-1:0] (
  133. .PACKAGE_PIN(data_pad),
  134. .D_OUT_0(data_iob_o),
  135. .OUTPUT_CLK(clk_4x)
  136. );
  137. assign hdmi_data = data_pad;
  138. endmodule