module video ( input rst_n, input vid_clk, input vid_hdmiclk, output [2:0] hdmi_d, output hdmi_clk, inout hdmi_scl, inout hdmi_sda, inout hdmi_hpd ); assign hdmi_scl = 1'bz; assign hdmi_sda = 1'bz; assign hdmi_hpd = 1'bz; // // 1024x768x60 with a 56 MHz pixel clock // // Htiming: 1024 48 32 80 = 1184 = 47.297 kHz // Vtiming: 768 4 4 12 = 788 = 60.022 Hz // localparam [10:0] xact = 11'd1024; localparam [10:0] xback = 11'd48; localparam [10:0] xsync = 11'd32; localparam [10:0] xfront = 11'd80; localparam [ 9:0] yact = 10'd768; localparam [ 9:0] yback = 10'd4; localparam [ 9:0] ysync = 10'd4; localparam [ 9:0] yfront = 10'd12; reg [10:0] x; reg [ 9:0] y; reg [7:0] r; reg [7:0] g; reg [7:0] b; reg hblank; reg hsync; reg vblank; reg vsync; wire [7:0] pixbar = { x[6:0], 1'b0 } ^ {8{y[9]}}; always @(posedge vid_clk or negedge rst_n) if (~rst_n) begin x <= 11'b0; y <= 10'b0; r <= 8'b0; g <= 8'b0; b <= 8'b0; hblank <= 1'b0; hsync <= 1'b0; vblank <= 1'b0; vsync <= 1'b0; end else begin r <= pixbar & {8{x[9]}}; g <= pixbar & {8{x[8]}}; b <= pixbar & {8{x[7]}}; x <= x + 1'b1; if (x >= (xact+xback+xsync+xfront-1'b1)) begin x <= 11'd0; y <= y + 1'b1; if (y >= (yact+yback+ysync+yfront-1'b1)) y <= 10'd0; end hblank <= x >= xact; vblank <= y >= yact; hsync <= (x >= (xact+xback) && x < (xact+xback+xsync)); vsync <= (y >= (yact+yback) && y < (yact+yback+ysync)); end // else: !if(~rst_n) wire [7:0] hdmi_data[0:2]; assign hdmi_data[2] = r; assign hdmi_data[1] = g; assign hdmi_data[0] = b; wire [1:0] hdmi_ctl[0:2]; assign hdmi_ctl[0] = { vsync, hsync }; assign hdmi_ctl[1] = 2'b00; assign hdmi_ctl[2] = 2'b00; wire [9:0] hdmi_tmds_data[0:2]; // TMDS encoded data per channel generate genvar i; for (i = 0; i < 3; i = i + 1) begin : hdmitmds tmdsenc enc ( .rst_n ( rst_n ), .clk ( vid_clk ), .den ( ~hblank & ~vblank ), .d ( hdmi_data[i] ), .ten ( 1'b0 ), // TERC data not supported yet .t ( 4'bx ), .c ( hdmi_ctl[i] ), .q ( hdmi_tmds_data[i] ) ); end endgenerate assign hdmi_scl = 1'bz; assign hdmi_sda = 1'bz; assign hdmi_hpd = 1'bz; // // The ALTLVDS_TX megafunctions is MSB-first in channel-major // order, but TMDS is LSB first. Thus, bit-reverse the data within // each channel. // wire [39:0] hdmi_to_tx; // TMDS data in the order hdmitx expects transpose #(.words( 4 ), .bits( 10 ), .reverse_b ( 1'b1 ), .reverse_w ( 1'b0 ), .transpose ( 1'b0 ), .reg_d ( 1'b0 ), .reg_q ( 1'b1 ) ) hdmitranspose ( .clk ( vid_clk ), .d ( { 10'b00000_11111, hdmi_tmds_data[2], hdmi_tmds_data[1], hdmi_tmds_data[0] } ), .q ( hdmi_to_tx ) ); hdmitx hdmitx ( .tx_in ( hdmi_to_tx ), .tx_syncclock ( vid_clk ), .tx_inclock ( vid_hdmiclk ), .tx_out ( { hdmi_clk, hdmi_d } ) ); endmodule // video