FPGA实现HDMI传输(二)

之前的文章简单介绍了HDMI接口、TMDS编码以及ADV611工作原理和寄存器配置,本篇博客将给出具体的代码以及板级验证结果,代码参考自米联客的教程。

一.ADV7611配置

1.i2c驱动模块

`timescale 1ns / 1psmodule uii2c#
(parameter       WMEN_LEN        =       8'd0,                                           //写入字节长度parameter       RMEN_LEN        =       8'd0,                                           //读出字节长度parameter       CLK_DIV         =       16'd499                                         //i2c时钟分频系数
)
(input                                       clk_i,                                      //系统时钟input            [7:0]                      rd_cnt,                                     //读数据长度,包含器件地址input                                       iic_en,                                     //i2c使能信号input                                       iic_mode,                                   //i2c工作模式input            [WMEN_LEN*8-1'b1:0]        wr_data,                                    //写入数据input            [7:0]                      wr_cnt,                                     //写数据长度,包含器件地址output       reg [RMEN_LEN*8-1'b1:0]        rd_data     =   0,                          //读取数据output       reg                            iic_scl     =   0 ,                         //i2c时钟总线output       reg                            iic_busy    =   0,                          //i2c忙碌,拉高时不进行操作inout        wire                           iic_sda,                                    //i2c数据总线output       reg                            sda_dg      =   1'b1                        //用于调试
);parameter               IDLE        =       4'd0;                                       //空闲状态parameter               START       =       4'd1;                                       //开始parameter               W_WAIT      =       4'd2;                                       //写入数据parameter               W_ACK       =       4'd3;                                       //写响应parameter               R_WAIT      =       4'd4;                                       //读取数据parameter               R_ACK       =       4'd5;                                       //读响应parameter               STOP1       =       4'd6;                                       //停止信号1parameter               STOP2       =       4'd7;                                       //停止信号2parameter               OFFSET      =       CLK_DIV - CLK_DIV/4;                        //产生i2c时钟reg         [2:0]       IIC_S       =       4'd0;                                       //i2c工作状态reg         [15:0]      clkdiv      =       16'd0;                                      //时钟分频计数器reg                     scl_clk     =       1'b0;                                       //i2c工作时钟reg                     scl_r       =       1'b1;                                       //i2c时钟寄存器reg                     sda_o       =       1'b0;                                       //sda输出reg         [7:0]       sda_r       =       8'd0;                                       //i2c数据寄存器reg         [7:0]       sda_i_r     =       8'd0;                                       //i2c输入数据寄存器reg         [7:0]       wcnt        =       8'd0;                                       //写数据计数reg         [7:0]       rcnt        =       8'd0;                                       //读数据计数reg         [2:0]       bcnt        =       3'd0;                                       //读写字节计数reg                     rd_en       =       1'b0;                                       //读使能reg                     iic_sda_r   =       1'b1;                                       //数据总线缓存wire                    scl_offset  =       (clkdiv == OFFSET);                         //scl delay output to fit timingwire                    sda_i;                                                          //i2c数据总线输入//利用计数器产生i2c驱动时钟always@(posedge clk_i)beginif(clkdiv < CLK_DIV)    clkdiv <= clkdiv + 1'b1;else beginclkdiv <= 16'd0; scl_clk <= !scl_clk;endend//三态门处理IOBUF #(.DRIVE(12), // Specify the output drive strength.IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE" .IOSTANDARD("DEFAULT"), // Specify the I/O standard.SLEW("SLOW") // Specify the output slew rate) IOBUF_inst (.O(sda_i),    // Buffer output.IO(iic_sda), // Buffer inout port (connect directly to top-level port).I(sda_o),    // Buffer input.T(sda_o)     // 3-state enable input, high=input, low=output);//时钟总线输出    always @(posedge clk_i) iic_scl <=  scl_offset ?  scl_r : iic_scl;       PULLUP PULLUP_inst (.O(iic_sda));always @(*) beginif(IIC_S == IDLE || IIC_S == STOP1 || IIC_S == STOP2)scl_r <= 1'b1;else scl_r <= ~scl_clk;end   //sda output always @(*) beginif(IIC_S == START || IIC_S == STOP1 || (IIC_S == R_ACK && (rcnt != rd_cnt)))sda_o <= 1'b0;else if(IIC_S == W_WAIT)sda_o <= sda_r[7]; else  sda_o <= 1'b1;end   //sda输出转换always @(negedge scl_clk) beginif(IIC_S == W_ACK || IIC_S == START)beginsda_r <= wr_data[(wcnt*8) +: 8];if( rd_en ) sda_r <= {wr_data[7:1],1'b1};endelse if(IIC_S == W_WAIT)sda_r <= {sda_r[6:0],1'b1};else sda_r <= sda_r;end//sda输入转换  always @(posedge scl_clk) beginif(IIC_S == R_WAIT ||IIC_S == W_ACK ) beginsda_i_r <= {sda_i_r[6:0],sda_i};endelse if(IIC_S == R_ACK)rd_data[((rcnt-1'b1)*8) +: 8] <= sda_i_r[7:0];else if(IIC_S == IDLE)beginsda_i_r <= 8'd0;end endalways @(posedge scl_clk) iic_sda_r <= sda_i;always @(posedge clk_i) sda_dg <= sda_i;//iic状态机always @(negedge scl_clk)begincase(IIC_S) //sda = 1 scl =1IDLE://idle wait iic_en == 1'b1 start trasmit   rd_en == 1'b1 restart if(iic_en == 1'b1 || rd_en == 1'b1)begin iic_busy <= 1'b1;        IIC_S  <= START;endelse beginiic_busy <= 1'b0;wcnt <= 8'd0;rcnt <= 8'd0;rd_en <= 1'b0;endSTART:begin //sda = 0  then scl_clk =0 scl =0 generate startbcnt <= 3'd7;          IIC_S  <= W_WAIT;end           W_WAIT://write data beginif(bcnt > 3'd0)bcnt  <= bcnt - 1'b1; else beginwcnt <= wcnt + 1'b1; IIC_S  <= W_ACK;endend W_ACK://write data ackbegin if(wcnt < wr_cnt)begin bcnt <= 3'd7;IIC_S <= W_WAIT;endelse if(rd_cnt > 3'd0)begin// read dataif(rd_en == 1'b0 && iic_mode == 1'b1)begin rd_en <= 1'b1;IIC_S <= IDLE;  endelse IIC_S <= R_WAIT;bcnt <= 3'd7;endelseIIC_S <= STOP1; if(iic_sda_r == 1'b1)IIC_S <= STOP1;end  R_WAIT://read databeginrd_en <= 1'b0;bcnt  <= bcnt - 1'b1; if(bcnt == 3'd0)beginrcnt <= (rcnt < rd_cnt) ? (rcnt + 1'b1) : rcnt;IIC_S  <= R_ACK;endendR_ACK://read date ackbeginbcnt <= 3'd7;IIC_S <= (rcnt < rd_cnt) ? R_WAIT : STOP1; end  STOP1://sda = 0 scl = 1IIC_S <= STOP2;STOP2://sda = 1 scl = 1IIC_S <= IDLE;          default:IIC_S <= IDLE;endcase
endendmodule

2.adv7611寄存器数据

`timescale 1ns / 1psmodule ui7611reg(input               [8 :0]              REG_INDEX,                      //对已配置寄存器计数output          reg [31:0]              REG_DATA,                       //寄存器地址+写入数据output              [8 :0]              REG_SIZE                        //需配置寄存器个数
);assign	                                REG_SIZE    =   9'd182;//-----------------------------------------------------------------
/	Config Data REG	  //	
always@(*)
case(REG_INDEX)
//write Data Index0   : REG_DATA	=	{8'h98,8'hF4, 8'h80};	//Manufacturer ID Byte - High (Read only)1   : REG_DATA	=	{8'h98,8'hF5, 8'h7c};	//Manufacturer ID Byte - Low (Read only)2   : REG_DATA	= 	{8'h98,8'hF8, 8'h4c};	// BIT[7]-Reset all the Reg 3   : REG_DATA	= 	{8'h98,8'hF9, 8'h64};	//DC offset for analog process4   : REG_DATA	= 	{8'h98,8'hFA, 8'h6c};	//COM10 : href/vsync/pclk/data reverse(Vsync H valid)5   : REG_DATA	= 	{8'h98,8'hFB, 8'h68};	//VGA :	8'h22;	QVGA :	8'h3f;6   : REG_DATA	= 	{8'h98,8'hFD, 8'h44};	//VGA :	8'ha4;	QVGA :	8'h50;7   : REG_DATA	=	{8'h98,8'h01, 8'h05};	//VGA :	8'h07;	QVGA :	8'h03;8   : REG_DATA	= 	{8'h98,8'h00, 8'h1F};	//VGA :	8'hf0;	QVGA :	8'h78;9   : REG_DATA	= 	{8'h98,8'h02, 8'hF7};	//HREF	/ 8'h8010  : REG_DATA  = 	{8'h98,8'h03, 8'h40};	//VGA :	8'hA0;	QVGA :	8'hF011  : REG_DATA  = 	{8'h98,8'h04, 8'h42};	//VGA :	8'hF0;	QVGA :	8'h7812  : REG_DATA	=	{8'h98,8'h05, 8'h28};	//13  : REG_DATA	= 	{8'h98,8'h06, 8'ha7};	//14  : REG_DATA	= 	{8'h98,8'h0b, 8'h44};	//BIT[6] :	0 :VGA; 1;QVGA15  : REG_DATA	= 	{8'h98,8'h0C, 8'h42};	//16  : REG_DATA	= 	{8'h98,8'h15, 8'h80};	//17  : REG_DATA	= 	{8'h98,8'h19, 8'h8a};	//18  : REG_DATA	= 	{8'h98,8'h33, 8'h40};	//19  : REG_DATA	= 	{8'h98,8'h14, 8'h3f};	//20  : REG_DATA	= 	{8'h44,8'hba, 8'h01};	//21  : REG_DATA	= 	{8'h44,8'h7c, 8'h01};	//	22  : REG_DATA	= 	{8'h64,8'h40, 8'h81};	//DSP_Ctrl4 :00/01 : YUV or RGB; 10 : RAW8; 11 : RAW10		23  : REG_DATA	=	{8'h68,8'h9b, 8'h03};   //ADI recommanded setting24  : REG_DATA	=	{8'h68,8'hc1, 8'h01};	//ADI recommanded setting25  : REG_DATA	=	{8'h68,8'hc2, 8'h01};	//ADI recommanded setting26  : REG_DATA	=	{8'h68,8'hc3, 8'h01};	//ADI recommanded setting27  : REG_DATA	=	{8'h68,8'hc4, 8'h01};	//ADI recommanded setting28  : REG_DATA	=	{8'h68,8'hc5, 8'h01};	//ADI recommanded setting29  : REG_DATA	=	{8'h68,8'hc6, 8'h01};	//ADI recommanded setting30  : REG_DATA	=	{8'h68,8'hc7, 8'h01};	//ADI recommanded setting31  : REG_DATA	=	{8'h68,8'hc8, 8'h01};	//ADI recommanded setting32  : REG_DATA	=	{8'h68,8'hc9, 8'h01};	//ADI recommanded settin g33  : REG_DATA	=	{8'h68,8'hca, 8'h01};	//ADI recommanded setting34  : REG_DATA	=	{8'h68,8'hcb, 8'h01};	//ADI recommanded setting35  : REG_DATA	=	{8'h68,8'hcc, 8'h01};	//ADI recommanded setting36  : REG_DATA	=	{8'h68,8'h00, 8'h00}; 	//Set HDMI input Port A37  : REG_DATA	=	{8'h68,8'h83, 8'hfe};	//terminator for Port A38  : REG_DATA	=	{8'h68,8'h6f, 8'h08};	//ADI recommended setting39  : REG_DATA	=	{8'h68,8'h85, 8'h1f};	//ADI recommended setting40  : REG_DATA	=	{8'h68,8'h87, 8'h70};	//ADI recommended setting41  : REG_DATA	=	{8'h68,8'h8d, 8'h04};	//LFG42  : REG_DATA	=	{8'h68,8'h8e, 8'h1e};	//HFG43  : REG_DATA	=	{8'h68,8'h1a, 8'h8a};	//unmute audio44  : REG_DATA	=	{8'h68,8'h57, 8'hda};	// ADI recommended setting45  : REG_DATA	=	{8'h68,8'h58, 8'h01};46  : REG_DATA	=	{8'h68,8'h75, 8'h10}; 47  : REG_DATA	= 	{8'h68,8'h6c ,8'ha3};//enable manual HPA48  : REG_DATA	= 	{8'h98,8'h20 ,8'h70};//HPD low49  : REG_DATA	= 	{8'h64,8'h74 ,8'h00};//disable internal EDID 
//edid 
//0: REG_DATA	= 	{8'h68,8'h6c ,8'ha3}; enable manual HPA
//1: REG_DATA	= 	{8'h98,8'h20 ,8'h70};//HPD low
//2: REG_DATA	= 	{8'h64,8'h74 ,8'h00};//disable internal EDID  
//edid par50  : REG_DATA	= 	{8'h6c,8'd0  , 8'h00};51  : REG_DATA	= 	{8'h6c,8'd1  , 8'hFF};52  : REG_DATA	= 	{8'h6c,8'd2  , 8'hFF};53  : REG_DATA	= 	{8'h6c,8'd3  , 8'hFF};54  : REG_DATA	= 	{8'h6c,8'd4  , 8'hFF};55  : REG_DATA	= 	{8'h6c,8'd5  , 8'hFF};56  : REG_DATA	= 	{8'h6c,8'd6  , 8'hFF};57  : REG_DATA	= 	{8'h6c,8'd7  , 8'h00};58  : REG_DATA	= 	{8'h6c,8'd8  , 8'h20};59  : REG_DATA	= 	{8'h6c,8'd9  , 8'hA3};60  : REG_DATA	= 	{8'h6c,8'd10 , 8'h29};61  : REG_DATA	= 	{8'h6c,8'd11 , 8'h00};62  : REG_DATA	= 	{8'h6c,8'd12 , 8'h01};63  : REG_DATA	= 	{8'h6c,8'd13 , 8'h00};64  : REG_DATA	= 	{8'h6c,8'd14 , 8'h00};65  : REG_DATA	= 	{8'h6c,8'd15 , 8'h00};66  : REG_DATA	= 	{8'h6c,8'd16 , 8'h23};67  : REG_DATA	= 	{8'h6c,8'd17 , 8'h12};68  : REG_DATA	= 	{8'h6c,8'd18 , 8'h01};69  : REG_DATA	= 	{8'h6c,8'd19 , 8'h03};70  : REG_DATA	= 	{8'h6c,8'd20 , 8'h80};71  : REG_DATA	= 	{8'h6c,8'd21 , 8'h73};72  : REG_DATA	= 	{8'h6c,8'd22 , 8'h41};73  : REG_DATA	= 	{8'h6c,8'd23 , 8'h78};74  : REG_DATA	= 	{8'h6c,8'd24 , 8'h0A};75  : REG_DATA	= 	{8'h6c,8'd25 , 8'hF3};76  : REG_DATA	= 	{8'h6c,8'd26 , 8'h30};77  : REG_DATA	= 	{8'h6c,8'd27 , 8'hA7};78  : REG_DATA	= 	{8'h6c,8'd28 , 8'h54};79  : REG_DATA	= 	{8'h6c,8'd29 , 8'h42};80  : REG_DATA	= 	{8'h6c,8'd30 , 8'hAA};81  : REG_DATA	= 	{8'h6c,8'd31 , 8'h26};82  : REG_DATA	= 	{8'h6c,8'd32 , 8'h0F};83  : REG_DATA	= 	{8'h6c,8'd33 , 8'h50};84  : REG_DATA	= 	{8'h6c,8'd34 , 8'h54};85  : REG_DATA	= 	{8'h6c,8'd35 , 8'h25};86  : REG_DATA	= 	{8'h6c,8'd36 , 8'hC8};87  : REG_DATA	= 	{8'h6c,8'd37 , 8'h00};88  : REG_DATA	= 	{8'h6c,8'd38 , 8'h61};89  : REG_DATA	= 	{8'h6c,8'd39 , 8'h4F};90  : REG_DATA	= 	{8'h6c,8'd40 , 8'h01};91  : REG_DATA	= 	{8'h6c,8'd41 , 8'h01};92  : REG_DATA	= 	{8'h6c,8'd42 , 8'h01};93  : REG_DATA	= 	{8'h6c,8'd43 , 8'h01};94  : REG_DATA	= 	{8'h6c,8'd44 , 8'h01};95  : REG_DATA	= 	{8'h6c,8'd45 , 8'h01};96  : REG_DATA	= 	{8'h6c,8'd46 , 8'h01};97  : REG_DATA	= 	{8'h6c,8'd47 , 8'h01};98  : REG_DATA	= 	{8'h6c,8'd48 , 8'h01};99  : REG_DATA	= 	{8'h6c,8'd49 , 8'h01};100  : REG_DATA	= 	{8'h6c,8'd50 , 8'h01};101  : REG_DATA	= 	{8'h6c,8'd51 , 8'h01};102  : REG_DATA	= 	{8'h6c,8'd52 , 8'h01};103  : REG_DATA	= 	{8'h6c,8'd53 , 8'h01};104  : REG_DATA	= 	{8'h6c,8'd54 , 8'h02};105  : REG_DATA	= 	{8'h6c,8'd55 , 8'h3A};106  : REG_DATA	= 	{8'h6c,8'd56 , 8'h80};107  : REG_DATA	= 	{8'h6c,8'd57 , 8'h18};108  : REG_DATA	= 	{8'h6c,8'd58 , 8'h71};109  : REG_DATA	= 	{8'h6c,8'd59 , 8'h38};110  : REG_DATA	= 	{8'h6c,8'd60 , 8'h2D};111  : REG_DATA	= 	{8'h6c,8'd61 , 8'h40};112  : REG_DATA	= 	{8'h6c,8'd62 , 8'h58};113  : REG_DATA	= 	{8'h6c,8'd63 , 8'h2C};114  : REG_DATA	= 	{8'h6c,8'd64 , 8'h45};115  : REG_DATA	= 	{8'h6c,8'd65 , 8'h00};116  : REG_DATA	= 	{8'h6c,8'd66 , 8'h80};117  : REG_DATA	= 	{8'h6c,8'd67 , 8'h88};118  : REG_DATA	= 	{8'h6c,8'd68 , 8'h42};119  : REG_DATA	= 	{8'h6c,8'd69 , 8'h00};120  : REG_DATA	= 	{8'h6c,8'd70 , 8'h00};121  : REG_DATA	= 	{8'h6c,8'd71 , 8'h1E};122  : REG_DATA	= 	{8'h6c,8'd72 , 8'h8C};123  : REG_DATA	= 	{8'h6c,8'd73 , 8'h0A};124  : REG_DATA	= 	{8'h6c,8'd74 , 8'hD0};125  : REG_DATA	= 	{8'h6c,8'd75 , 8'h8A};126  : REG_DATA	= 	{8'h6c,8'd76 , 8'h20};127  : REG_DATA	= 	{8'h6c,8'd77 , 8'hE0};128  : REG_DATA	= 	{8'h6c,8'd78 , 8'h2D};129  : REG_DATA	= 	{8'h6c,8'd79 , 8'h10};130  : REG_DATA	= 	{8'h6c,8'd80 , 8'h10};131  : REG_DATA	= 	{8'h6c,8'd81 , 8'h3E};132  : REG_DATA	= 	{8'h6c,8'd82 , 8'h96};133  : REG_DATA	= 	{8'h6c,8'd83 , 8'h00};134  : REG_DATA	= 	{8'h6c,8'd84 , 8'h80};135  : REG_DATA	= 	{8'h6c,8'd85 , 8'h88};136  : REG_DATA	= 	{8'h6c,8'd86 , 8'h42};137  : REG_DATA	= 	{8'h6c,8'd87 , 8'h00};138  : REG_DATA	= 	{8'h6c,8'd88 , 8'h00};139  : REG_DATA	= 	{8'h6c,8'd89 , 8'h18};140  : REG_DATA	= 	{8'h6c,8'd90 , 8'h00};141  : REG_DATA	= 	{8'h6c,8'd91 , 8'h00};142  : REG_DATA	= 	{8'h6c,8'd92 , 8'h00};143  : REG_DATA	= 	{8'h6c,8'd93 , 8'hFC};144  : REG_DATA	= 	{8'h6c,8'd94 , 8'h00};145  : REG_DATA	= 	{8'h6c,8'd95 , 8'h48};146  : REG_DATA	= 	{8'h6c,8'd96 , 8'h44};147  : REG_DATA	= 	{8'h6c,8'd97 , 8'h4D};148  : REG_DATA	= 	{8'h6c,8'd98 , 8'h49};149  : REG_DATA	= 	{8'h6c,8'd99 , 8'h20};150  : REG_DATA	= 	{8'h6c,8'd100 , 8'h20};151  : REG_DATA	= 	{8'h6c,8'd101 , 8'h20};152  : REG_DATA	= 	{8'h6c,8'd102 , 8'h20};153  : REG_DATA	= 	{8'h6c,8'd103 , 8'h0A};154  : REG_DATA	= 	{8'h6c,8'd104 , 8'h20};155  : REG_DATA	= 	{8'h6c,8'd105 , 8'h20};156  : REG_DATA	= 	{8'h6c,8'd106 , 8'h20};157  : REG_DATA	= 	{8'h6c,8'd107 , 8'h20};158  : REG_DATA	= 	{8'h6c,8'd108 , 8'h00};159  : REG_DATA	= 	{8'h6c,8'd109 , 8'h00};160  : REG_DATA	= 	{8'h6c,8'd110 , 8'h00};161  : REG_DATA	= 	{8'h6c,8'd111 , 8'hFD};162  : REG_DATA	= 	{8'h6c,8'd112 , 8'h00};163  : REG_DATA	= 	{8'h6c,8'd113 , 8'h32};164  : REG_DATA	= 	{8'h6c,8'd114 , 8'h55};165  : REG_DATA	= 	{8'h6c,8'd115 , 8'h1F};166  : REG_DATA	= 	{8'h6c,8'd116 , 8'h45};167  : REG_DATA	= 	{8'h6c,8'd117 , 8'h0F};168  : REG_DATA	= 	{8'h6c,8'd118 , 8'h00};169  : REG_DATA	= 	{8'h6c,8'd119 , 8'h0A};170  : REG_DATA	= 	{8'h6c,8'd120 , 8'h20};171  : REG_DATA	= 	{8'h6c,8'd121 , 8'h20};172  : REG_DATA	= 	{8'h6c,8'd122 , 8'h20};173  : REG_DATA	= 	{8'h6c,8'd123 , 8'h20};174  : REG_DATA	= 	{8'h6c,8'd124 , 8'h20};175  : REG_DATA	= 	{8'h6c,8'd125 , 8'h20};176  : REG_DATA	= 	{8'h6c,8'd126 , 8'h01};177  : REG_DATA	= 	{8'h6c,8'd127 , 8'h24};178  : REG_DATA	= 	{8'h64,8'h74  , 8'h01};// enable internal EDID179  : REG_DATA	= 	{8'h98,8'h20  , 8'hf0};// HPD high180  : REG_DATA	= 	{8'h68,8'h6c  , 8'ha2};// disable manual HPA	181  : REG_DATA	=   {8'h98,8'hf4  , 8'h00};default:REG_DATA =0;
endcaseendmodule

3.配置模块顶层

`timescale 1ns / 1psmodule uicfg7611#(parameter	        CLK_DIV         =           16'd999
)
(input                                   clk_i,                                          //系统时钟input                                   rst_n,                                          //系统复位output                                  adv_scl,                                        //i2c时钟总线inout                                   adv_sda,                                        //i2c数据总线output reg                              cfg_done                                        //寄存器配置完成信号
);	reg                     [8 :0]          rst_cnt     =   9'd0;                           //延迟复位计数器reg                                     iic_en;                                         //i2c使能信号reg                     [31:0]          wr_data;                                        //寄存器地址+写入数据reg                     [1 :0]          TS_S        =   2'd0;                           //状态机工作状态reg                     [8 :0]          byte_cnt    =   9'd0;                           //读写字节计数器reg                     [8 :0]          REG_INDEX;                                      //寄存器配置wire                                    iic_busy;                                       //i2c忙碌wire                    [23:0]          REG_DATA;wire                    [8 :0]          REG_SIZE;always@(posedge clk_i) beginif(!rst_n)rst_cnt <= 9'd0;else if(!rst_cnt[8]) rst_cnt <= rst_cnt + 1'b1;end//状态机工作状态转换以及输出always@(posedge clk_i) beginif(!rst_cnt[8])beginREG_INDEX<= 9'd0;iic_en  <= 1'b0;wr_data <= 32'd0;cfg_done<= 1'b0;TS_S    <= 2'd0;    endelse begincase(TS_S)0:if(cfg_done == 1'b0)TS_S <= 2'd1;1:if(!iic_busy)begin//write dataiic_en  <= 1'b1; wr_data[7  :0] <= REG_DATA[23:16];   wr_data[15 :8] <= REG_DATA[15: 8];   wr_data[23:16] <= REG_DATA[7 : 0];endelse TS_S    <= 2'd2;2:beginiic_en  <= 1'b0; if(!iic_busy)begin REG_INDEX<= REG_INDEX + 1'b1;TS_S    <= 2'd3;endend3:begin//read rtc registerif(REG_INDEX == REG_SIZE)begincfg_done <= 1'b1;endTS_S 	<= 2'd0;end endcaseend
enduii2c#(.WMEN_LEN(4),.RMEN_LEN(1),.CLK_DIV(CLK_DIV)//499 for 50M 999 for 100M)uii2c_inst(.clk_i(clk_i),.iic_scl(adv_scl),.iic_sda(adv_sda),.wr_data(wr_data),.wr_cnt(8'd3),//write data max len = 4BYTES.rd_data(),   //read not used.rd_cnt(8'd0),//read not used.iic_mode(1'b0),.iic_en(iic_en),.iic_busy(iic_busy));//7611regui7611reg  ui7611reg_inst(.REG_SIZE(REG_SIZE),.REG_INDEX(REG_INDEX),.REG_DATA(REG_DATA));   endmodule

二.HDMI输出

1.TMDS编码

module TMDSEncoder(input									    clk		        ,//系统时钟信号;input									    rst  	        ,//系统复位信号,高电平有效;input				[7 : 0]	                din		        ,//输入待编码数据input                                       c0              ,//控制信号C0input                                       c1              ,//控制信号c1input                                       de              ,//输入数据有效指示信号;output reg			[9 : 0]	                q_out	         //编码输出数据
);localparam          CTRLTOKEN0      =       10'b1101010100  ;localparam          CTRLTOKEN1      =       10'b0010101011  ;localparam          CTRLTOKEN2      =       10'b0101010100  ;localparam          CTRLTOKEN3      =       10'b1010101011  ;reg                 [7 : 0]                 din_r           ;//reg                 [1 : 0]                 de_r,c0_r,c1_r  ;reg                 [3 : 0]                 n1d,n1q_m,n0q_m ;reg                 [5 : 0]                 cnt             ;reg                 [8 : 0]                 q_m_r           ;wire                [8 : 0]                 q_m             ;//wire                                        condition1      ;wire                                        condition2      ;wire                                        condition3      ;//统计待编码输入数据中1的个数,最多8个1,所以位宽为4。always@(posedge clk)beginif(rst)begin//初始值为0;n1d <= 4'd0;endelse if(de)begin//当DE为高电平,统计输入数据中1的个数。n1d <= din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7];endelse begin//当DE为低电平时,对控制信号编码,此时不需要统计输入信号中1的个数,故清零。n1d <= 4'd0;endend//移位寄存器将输入数据暂存,与后续信号对齐。always@(posedge clk)begindin_r   <= din;de_r    <= {de_r[0],de};c0_r    <= {c0_r[0],c0};c1_r    <= {c1_r[0],c1};q_m_r   <= q_m;end//判断条件1,输入数据1的个数多余4或者1的个数等于4并且最低位为0时拉高,其余时间拉低。assign condition1 = ((n1d > 4'd4) || ((n1d == 4'd4) && (~din_r[0])));//对输入的信号进行异或运算。assign q_m[0] = din_r[0];assign q_m[1] = condition1 ? ~((q_m[0] ^ din_r[1])) : (q_m[0] ^ din_r[1]);assign q_m[2] = condition1 ? ~((q_m[1] ^ din_r[2])) : (q_m[1] ^ din_r[2]);assign q_m[3] = condition1 ? ~((q_m[2] ^ din_r[3])) : (q_m[2] ^ din_r[3]);assign q_m[4] = condition1 ? ~((q_m[3] ^ din_r[4])) : (q_m[3] ^ din_r[4]);assign q_m[5] = condition1 ? ~((q_m[4] ^ din_r[5])) : (q_m[4] ^ din_r[5]);assign q_m[6] = condition1 ? ~((q_m[5] ^ din_r[6])) : (q_m[5] ^ din_r[6]);assign q_m[7] = condition1 ? ~((q_m[6] ^ din_r[7])) : (q_m[6] ^ din_r[7]);assign q_m[8] = ~condition1;always@(posedge clk)beginif(rst)begin//初始值为0;n1q_m <= 4'd0;n0q_m <= 4'd0;endelse if(de_r[0])begin//对输入有效数据时,q_m中1和0的个数进行统计;n1q_m <= q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];n0q_m <= 4'd8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]);endelse begin//输入数据无效时清零。n1q_m <= 4'd0;n0q_m <= 4'd0;endend//判断条件2,一行已编码数据中1的个数等于0的个数或者本次编码数据中1的个数等于0的个数。assign condition2 = ((cnt == 6'd0) || (n1q_m == n0q_m));//判断条件3,已编码数据中1的多余0并且本次编码中间数据1的个数也多与0的个数或者已编码数据中0的个数较多并且此次编码中0的个数也比较多时拉高,其余时间拉低。assign condition3 = (((~cnt[5]) && (n1q_m > n0q_m)) || (cnt[5] && (n1q_m < n0q_m)));always@(posedge clk)beginif(rst)begin//初始值为0;cnt <= 6'd0;q_out <= 10'd0;endelse if(de_r[1])beginq_out[8] <= q_m_r[8];//第8位为编码方式位,直接输出即可。if(condition2)beginq_out[9] <= ~q_m_r[8];q_out[7:0] <= q_m_r[8] ? q_m_r[7:0] : ~q_m_r[7:0];//进行cnt的计算;cnt <= q_m_r[8] ? (cnt + n1q_m - n0q_m) : (cnt + n0q_m - n1q_m);endelse if(condition3)beginq_out[9] <= 1'b1;q_out[7:0] <= ~q_m_r[7:0];//进行cnt的计算;cnt <= cnt + {q_m_r[8],1'b0} + n0q_m - n1q_m;endelse beginq_out[9] <= 1'b0;q_out[7:0] <= q_m_r[7:0];//进行cnt的计算;cnt <= cnt - {~q_m_r[8],1'b0} + n1q_m - n0q_m;endendelse begincnt <= 6'd0;//对控制信号进行编码时,将计数器清零。case ({c1_r[1],c0_r[1]})2'b00   : q_out <= CTRLTOKEN0;2'b01   : q_out <= CTRLTOKEN1;2'b10   : q_out <= CTRLTOKEN2;2'b11   : q_out <= CTRLTOKEN3;endcaseendendendmodule

2.并串转换以及差分输出

`timescale 1ns / 1psmodule oserdese2_10to1(input                [9:0]             txdata,                                      //输入并行10位数据input                                  pclk,                                        //并行数据时钟input                                  clkdiv2,                                     //并串转换时钟input                                  txrst,                                       //复位信号output                                 tx_p,                                        //差分输出output                                 tx_n
); wire                 [13:0]            tx_data;wire                                   cascade_do, cascade_di, cascade_to, cascade_ti;reg                                    int_rst;wire                                   dai;assign tx_data = {4'd0,txdata[9:0]};                                                //最高支持14位并串转换always @(*)if(txrst == 1'b1)int_rst <= 1'b1;else if(pclk)int_rst <= 1'b0;else int_rst <= int_rst;OBUFDS #(.IOSTANDARD("DEFAULT"), // Specify the output I/O standard.SLEW("SLOW")           // Specify the output slew rate) OBUFDS_inst (.O(tx_p),     // Diff_p output (connect directly to top-level port).OB(tx_n),   // Diff_n output (connect directly to top-level port).I(dai)      // Buffer input);//----------------------------------------------------------------------------------
//-- Cascaded OSERDES for 10:1 ratio (DDR)
//----------------------------------------------------------------------------------
OSERDESE2 #(.DATA_RATE_OQ("DDR"),   // DDR, SDR.DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR.DATA_WIDTH(10),         // Parallel data width (2-8,10,14).SERDES_MODE("MASTER"), // MASTER, SLAVE.TRISTATE_WIDTH(1)      // 3-state converter width (1,4))oserdese2_master (// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(tx_data[0]),.D2(tx_data[1]),.D3(tx_data[2]),.D4(tx_data[3]),.D5(tx_data[4]),.D6(tx_data[5]),.D7(tx_data[6]),.D8(tx_data[7]),  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(1'b0),.T2(1'b0),.T3(1'b0),.T4(1'b0), // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1(cascade_di),.SHIFTIN2(cascade_ti),// SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each).SHIFTOUT1(),.SHIFTOUT2(),   .OCE(1'b1),             // 1-bit input: Output data clock enable    .CLK(clkdiv2),        // 1-bit input: High speed clock.CLKDIV(pclk),     // 1-bit input: Divided clock                       .OQ(dai),               // 1-bit output: Data path output.TQ(),               // 1-bit output: 3-state control.OFB(),             // 1-bit output: Feedback path for data.TBYTEIN(1'b0),     // 1-bit input: Byte group tristate      .TBYTEOUT(),   // 1-bit output: Byte group tristate.TFB(),             // 1-bit output: 3-state control.TCE(1'b0),          // 1-bit input: 3-state clock enable      .RST(int_rst)             // 1-bit input: Reset);OSERDESE2 #(.DATA_RATE_OQ("DDR"),   // DDR, SDR.DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR.DATA_WIDTH(10),         // Parallel data width (2-8,10,14).SERDES_MODE("SLAVE"), // MASTER, SLAVE.TRISTATE_WIDTH(1)      // 3-state converter width (1,4))oserdese2_slave (// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(1'b0),.D2(1'b0),.D3(tx_data[8]),.D4(tx_data[9]),.D5(tx_data[10]),.D6(tx_data[11]),.D7(tx_data[12]),.D8(tx_data[13]),  // T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(1'b0),.T2(1'b0),.T3(1'b0),.T4(1'b0), // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each).SHIFTOUT1(cascade_di),.SHIFTOUT2(cascade_ti),         // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1(1'b0),.SHIFTIN2(1'b0),.OCE(1'b1),             // 1-bit input: Output data clock enable    .CLK(clkdiv2),        // 1-bit input: High speed clock.CLKDIV(pclk),     // 1-bit input: Divided clock                       .OQ(),               // 1-bit output: Data path output.TQ(),               // 1-bit output: 3-state control.OFB(),             // 1-bit output: Feedback path for data.TFB(),             // 1-bit output: 3-state control.TBYTEIN(1'b0),     // 1-bit input: Byte group tristate      .TBYTEOUT(),   // 1-bit output: Byte group tristate.TCE(1'b0),          // 1-bit input: 3-state clock enable      .RST(int_rst)             // 1-bit input: Reset); endmodule

三.顶层模块

`timescale 1ns / 1psmodule top(input                                               clk_i,                              //系统时钟input                                               hs_i,                               //行同步信号input                                               vs_i,                               //场同步信号input                                               de_i,                               //数据有效信号input                                               pclk_i,                             //像素时钟input               [23:0]                          rgb_i,                              //输入图像数据output                                              adv_rst,                            //adv7611复位信号output                                              adv_scl,                            //时钟总线inout                                               adv_sda,                            //数据总线output                                              HDMI_CLK_P,                         //差分时钟输出output                                              HDMI_CLK_N,output              [2:0]                           HDMI_TX_P,                          //差分数据输出output              [2:0]                           HDMI_TX_N
);assign                                              adv_rst = 1'b1;                     wire                                                cfg_done;                           //寄存器配置完成信号wire                                                locked ;                            //锁相环工作完成信号wire                                                pclkx1,pclkx5;                      //锁相环输出时钟reg                                                 hs_r_0,hs_r_1,hs_r;                 reg                                                 vs_r_0,vs_r_1,vs_r;reg                                                 de_r_0,de_r_1,de_r;reg                 [23:0]                          rgb_r_0;reg                 [23:0]                          rgb_r_1;reg                 [23:0]                          rgb_r;wire                                                rst_o1,rst_o2;wire                                                vid_rst,vid_clk,vid_vs,vid_hs,vid_de;reg                                                 tpg_vs_r = 1'b0;reg                                                 tpg_hs_r = 1'b0;clk_wiz_0 clk_wiz_inst(.clk_out1(pclkx1),.clk_out2(pclkx5),.locked(locked), .clk_in1(pclk_i));uihdmitx uihdmitx_inst
(
.RSTn_i(cfg_done&&locked),
.HS_i(hs_i),
.VS_i(vs_i),
.VDE_i(de_i),
.RGB_i({rgb_i[7:0],rgb_i[15:8],rgb_i[23:16]}),
.PCLKX1_i(pclkx1),
.PCLKX2_5_i(1'b0),
.PCLKX5_i(pclkx5),
.TMDS_TX_CLK_P(HDMI_CLK_P),
.TMDS_TX_CLK_N(HDMI_CLK_N),
.TMDS_TX_P(HDMI_TX_P),
.TMDS_TX_N(HDMI_TX_N)
);uicfg7611 uicfg7611_inst
(
.clk_i(clk_i),
.rst_n(1'b1), 
.adv_scl(adv_scl),
.adv_sda(adv_sda),
.cfg_done(cfg_done)
);endmodule

四.板级验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411523.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM对象创建和内存分配机制深度解析

一、对象创建方式 1、new关键字 这是最常见的创建对象的方式。通过调用类的构造方法&#xff08;constructor&#xff09;来创建对象。如&#xff1a;MyClass obj new MyClass()。这种方式会触发类的加载、链接、初始化过程&#xff08;如果类还未被加载过的话&#xff09;&…

ComfyUI SDXL Prompt Styler 简介

SDXL Prompt Styler 来自于 comfyui-art-venture 节点 style 已经更新 旧版本的 sai-line art 变更为 line art log_prompt 已经更新 旧版本的 false 变更为 Yes 或 No style_name 已经更新 旧版本的 true &#xff08;不再适用&#xff09;&#xff08;可以尝试对应style中…

亲测好用,ChatGPT 3.5/4.0新手使用手册,最全论文指令手册~ 【2024年9月 更新】

本以为遥遥领先的GPT早就普及了&#xff0c;但小伙伴寻找使用的热度一直高居不下&#xff0c;其实现在很简单了&#xff01; 国产大模型快200家了&#xff0c;还有很多成熟的国内AI产品&#xff0c;跟官网一样使用&#xff0c;还更加好用~ ① 3.5 大多数场景是够用的&#xff…

Web大学生网页作业成品——VIVO介绍网页设计与实现(HTML+CSS)(1个页面)

&#x1f389;&#x1f389;&#x1f389; 常见网页设计作业题材有**汽车、环保、明星、文化、国家、抗疫、景点、人物、体育、植物、公益、图书、节日、游戏、商城、旅游、家乡、学校、电影、动漫、非遗、动物、个人、企业、美食、婚纱、其他**等网页设计题目, 可满足大学生网…

基于大数据分析景区消费行为影响因素研究【消费等级预测、携程,去哪网数据抓取】

有需要本项目的可以私信博主&#xff0c;讲解、部署 目录 摘要.... 1 Abstract 2 1引言... 3 1.1 研究背景... 3 1.2 国内外研究现状... 4 1.3 研究目的... 5 1.4 研究意义... 6 2 关键技术理论介绍... 7 2.1 网络爬虫... 7 2.2 Python介绍... 8 2.3 随机森林... 9…

[数据集][目标检测]光伏发电板红外图像鸟粪检测数据集VOC+YOLO格式173张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;173 标注数量(xml文件个数)&#xff1a;173 标注数量(txt文件个数)&#xff1a;173 标注类别…

JAVA国际版同城货运搬家货拉拉货运车系统小程序H5+APP源码

&#x1f31f;【全球搬家新宠儿】国际版同城货运&搬家神器——货拉拉货运车系统&#x1f69a; &#x1f30d; 跨国搬家不再难&#xff0c;货拉拉国际版来助力&#xff01; 你是否曾为跨国搬家而头疼不已&#xff1f;行李堆积如山&#xff0c;物流信息错综复杂&#xff0c…

虚幻引擎UE5入坑记

前言 Unreal Engine 和Unity Engine作为目前主流的游戏引擎&#xff0c;各有优缺点。而我目前的工作还是以Unity开发为主&#xff0c;在使用Unity的过程中&#xff0c;总避免不了听到或看到过UE相关的东西&#xff0c;从开始的好奇到后面想要去学习它&#xff0c;但是&#xf…

JSP 的6种核心动作简介

JSP 的6种核心动作简介 1. jsp:include2. jsp:useBean3. jsp:setProperty4. jsp:getProperty5. jsp:forward6. jsp:plugin &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; JSP 提供了一系列核心动作标签&#xff0c;它们极大地简化了页面开发…

图像字幕Image Captioning——使用语法和语义正确的语言描述图像

1. 什么是图像字幕 Image Captioning&#xff08;图像字幕生成&#xff09; 是计算机视觉和自然语言处理&#xff08;NLP&#xff09;领域的一个交叉研究任务&#xff0c;其目标是自动生成能够描述给定图像内容的自然语言句子。这项任务要求系统不仅要理解图像中的视觉内容&…

揭秘无线领夹麦克风五大行业隐秘:音质失真、隐私泄露需警惕!

​无线领夹麦克风是演讲、教学、直播等场合的得力助手&#xff0c;然而市场上品牌众多&#xff0c;产品质量参差不齐&#xff0c;安全隐患层出不穷。作为一名音频设备评测师&#xff0c;我近期入手了多款无线领夹麦克风进行测评&#xff0c;下面就来为大家揭秘无线领夹麦克风行…

聚餐地计算(华为od机考题)

一、题目 1.原题 小华和小为是很要好的朋友&#xff0c;他们约定周末一起吃饭。 通过手机交流&#xff0c; 他们在地图上选择了多个聚餐地点 &#xff08;由于自然地形等原因&#xff0c;部分聚餐地点不可达&#xff09;&#xff0c; 求小华和小为都能到达的聚餐地点有多少个…

海洋生物材料及其衍生物在3D生物打印中的用处

大家好&#xff0c;今天我们来聊一聊 海洋衍生生物材料在3D 生物打印的引言——《Recent Developments in Bio-Ink Formulations Using Marine-Derived Biomaterials for Three-Dimensional (3D) Bioprinting》。3D 生物打印具有巨大的应用潜力&#xff0c;在生物医学、制药等领…

同声传译是什么?5款同声传译器让国际旅行沟通无障碍

当我踏上异国他乡的旅途&#xff0c;语言的障碍总是让人既兴奋又忐忑。幸运的是&#xff0c;有了同声传译好用的软件&#xff0c;我不再担心与当地人的交流。 只需轻触屏幕&#xff0c;我的话语就能被即时翻译成他们的语言&#xff0c;而他们的回应也能迅速转化为我熟悉的母语…

《前端攻城狮 · Snowflake 雪花算法》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

贾湖刻符——汉字起源的重要线索

关注我们 - 数字罗塞塔计划 - 汉字是世界上唯一沿用至今的古老文字系统&#xff0c;其演变历程承载着中华文明的发展和赓续。那么汉字究竟源自何时&#xff1f;是古代神话传说的“昔者仓颉作书&#xff0c;而天雨粟&#xff0c;鬼夜哭”&#xff1b;还是由华夏先民创制的刻划符…

LCD模组驱动开发

Linux 5.15 内核适配 驱动勾选 由于使用的是 SPI0&#xff0c;所以 TinyVision 的 LCD 模块并不支持使用MIPI-DBI进行驱动&#xff0c;这里我们使用普通的SPI模拟时序。 勾选 SPI 驱动 这里我们使用 SPI-NG 驱动&#xff0c;勾选 <*> SPI NG Driver Support for Allw…

图解计算机网络:一条 HTTP 请求的网络拓扑之旅

引言 常见的网络拓扑结构如下图所示&#xff1a; 在此拓扑中&#xff0c;终端设备通过 WiFi 连接到路由器&#xff0c;路由器再连接到光猫&#xff08;或终端设备通过移动网络 4G/5G 连接到基站&#xff09;&#xff0c;之后 ISP 网络服务提供商接管网络通信&#xff0c;将请求…

Sweet Home 3D:Mac 与 Win 平台的强大 3D 室内装潢设计软件

在当今数字化的时代&#xff0c;一款优秀的室内装潢设计软件可以让你的家居梦想轻松变为现实。Sweet Home 3D for Mac/win 便是这样一款令人惊艳的 3D 室内装潢设计软件&#xff0c;它以其强大的功能和便捷的操作&#xff0c;成为了众多设计师和家居爱好者的首选。 一、功能强…

[数据集][目标检测]考场行为作弊检测数据集VOC+YOLO格式4413张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4413 标注数量(xml文件个数)&#xff1a;4413 标注数量(txt文件个数)&#xff1a;4413 标注…