video.sv 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. module video (
  2. input rst_n,
  3. input vid_clk,
  4. input [1:0] pll_locked,
  5. output [2:0] hdmi_d,
  6. output hdmi_clk,
  7. inout hdmi_scl,
  8. inout hdmi_sda,
  9. inout hdmi_hpd
  10. );
  11. assign hdmi_scl = 1'bz;
  12. assign hdmi_sda = 1'bz;
  13. assign hdmi_hpd = 1'bz;
  14. // 1024x768x60 with a 67.2 MHz pixel clock
  15. // Htiming: 1024 128 112 140 = 1404
  16. // Vtiming: 768 3 4 23 = 798
  17. reg [10:0] x;
  18. reg [ 9:0] y;
  19. reg [7:0] r;
  20. reg [7:0] g;
  21. reg [7:0] b;
  22. reg hblank;
  23. reg hsync;
  24. reg vblank;
  25. reg vsync;
  26. wire [7:0] pixbar = { x[6:0], 1'b0 } ^ {8{y[9]}};
  27. always @(posedge vid_clk or negedge rst_n)
  28. if (~rst_n)
  29. begin
  30. x <= 11'b0;
  31. y <= 10'b0;
  32. r <= 8'b0;
  33. g <= 8'b0;
  34. b <= 8'b0;
  35. hblank <= 1'b0;
  36. hsync <= 1'b0;
  37. vblank <= 1'b0;
  38. vsync <= 1'b0;
  39. end
  40. else
  41. begin
  42. r <= pixbar & {8{x[9]}};
  43. g <= pixbar & {8{x[8]}};
  44. b <= pixbar & {8{x[7]}};
  45. x <= x + 1'b1;
  46. if (x >= 11'd1403)
  47. begin
  48. x <= 11'd0;
  49. y <= y + 1'b1;
  50. if (y >= 10'd797)
  51. y <= 10'd0;
  52. end
  53. hblank <= x[10];
  54. vblank <= &y[9:8];
  55. hsync <= (x >= 11'd1152 && x < 11'd1264);
  56. vsync <= (y >= 10'd771 && y < 10'd775);
  57. end // else: !if(~rst_n)
  58. wire [7:0] hdmi_data[0:2];
  59. assign hdmi_data[2] = r;
  60. assign hdmi_data[1] = g;
  61. assign hdmi_data[0] = b;
  62. // hdmi_ctl[4] enables TERC4 encoding
  63. wire [4:0] hdmi_ctl[0:2];
  64. assign hdmi_ctl[0][0] = hsync;
  65. assign hdmi_ctl[0][1] = vsync;
  66. assign hdmi_ctl[0][4:2] = 3'b0_00;
  67. assign hdmi_ctl[1] = 5'b0_0000;
  68. assign hdmi_ctl[2] = 5'b0_0000;
  69. wire [9:0] hdmi_tmds_data[0:2]; // TMDS encoded data per channel
  70. generate
  71. genvar i;
  72. for (i = 0; i < 3; i = i + 1)
  73. begin : hdmitmds
  74. tmdsenc enc (
  75. .rst_n ( rst_n ),
  76. .clk ( vid_clk ),
  77. .den ( ~hblank & ~vblank ),
  78. .d ( hdmi_data[i] ),
  79. .c ( hdmi_ctl[i][3:0] ),
  80. .tercen( hdmi_ctl[i][4] ),
  81. .q ( hdmi_tmds_data[i] )
  82. );
  83. end
  84. endgenerate
  85. assign hdmi_scl = 1'bz;
  86. assign hdmi_sda = 1'bz;
  87. assign hdmi_hpd = 1'bz;
  88. //
  89. // The ALTLVDS_TX megafunctions is MSB-first and in time-major order.
  90. // However, TMDS is LSB-first, and we have three TMDS words that
  91. // concatenate in word(channel)-major order.
  92. //
  93. wire [29:0] hdmi_to_tx; // TMDS data in the order hdmitx expects
  94. transpose #(.words(3), .bits(10), .reverse_b(1),
  95. .reg_d(0), .reg_q(0)) hdmitranspose
  96. (
  97. .clk ( vid_clk ),
  98. .d ( { hdmi_tmds_data[2], hdmi_tmds_data[1], hdmi_tmds_data[0] } ),
  99. .q ( hdmi_to_tx )
  100. );
  101. wire vid_hdmiclk;
  102. hdmitx hdmitx (
  103. .pll_areset ( ~pll_locked[0] ),
  104. .tx_in ( hdmi_to_tx ),
  105. .tx_inclock ( vid_clk ),
  106. .tx_coreclock ( vid_hdmiclk ), // Pixel clock in HDMI domain
  107. .tx_locked ( pll_locked[1] ),
  108. .tx_out ( hdmi_d ),
  109. .tx_outclock ( hdmi_clk )
  110. );
  111. endmodule // video