hdmi_core.sv (2689B)
1 // Copyright 2014 Brian Swetland <swetland@frotz.net> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 `timescale 1ns/1ps 16 17 module hdmi_core ( 18 input pixclk, 19 input pixclkx5, 20 // TMDS33 outputs 21 output [2:0]hdmi_d_p, 22 output [2:0]hdmi_d_n, 23 output hdmi_clk_p, 24 output hdmi_clk_n, 25 // RGB data input 26 output rgb_ready, 27 input [7:0]red, 28 input [7:0]grn, 29 input [7:0]blu, 30 // core status 31 output [10:0]xpixel, 32 output [10:0]ypixel, 33 output vblank 34 ); 35 36 parameter HWIDTH = 960; 37 parameter HSYNC0 = 1000; 38 parameter HSYNC1 = 1100; 39 parameter HMAX = 1199; 40 parameter VHEIGHT = 600; 41 parameter VSYNC0 = 613; 42 parameter VSYNC1 = 620; 43 parameter VMAX = 624; 44 45 reg [10:0] hcount, vcount; 46 reg hsync, vsync, active; 47 48 assign vblank = vsync; 49 50 always @(posedge pixclk) begin 51 if (hcount == HMAX) begin 52 hcount <= 0; 53 if (vcount == VMAX) begin 54 vcount <= 0; 55 end else begin 56 vcount <= vcount + 1; 57 end 58 end else begin 59 hcount <= hcount + 1; 60 end 61 active <= (hcount < HWIDTH) && (vcount < VHEIGHT); 62 hsync <= (hcount >= HSYNC0) && (hcount < HSYNC1); 63 vsync <= (vcount >= VSYNC0) && (vcount < VSYNC1); 64 end 65 66 assign xpixel = hcount; 67 assign ypixel = vcount; 68 assign rgb_ready = active; 69 70 wire [9:0] ch0, ch1, ch2; 71 72 tmds_encoder enc2( 73 .clk(pixclk), 74 .data(red), 75 .ctrl(0), 76 .active(active), 77 .out(ch2) 78 ); 79 tmds_encoder enc1( 80 .clk(pixclk), 81 .active(active), 82 .data(grn), 83 .ctrl(0), 84 .out(ch1) 85 ); 86 tmds_encoder enc0( 87 .clk(pixclk), 88 .active(active), 89 .data(blu), 90 .ctrl({vsync,hsync}), 91 .out(ch0) 92 ); 93 94 // does not reliably work on cold boot without reset/sync 95 reg [9:0]txrescnt = 0; 96 wire txres = (txrescnt[9:1] == 9'b100000000); 97 always @(posedge pixclk) begin 98 if (txrescnt != 10'b1111111111) begin 99 txrescnt <= txrescnt + 1; 100 end 101 end 102 103 serdes_10to1_tx tx2( 104 .clk(pixclk), 105 .clkx5(pixclkx5), 106 .reset(txres), 107 .o_p(hdmi_d_p[2]), 108 .o_n(hdmi_d_n[2]), 109 .i_data(ch2) 110 ); 111 112 serdes_10to1_tx tx1( 113 .clk(pixclk), 114 .clkx5(pixclkx5), 115 .reset(txres), 116 .o_p(hdmi_d_p[1]), 117 .o_n(hdmi_d_n[1]), 118 .i_data(ch1) 119 ); 120 121 serdes_10to1_tx tx0( 122 .clk(pixclk), 123 .clkx5(pixclkx5), 124 .reset(txres), 125 .o_p(hdmi_d_p[0]), 126 .o_n(hdmi_d_n[0]), 127 .i_data(ch0) 128 ); 129 130 OBUFDS OBUFDS_clock(.I(pixclk), .O(hdmi_clk_p), .OB(hdmi_clk_n)); 131 132 endmodule