ZEDBOARD 视频扩展板子上实现HDMI,代码



  
1,www.fpga4fun.com是一个非常好的站,深入浅出讲解。此代码主要部分来源于其HDMI部分的代码。

2.,使用SYSCLK.TAOBAO.COM购买的兼容ZEDBOARD板子以及视频输出扩展板。

3,实现了640X480 分辨率输出:

//1//


4,需要两个时钟,一个是像素点时钟PIXCEL—CLK ,另外一个是10倍于PIXCEL_CLK的HDMI数据输出时钟。当640X480分辨率时,这两个时钟分别是 25M和250M。


5,代码如下 :  

//THIS HARDWARE ONLY SUPPORT TO 640X480!!!!!!



`define VGA_640x480_60HZ_25MHz
//`define VGA_800x600_60HZ_40MHz
//`define VGA_1024x768_60HZ_65MHz
//`define VGA_1440x900_60HZ_106_5MHz
//`define VGA_1280x1024_60HZ_108MHz
//`define VGA_1600x1200_60HZ_175_5MHz
//`define VGA_1920x1080_60HZ_148_5MHz



`ifdef VGA_640x480_60HZ_25MHz
//640x480@60HZ_25MHz clock.

`define    H_ACTIVE		  640   
`define    H_FRONT		  16    
`define    H_SYNC		  96    
`define    H_BACK		  48    
`define    V_ACTIVE		  480  	
`define    V_FRONT  	  11    
`define    V_SYNC		  2     
`define    V_BACK	      31    
	
`endif


`ifdef VGA_800x600_60HZ_40MHz
//800x600@60HZ_40MHz clock.
`define   H_SYNC      128  
`define   H_BACK      88  
`define   H_ACTIVE    800  
`define   H_FRONT     40  
`define   V_SYNC      4  
`define   V_BACK      23  
`define   V_ACTIVE    600  
`define   V_FRONT     1  

`endif

`ifdef VGA_1024x768_60HZ_65MHz
  //1024x768@60HZ_65MHz clock.
`define   H_SYNC      136  
`define   H_BACK      160  
`define   H_ACTIVE    1024  
`define   H_FRONT     24  
`define   V_SYNC      6  
`define   V_BACK      29  
`define   V_ACTIVE    768  
`define   V_FRONT     3  

`endif

`ifdef VGA_1440x900_60HZ_106_5MHz
  //1440x900@60HZ_106.5MHz clock.
`define   H_SYNC      152  
`define   H_BACK      232  
`define   H_ACTIVE    1440  
`define   H_FRONT     80  
`define   V_SYNC      6  
`define   V_BACK      25  
`define   V_ACTIVE    900  
`define   V_FRONT     3  

`endif

`ifdef VGA_1280x1024_60HZ_108MHz
  //1280x1024@60HZ_108MHz clock.
`define   H_SYNC      112  
`define   H_BACK      248  
`define   H_ACTIVE    1280  
`define   H_FRONT     48  
`define   V_SYNC      3  
`define   V_BACK      38  
`define   V_ACTIVE    1024  
`define   V_FRONT     1  

`endif

`ifdef VGA_1600x1200_60HZ_175_5MHz
 //1600x1200@65HZ_175.5MHz clock.
`define   H_SYNC      192  
`define   H_BACK      304  
`define   H_ACTIVE    1600  
`define   H_FRONT     64  
`define   V_SYNC      3  
`define   V_BACK      46  
`define   V_ACTIVE    1200  
`define   V_FRONT     1  

`endif

`ifdef VGA_1920x1080_60HZ_148_5MHz
 //1920x1080_60HZ_148_5MHz clock.
`define   H_SYNC      44  
`define   H_BACK      148  
`define   H_ACTIVE    1920  
`define   H_FRONT     88  
`define   V_SYNC      5  
`define   V_BACK      36  
`define   V_ACTIVE    1080  
`define   V_FRONT     4  

`endif

//`define   H_TOTAL   ( H_SYNC + H_BACK + H_ACTIVE + H_FRONT  )
//`define   V_TOTAL   ( V_SYNC + V_BACK + V_ACTIVE + V_FRONT  )








// (c) fpga4fun.com & KNJN LLC 2013



module HDMI_test_TOP(
	input clk_i,  // 25MHz
	output [2:0] TMDSp, TMDSn,
	output TMDSp_clock, TMDSn_clock
);
wire   pclk,pclkx10; 
 DCM_PLL U (
 .clk_in1(clk_i), //CLK100M IN 
  .clk_out1(pclk),//CLK25M_OUT 
  .clk_out2(pclkx10),//CLK25M_OUT 
 .locked(),
 .reset(1'b0)
 );

HDMI_test #(
.H_ACTIVE     (`H_ACTIVE ) ,  
.H_FRONT      ( `H_FRONT )  ,  
.H_SYNC       ( `H_SYNC  ) ,  
.H_BACK       (`H_BACK   ),  
.V_ACTIVE     (`V_ACTIVE ) ,       
.V_FRONT      (`V_FRONT  ) ,  
.V_SYNC       (`V_SYNC   ) ,  
.V_BACK       ( `V_BACK   )  
) uu(
     .pixclk(pclk),  // 25MHz
     .clk_TMDS(pclkx10),
     .TMDSp( TMDSp), 
     .TMDSn( TMDSn),
     .TMDSp_clock(TMDSp_clock ), 
     .TMDSn_clock( TMDSn_clock )
 );
   
   
endmodule 
   
/*
`ifdef VGA_640x480_60HZ_25MHz  
//640x480@60HZ_25MHz clock.  
  
parameter  H_ACTIVE     = 640 ;  
parameter  H_FRONT      = 16  ;  
parameter  H_SYNC       = 96  ;  
parameter  H_BACK       = 48  ;  

parameter  V_ACTIVE     = 480 ;       
parameter  V_FRONT      = 11  ;  
parameter  V_SYNC       = 2   ;  
parameter  V_BACK       = 31  ;    
      
`endif  
*/
    
module HDMI_test #(
parameter   integer H_ACTIVE     =   `H_ACTIVE  ,  
parameter   integer H_FRONT      =   `H_FRONT   ,  
parameter   integer H_SYNC       =   `H_SYNC    ,  
parameter   integer H_BACK       =   `H_BACK    ,  
parameter   integer V_ACTIVE     =   `V_ACTIVE  ,       
parameter   integer V_FRONT      =   `V_FRONT   ,  
parameter   integer V_SYNC       =   `V_SYNC    ,  
parameter   integer V_BACK       =   `V_BACK    
) (
	input pixclk, clk_TMDS, // 25MHz
	output [2:0] TMDSp, TMDSn,
	output TMDSp_clock, TMDSn_clock
);
parameter integer H_TOTAL  = H_SYNC + H_BACK + H_ACTIVE + H_FRONT;  
parameter integer V_TOTAL  = V_SYNC + V_BACK + V_ACTIVE + V_FRONT;      

reg [31:0] CounterX, CounterY;
reg hSync, vSync, DrawArea;
always @(posedge pixclk) DrawArea <= (CounterX<H_ACTIVE) && (CounterY<V_ACTIVE);

always @(posedge pixclk) CounterX <= (CounterX==(H_TOTAL-1)) ? 0 : CounterX+1;
always @(posedge pixclk) if(CounterX==(H_TOTAL-1)) CounterY <= (CounterY==(V_TOTAL-1)) ? 0 : CounterY+1;

always @(posedge pixclk) hSync <= (CounterX>=(H_FRONT+H_ACTIVE)) && (CounterX<(H_FRONT+H_ACTIVE+H_SYNC));
always @(posedge pixclk) vSync <= (CounterY>=(V_FRONT+V_ACTIVE)) && (CounterY<(V_FRONT+V_ACTIVE+V_SYNC));


wire [7:0] W = {8{CounterX[7:0]==CounterY[7:0]}};
wire [7:0] A = {8{CounterX[7:5]==3'h2 && CounterY[7:5]==3'h2}};
reg [7:0] red, green, blue;
always @(posedge pixclk) red <= ({CounterX[5:0] & {6{CounterY[4:3]==~CounterX[4:3]}}, 2'b00} | W) & ~A;
always @(posedge pixclk) green <= (CounterX[7:0] & {8{CounterY[6]}} | W) & ~A;
always @(posedge pixclk) blue <= CounterY[7:0] | W | A;


wire [9:0] TMDS_red, TMDS_green, TMDS_blue;
TMDS_encoder encode_R(.clk(pixclk), .VD(red  ), .CD(2'b00)        , .VDE(DrawArea), .TMDS(TMDS_red));
TMDS_encoder encode_G(.clk(pixclk), .VD(green), .CD(2'b00)        , .VDE(DrawArea), .TMDS(TMDS_green));
TMDS_encoder encode_B(.clk(pixclk), .VD(blue ), .CD({vSync,hSync}), .VDE(DrawArea), .TMDS(TMDS_blue));


//wire clk_TMDS, DCM_TMDS_CLKFX;  // 25MHz x 10 = 250MHz
//DCM_SP #(.CLKFX_MULTIPLY(10)) DCM_TMDS_inst(.CLKIN(pixclk), .CLKFX(DCM_TMDS_CLKFX), .RST(1'b0));
//BUFG BUFG_TMDSp(.I(DCM_TMDS_CLKFX), .O(clk_TMDS));


reg [3:0] TMDS_mod10=0;  // modulus 10 counter
reg [9:0] TMDS_shift_red=0, TMDS_shift_green=0, TMDS_shift_blue=0;
reg TMDS_shift_load=0;
always @(posedge clk_TMDS) TMDS_shift_load <= (TMDS_mod10==4'd9);

always @(posedge clk_TMDS)
begin
	TMDS_shift_red   <= TMDS_shift_load ? TMDS_red   : TMDS_shift_red  [9:1];
	TMDS_shift_green <= TMDS_shift_load ? TMDS_green : TMDS_shift_green[9:1];
	TMDS_shift_blue  <= TMDS_shift_load ? TMDS_blue  : TMDS_shift_blue [9:1];	
	TMDS_mod10 <= (TMDS_mod10==4'd9) ? 4'd0 : TMDS_mod10+4'd1;
end

OBUFDS OBUFDS_red  (.I(TMDS_shift_red  [0]), .O(TMDSp[2]), .OB(TMDSn[2]));
OBUFDS OBUFDS_green(.I(TMDS_shift_green[0]), .O(TMDSp[1]), .OB(TMDSn[1]));
OBUFDS OBUFDS_blue (.I(TMDS_shift_blue [0]), .O(TMDSp[0]), .OB(TMDSn[0]));
OBUFDS OBUFDS_clock(.I(pixclk), .O(TMDSp_clock), .OB(TMDSn_clock));

endmodule



module TMDS_encoder(
	input clk,
	input [7:0] VD,  // video data (red, green or blue)
	input [1:0] CD,  // control data
	input VDE,  // video data enable, to choose between CD (when VDE=0) and VD (when VDE=1)
	output reg [9:0] TMDS = 0
);

wire [3:0] Nb1s = VD[0] + VD[1] + VD[2] + VD[3] + VD[4] + VD[5] + VD[6] + VD[7];
wire XNOR = (Nb1s>4'd4) || (Nb1s==4'd4 && VD[0]==1'b0);
wire [8:0] q_m = {~XNOR, q_m[6:0] ^ VD[7:1] ^ {7{XNOR}}, VD[0]};

reg [3:0] balance_acc = 0;
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;
wire balance_sign_eq = (balance[3] == balance_acc[3]);
wire invert_q_m = (balance==0 || balance_acc==0) ? ~q_m[8] : balance_sign_eq;
wire [3:0] balance_acc_inc = balance - ({q_m[8] ^ ~balance_sign_eq} & ~(balance==0 || balance_acc==0));
wire [3:0] balance_acc_new = invert_q_m ? balance_acc-balance_acc_inc : balance_acc+balance_acc_inc;
wire [9:0] TMDS_data = {invert_q_m, q_m[8], q_m[7:0] ^ {8{invert_q_m}}};
wire [9:0] TMDS_code = CD[1] ? (CD[0] ? 10'b1010101011 : 10'b0101010100) : (CD[0] ? 10'b0010101011 : 10'b1101010100);

always @(posedge clk) TMDS <= VDE ? TMDS_data : TMDS_code;
always @(posedge clk) balance_acc <= VDE ? balance_acc_new : 4'h0;
endmodule


约束文件如下 :

 

set_property PACKAGE_PIN Y9 [get_ports {clk_i}]
set_property IOSTANDARD LVCMOS33 [get_ports {clk_i}]


set_property PACKAGE_PIN L21 [get_ports {TMDSp[0]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSp[0]}]
  
set_property PACKAGE_PIN L22  [get_ports {TMDSn[0]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSn[0]}]
  
set_property PACKAGE_PIN R19 [get_ports {TMDSp[1]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSp[1]}]
 
set_property PACKAGE_PIN T19 [get_ports {TMDSn[1]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSn[1]}]


set_property PACKAGE_PIN K19 [get_ports {TMDSp[2]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSp[2]}]
  
set_property PACKAGE_PIN K20 [get_ports {TMDSn[2]}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSp[2]}]
  
  
  
set_property PACKAGE_PIN L17 [get_ports {TMDSp_clock}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSp_clock}]
  
set_property PACKAGE_PIN M17 [get_ports {TMDSn_clock}]
set_property IOSTANDARD LVDS_25 [get_ports {TMDSn_clock}]


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值