1 |
121 |
ultro |
////////////////////////////////////////////////////////////////////////
|
2 |
|
|
module HDMI_test(
|
3 |
|
|
input rstn,
|
4 |
|
|
input pixclk, // 25MHz
|
5 |
|
|
output [2:0] TMDSp, TMDSn,
|
6 |
|
|
output TMDSp_clock, TMDSn_clock
|
7 |
|
|
);
|
8 |
|
|
////////////////////////////////////////////////////////////////////////
|
9 |
|
|
reg [9:0] CounterX, CounterY;
|
10 |
|
|
reg hSync, vSync, DrawArea;
|
11 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) DrawArea <= 0; else DrawArea <= (CounterX<640) && (CounterY<480);
|
12 |
|
|
|
13 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) CounterX <= 0; else CounterX <= (CounterX==799) ? 0 : CounterX+1;
|
14 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) CounterY <= 0; else if(CounterX==799) CounterY <= (CounterY==524) ? 0 : CounterY+1;
|
15 |
|
|
|
16 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) hSync <= 0; else hSync <= (CounterX>=656) && (CounterX<752);
|
17 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) vSync <= 0; else vSync <= (CounterY>=490) && (CounterY<492);
|
18 |
|
|
|
19 |
|
|
////////////////
|
20 |
|
|
wire [7:0] W = {8{CounterX[7:0]==CounterY[7:0]}};
|
21 |
|
|
wire [7:0] A = {8{CounterX[7:5]==3'h2 && CounterY[7:5]==3'h2}};
|
22 |
|
|
reg [7:0] red, green, blue;
|
23 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) red <= 0; else red <= ({CounterX[5:0] & {6{CounterY[4:3]==~CounterX[4:3]}}, 2'b00} | W) & ~A;
|
24 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) green <= 0; else green <= (CounterX[7:0] & {8{CounterY[6]}} | W) & ~A;
|
25 |
|
|
always @(posedge pixclk or negedge rstn) if (~rstn) blue <= 0; else blue <= CounterY[7:0] | W | A;
|
26 |
|
|
|
27 |
|
|
////////////////////////////////////////////////////////////////////////
|
28 |
|
|
wire [9:0] TMDS_red, TMDS_green, TMDS_blue;
|
29 |
|
|
TMDS_encoder encode_R(.clk(pixclk), .VD(red ), .CD(2'b00) , .VDE(DrawArea), .TMDS(TMDS_red));
|
30 |
|
|
TMDS_encoder encode_G(.clk(pixclk), .VD(green), .CD(2'b00) , .VDE(DrawArea), .TMDS(TMDS_green));
|
31 |
|
|
TMDS_encoder encode_B(.clk(pixclk), .VD(blue ), .CD({vSync,hSync}), .VDE(DrawArea), .TMDS(TMDS_blue));
|
32 |
|
|
|
33 |
|
|
////////////////////////////////////////////////////////////////////////
|
34 |
|
|
wire clk_TMDS, DCM_TMDS_CLKFX; // 25MHz x 10 = 250MHz
|
35 |
|
|
DCM_SP #(.CLKFX_MULTIPLY(10)) DCM_TMDS_inst(.CLKIN(pixclk), .CLKFX(DCM_TMDS_CLKFX), .RST(~rstn));
|
36 |
|
|
BUFG BUFG_TMDSp(.I(DCM_TMDS_CLKFX), .O(clk_TMDS));
|
37 |
|
|
|
38 |
|
|
////////////////////////////////////////////////////////////////////////
|
39 |
|
|
reg [3:0] TMDS_mod10=0; // modulus 10 counter
|
40 |
|
|
reg [9:0] TMDS_shift_red=0, TMDS_shift_green=0, TMDS_shift_blue=0;
|
41 |
|
|
reg TMDS_shift_load=0;
|
42 |
|
|
always @(posedge clk_TMDS) TMDS_shift_load <= (TMDS_mod10==4'd9);
|
43 |
|
|
|
44 |
|
|
always @(posedge clk_TMDS)
|
45 |
|
|
begin
|
46 |
|
|
TMDS_shift_red <= TMDS_shift_load ? TMDS_red : TMDS_shift_red [9:1];
|
47 |
|
|
TMDS_shift_green <= TMDS_shift_load ? TMDS_green : TMDS_shift_green[9:1];
|
48 |
|
|
TMDS_shift_blue <= TMDS_shift_load ? TMDS_blue : TMDS_shift_blue [9:1];
|
49 |
|
|
TMDS_mod10 <= (TMDS_mod10==4'd9) ? 4'd0 : TMDS_mod10+4'd1;
|
50 |
|
|
end
|
51 |
|
|
|
52 |
|
|
OBUFDS OBUFDS_red (.I(TMDS_shift_red [0]), .O(TMDSp[2]), .OB(TMDSn[2]));
|
53 |
|
|
OBUFDS OBUFDS_green(.I(TMDS_shift_green[0]), .O(TMDSp[1]), .OB(TMDSn[1]));
|
54 |
|
|
OBUFDS OBUFDS_blue (.I(TMDS_shift_blue [0]), .O(TMDSp[0]), .OB(TMDSn[0]));
|
55 |
|
|
OBUFDS OBUFDS_clock(.I(pixclk), .O(TMDSp_clock), .OB(TMDSn_clock));
|
56 |
|
|
endmodule
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
////////////////////////////////////////////////////////////////////////
|
60 |
|
|
module TMDS_encoder(
|
61 |
|
|
input clk,
|
62 |
|
|
input [7:0] VD, // video data (red, green or blue)
|
63 |
|
|
input [1:0] CD, // control data
|
64 |
|
|
input VDE, // video data enable, to choose between CD (when VDE=0) and VD (when VDE=1)
|
65 |
|
|
output reg [9:0] TMDS = 0
|
66 |
|
|
);
|
67 |
|
|
|
68 |
|
|
wire [3:0] Nb1s = VD[0] + VD[1] + VD[2] + VD[3] + VD[4] + VD[5] + VD[6] + VD[7];
|
69 |
|
|
wire XNOR = (Nb1s>4'd4) || (Nb1s==4'd4 && VD[0]==1'b0);
|
70 |
|
|
wire [8:0] q_m = {~XNOR, q_m[6:0] ^ VD[7:1] ^ {7{XNOR}}, VD[0]};
|
71 |
|
|
|
72 |
|
|
reg [3:0] balance_acc = 0;
|
73 |
|
|
wire [3:0] balance = q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7] - 4'd4;
|
74 |
|
|
wire balance_sign_eq = (balance[3] == balance_acc[3]);
|
75 |
|
|
wire invert_q_m = (balance==0 || balance_acc==0) ? ~q_m[8] : balance_sign_eq;
|
76 |
|
|
wire [3:0] balance_acc_inc = balance - ({q_m[8] ^ ~balance_sign_eq} & ~(balance==0 || balance_acc==0));
|
77 |
|
|
wire [3:0] balance_acc_new = invert_q_m ? balance_acc-balance_acc_inc : balance_acc+balance_acc_inc;
|
78 |
|
|
wire [9:0] TMDS_data = {invert_q_m, q_m[8], q_m[7:0] ^ {8{invert_q_m}}};
|
79 |
|
|
wire [9:0] TMDS_code = CD[1] ? (CD[0] ? 10'b1010101011 : 10'b0101010100) : (CD[0] ? 10'b0010101011 : 10'b1101010100);
|
80 |
|
|
|
81 |
|
|
always @(posedge clk) TMDS <= VDE ? TMDS_data : TMDS_code;
|
82 |
|
|
always @(posedge clk) balance_acc <= VDE ? balance_acc_new : 4'h0;
|
83 |
|
|
endmodule
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
////////////////////////////////////////////////////////////////////////
|