基于FPGA的 TMDS 编码 及 HDMI 显示

news2025/1/16 5:08:56


目录

引言

TMDS 编码

原理简介

TMDS编码实现

 HDMI差分数据串行

实现方法

源码

HDMI显示方法

思路

实现

工程结构

源代码分享

板级调试视频


引言

最近在开发板上倒腾了一下 TMDS 视频编码的原理以及实现。特在此做一个记录。文附 全部设计源码、MATLAB源码,需要的可以关注一下。



TMDS 编码

原理简介

TMDS,Transition Minimized Differential Signaling,是一种视频编码方式。其将8位数据编码为10位数据。分为两大阶段:

1、8bit —> 9bit

第一比特不变,接下来的7比特或者是与上一比特异或,或者是同或,取决于哪种结果导致翻转数较少;第9比特指示是哪种操作(异或或者同或);

2、9bit —> 10bit

第10比特决定是否要把阶段1中的前8比特反相,决策依据取决于操作是否有利于整体数据的0-1平衡(即,DC平衡)。

编码流程

D 是 8 位 的像素数据

C0C1 为 控制信号

DE 是数据有效信号
cnt是一个寄存器,用来记录数据流的极性,一个大 于0的正值表明了数据流中总共多传了多少个1,一个小于0 的负值表明了数据流中总共多传了多少个0。cnt{t-1}为上一次传输的中的极性,cnt{t}为当前输入的数据的极性。

q_m 最小化传输的编码结果,9 位,由输入的8 位数据经过最小化传输编码原理编码得到。

q_out 对最小化传输编码结果的9 位数据继续进行直流平衡编码后得到的10位输出结果。

N1{x} 统计输入的参数X 中1 的个数
N0{X} 统计输入的参数X 中0 的个数

TMDS编码实现

// | ===================================================---------------------------===================================================
// | ---------------------------------------------------      TMDS 编码模块 	   ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-12-21
// | 完成时间 : 2022-12-21
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 
// |			-2- 
// | 			-3- 
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:

module TMDS_ENCODE_MDL(
// | ==================================== 模块输入输出端口声明 ==================================== 
input 												   	I_PIXEL_CLK  ,//像素数据时钟
input												   	I_SYS_RSTN   ,

input 													I_DATA_EN    ,
input 			[7:0]									I_PIXEL_DATA ,

input 													I_CTRL0      ,
input 													I_CTRL1      ,

output		reg	[9:0]									O_ENCODE_DATA
    );
// | ====================================   模块内部参数声明   ====================================

localparam 		LP_CTRL0 				= 				10'b1101010100;
localparam 		LP_CTRL1 				= 				10'b0010101011;
localparam 		LP_CTRL2 				= 				10'b0101010100;
localparam 		LP_CTRL3 				= 				10'b1010101011;

// | ====================================   模块内部信号声明   ====================================
// 寄存
reg 			[1:0]									R_I_DATA_EN;
reg 			[7:0]									R_I_PIXEL_DATA;
reg 			[1:0]									R_I_CTRL0;
reg 			[1:0]									R_I_CTRL1;

// 4 个判断条件 (依据流程图)
wire 													W_JUDGE_CONDT1;
wire 													W_JUDGE_CONDT2;
wire 													W_JUDGE_CONDT3;
wire 													W_JUDGE_CONDT4;

// 计数
reg 			[3:0]									R_I_PIXEL_DATA_1_NUM;
reg 			[3:0]									R_Q_M_1_NUM;
reg 			[3:0]									R_Q_M_0_NUM;
reg 			[4:0]									R_CNT;


// 9bit编码
wire 			[8:0]									W_Q_M;
reg 			[8:0]									R_Q_M;
// | ====================================   模块内部逻辑设计   ====================================
always @ (posedge I_PIXEL_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_I_DATA_EN 	  <= 2'd0;
		R_I_PIXEL_DATA    <= I_PIXEL_DATA;
		R_I_CTRL0		  <= 2'd0;
		R_I_CTRL1         <= 2'd0;
		R_Q_M 			  <= 9'd0;
	end
	else
	begin
		R_I_DATA_EN 	  <= {R_I_DATA_EN[0],I_DATA_EN};
		R_I_PIXEL_DATA    <= I_PIXEL_DATA;
		R_I_CTRL0		  <= {R_I_CTRL0[0],I_CTRL0};
		R_I_CTRL1         <= {R_I_CTRL1[0],I_CTRL1};
		R_Q_M 			  <= W_Q_M;
	end
end

always @ (posedge I_PIXEL_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_I_PIXEL_DATA_1_NUM <= 4'd0;
	end
	else
	begin
		R_I_PIXEL_DATA_1_NUM <= I_PIXEL_DATA[0] + I_PIXEL_DATA[1] + I_PIXEL_DATA[2] + I_PIXEL_DATA[3] + 
								I_PIXEL_DATA[4] + I_PIXEL_DATA[5] + I_PIXEL_DATA[6] + I_PIXEL_DATA[7] ;
	end
end

assign W_JUDGE_CONDT1 = (R_I_PIXEL_DATA_1_NUM >4) | ((R_I_PIXEL_DATA_1_NUM == 4) & !R_I_PIXEL_DATA[0]); 

assign W_Q_M[0] = R_I_PIXEL_DATA[0];
assign W_Q_M[1] = W_JUDGE_CONDT1 ? ~(W_Q_M[0] ^ R_I_PIXEL_DATA[1]) : W_Q_M[0] ^ R_I_PIXEL_DATA[1];
assign W_Q_M[2] = W_JUDGE_CONDT1 ? ~(W_Q_M[1] ^ R_I_PIXEL_DATA[2]) : W_Q_M[1] ^ R_I_PIXEL_DATA[2];
assign W_Q_M[3] = W_JUDGE_CONDT1 ? ~(W_Q_M[2] ^ R_I_PIXEL_DATA[3]) : W_Q_M[2] ^ R_I_PIXEL_DATA[3];
assign W_Q_M[4] = W_JUDGE_CONDT1 ? ~(W_Q_M[3] ^ R_I_PIXEL_DATA[4]) : W_Q_M[3] ^ R_I_PIXEL_DATA[4];
assign W_Q_M[5] = W_JUDGE_CONDT1 ? ~(W_Q_M[4] ^ R_I_PIXEL_DATA[5]) : W_Q_M[4] ^ R_I_PIXEL_DATA[5];
assign W_Q_M[6] = W_JUDGE_CONDT1 ? ~(W_Q_M[5] ^ R_I_PIXEL_DATA[6]) : W_Q_M[5] ^ R_I_PIXEL_DATA[6];
assign W_Q_M[7] = W_JUDGE_CONDT1 ? ~(W_Q_M[6] ^ R_I_PIXEL_DATA[7]) : W_Q_M[6] ^ R_I_PIXEL_DATA[7];
assign W_Q_M[8] = W_JUDGE_CONDT1 ? 1'b0:1'b1;

assign W_JUDGE_CONDT2 = R_I_DATA_EN[1];

always @ (posedge I_PIXEL_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_Q_M_1_NUM <= 4'd0;
		R_Q_M_0_NUM <= 4'd0;
	end
	else
	begin
		R_Q_M_1_NUM <= W_Q_M[0] + W_Q_M[1] + W_Q_M[2] + W_Q_M[3] + 
					   W_Q_M[4] + W_Q_M[5] + W_Q_M[6] + W_Q_M[7] ;
		R_Q_M_0_NUM <= !W_Q_M[0] + !W_Q_M[1] + !W_Q_M[2] + !W_Q_M[3] + 
					   !W_Q_M[4] + !W_Q_M[5] + !W_Q_M[6] + !W_Q_M[7] ;
	end
end

assign W_JUDGE_CONDT3 = (R_CNT == 5'd0) | (R_Q_M_0_NUM == R_Q_M_1_NUM);
assign W_JUDGE_CONDT4 = (!R_CNT[4] & (R_Q_M_1_NUM > R_Q_M_0_NUM)) | (R_CNT[4] & (R_Q_M_0_NUM > R_Q_M_1_NUM));

always @ (posedge I_PIXEL_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_CNT <= 5'd0;
		O_ENCODE_DATA <= 10'd0;
	end
	else if(W_JUDGE_CONDT2)
	begin
		if(W_JUDGE_CONDT3)
		begin
			O_ENCODE_DATA[7:0] <=  R_Q_M[8] ? R_Q_M[7:0] : ~R_Q_M[7:0];
			O_ENCODE_DATA[8]   <=  R_Q_M[8];
			O_ENCODE_DATA[9]   <= ~R_Q_M[8];
			R_CNT			   <=  R_Q_M[8] ? (R_CNT + R_Q_M_1_NUM - R_Q_M_0_NUM) : (R_CNT + R_Q_M_0_NUM - R_Q_M_1_NUM);
		end
		else
		begin
			if(W_JUDGE_CONDT4)
			begin
				O_ENCODE_DATA[7:0] <= ~R_Q_M[7:0];
				O_ENCODE_DATA[8]   <= R_Q_M[8];
				O_ENCODE_DATA[9]   <= 1'b1;
				R_CNT              <= R_CNT + {R_Q_M[8],1'b0} + R_Q_M_0_NUM - R_Q_M_1_NUM;
			end
			else
			begin
				O_ENCODE_DATA[7:0] <= R_Q_M[7:0];
				O_ENCODE_DATA[8]   <= R_Q_M[8];
				O_ENCODE_DATA[9]   <= 1'b0;
				R_CNT              <= R_CNT - {~R_Q_M[8],1'b0} + R_Q_M_1_NUM - R_Q_M_0_NUM;
			end
		end
	end
	else
	begin
		R_CNT <= 5'd0;
		case({R_I_CTRL1[1],R_I_CTRL0[1]})
			2'b00:
			begin
				O_ENCODE_DATA <= LP_CTRL0;
			end
			2'b01:
			begin
				O_ENCODE_DATA <= LP_CTRL1;
			end
			2'b10:
			begin
				O_ENCODE_DATA <= LP_CTRL2;
			end
			2'b11:
			begin
				O_ENCODE_DATA <= LP_CTRL3;
			end
			default:
			begin
				O_ENCODE_DATA <= LP_CTRL0;
			end
		endcase
	end
end
endmodule

 HDMI差分数据串行

实现方法

每个像素时钟到来时,给出10bit的编码数据,串行发送时,需要用 5倍 于像素数据时钟的时钟频率分别在时钟的双沿将数据逐比特发出。

双沿数据发送使用 ODDR 原语(相同边沿 模式),差分转换使用 OBUFDS 原语。

源码

// | ===================================================---------------------------===================================================
// | ---------------------------------------------------    HDMI 数据发送模块	   ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-12-21
// | 完成时间 : 2022-12-21
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 仅包含视频数据发送(无音频)
// |			-2- 1280 * 720 分辨率
// | 			-3- 
// |
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:


module HDMI_DATA_TX_MDL(
// | ==================================== 模块输入输出端口声明 ==================================== 
input 												   I_CLK_74M25  ,
input												   	I_CLK_371M25 ,

input 													I_SYS_RSTN   ,

input 													I_PIXEL_DATA_EN,
input 				[7:0]								I_PIXEL_DATA_R, 
input 				[7:0]								I_PIXEL_DATA_G,
input 				[7:0]								I_PIXEL_DATA_B,

input 													I_HSYNC,
input													   I_VSYNC,

output 				[2:0]								O_TMDS_DATA_P,
output 				[2:0]								O_TMDS_DATA_N,

output 													O_TMDS_CLK_P,
output 													O_TMDS_CLK_N


    );
// | ====================================   模块内部信号声明   ====================================

wire 				[9:0]								W_ENCODE_DATA_10BIT[2:0];
wire 				[3:0]								W_ODDR_Q;
// 数据分配
wire 				[4:0]								W_TMDS_CH0_D1;
wire 				[4:0]								W_TMDS_CH0_D2;

wire 				[4:0]								W_TMDS_CH1_D1;
wire 				[4:0]								W_TMDS_CH1_D2;

wire 				[4:0]								W_TMDS_CH2_D1;
wire 				[4:0]								W_TMDS_CH2_D2;

wire 				[4:0]								W_TMDS_CH3_D1;
wire 				[4:0]								W_TMDS_CH3_D2;
// 移位寄存
reg 				[4:0]								R_TMDS_CH0_D1;
reg 				[4:0]								R_TMDS_CH0_D2;

reg 				[4:0]								R_TMDS_CH1_D1;
reg 				[4:0]								R_TMDS_CH1_D2;

reg 				[4:0]								R_TMDS_CH2_D1;
reg 				[4:0]								R_TMDS_CH2_D2;

reg 				[4:0]								R_TMDS_CH3_D1;
reg 				[4:0]								R_TMDS_CH3_D2;

// 计数
reg 				[2:0]								R_CNT ;

// | ====================================   模块内部逻辑设计   ====================================

assign 				W_TMDS_CH0_D1			=	{W_ENCODE_DATA_10BIT[0][8],W_ENCODE_DATA_10BIT[0][6],W_ENCODE_DATA_10BIT[0][4],W_ENCODE_DATA_10BIT[0][2],W_ENCODE_DATA_10BIT[0][0]};
assign 				W_TMDS_CH0_D2			=	{W_ENCODE_DATA_10BIT[0][9],W_ENCODE_DATA_10BIT[0][7],W_ENCODE_DATA_10BIT[0][5],W_ENCODE_DATA_10BIT[0][3],W_ENCODE_DATA_10BIT[0][1]};

assign 				W_TMDS_CH1_D1			=	{W_ENCODE_DATA_10BIT[1][8],W_ENCODE_DATA_10BIT[1][6],W_ENCODE_DATA_10BIT[1][4],W_ENCODE_DATA_10BIT[1][2],W_ENCODE_DATA_10BIT[1][0]};
assign 				W_TMDS_CH1_D2			=	{W_ENCODE_DATA_10BIT[1][9],W_ENCODE_DATA_10BIT[1][7],W_ENCODE_DATA_10BIT[1][5],W_ENCODE_DATA_10BIT[1][3],W_ENCODE_DATA_10BIT[1][1]};

assign 				W_TMDS_CH2_D1			=	{W_ENCODE_DATA_10BIT[2][8],W_ENCODE_DATA_10BIT[2][6],W_ENCODE_DATA_10BIT[2][4],W_ENCODE_DATA_10BIT[2][2],W_ENCODE_DATA_10BIT[2][0]};
assign 				W_TMDS_CH2_D2			=	{W_ENCODE_DATA_10BIT[2][9],W_ENCODE_DATA_10BIT[2][7],W_ENCODE_DATA_10BIT[2][5],W_ENCODE_DATA_10BIT[2][3],W_ENCODE_DATA_10BIT[2][1]};

assign 				W_TMDS_CH3_D1			=	{1'b1,1'b1,1'b0,1'b0,1'b0};
assign 				W_TMDS_CH3_D2			=	{1'b1,1'b1,1'b1,1'b0,1'b0};

always @ (posedge I_CLK_371M25)
begin
   if(~I_SYS_RSTN)
   begin
      R_TMDS_CH0_D1  <=  5'd0;
      R_TMDS_CH0_D2  <=  5'd0;
      R_TMDS_CH1_D1  <=  5'd0;
      R_TMDS_CH1_D2  <=  5'd0;
      R_TMDS_CH2_D1  <=  5'd0;
      R_TMDS_CH2_D2  <=  5'd0;
      R_TMDS_CH3_D1  <=  5'd0;
      R_TMDS_CH3_D2  <=  5'd0;
      R_CNT          <=  3'd0;
   end
   else
   begin
	  R_CNT		    <= R_CNT[2] ? 3'd0 : R_CNT + 3'd1;
	  R_TMDS_CH0_D1 <= R_CNT[2] ? W_TMDS_CH0_D1 : {1'b0,R_TMDS_CH0_D1[4:1]};
	  R_TMDS_CH0_D2 <= R_CNT[2] ? W_TMDS_CH0_D2 : {1'b0,R_TMDS_CH0_D2[4:1]};
	  R_TMDS_CH1_D1 <= R_CNT[2] ? W_TMDS_CH1_D1 : {1'b0,R_TMDS_CH1_D1[4:1]};
	  R_TMDS_CH1_D2 <= R_CNT[2] ? W_TMDS_CH1_D2 : {1'b0,R_TMDS_CH1_D2[4:1]};
	  R_TMDS_CH2_D1 <= R_CNT[2] ? W_TMDS_CH2_D1 : {1'b0,R_TMDS_CH2_D1[4:1]};
	  R_TMDS_CH2_D2 <= R_CNT[2] ? W_TMDS_CH2_D2 : {1'b0,R_TMDS_CH2_D2[4:1]};
	  R_TMDS_CH3_D1 <= R_CNT[2] ? W_TMDS_CH3_D1 : {1'b0,R_TMDS_CH3_D1[4:1]};
	  R_TMDS_CH3_D2 <= R_CNT[2] ? W_TMDS_CH3_D2 : {1'b0,R_TMDS_CH3_D2[4:1]};
   end
end

// | ====================================   模块内部模块例化   ====================================
// | TMDS 编码模块
	TMDS_ENCODE_MDL INST_TMDS_ENCODE_MDL_R
		(
			.I_PIXEL_CLK   (I_CLK_74M25),
			.I_SYS_RSTN    (I_SYS_RSTN),
			.I_DATA_EN     (I_PIXEL_DATA_EN),
			.I_PIXEL_DATA  (I_PIXEL_DATA_R),
			.I_CTRL0       (1'b0),
			.I_CTRL1       (1'b0),
			.O_ENCODE_DATA (W_ENCODE_DATA_10BIT[2])
		);
	TMDS_ENCODE_MDL INST_TMDS_ENCODE_MDL_G
		(
			.I_PIXEL_CLK   (I_CLK_74M25),
			.I_SYS_RSTN    (I_SYS_RSTN),
			.I_DATA_EN     (I_PIXEL_DATA_EN),
			.I_PIXEL_DATA  (I_PIXEL_DATA_G),
			.I_CTRL0       (1'b0),
			.I_CTRL1       (1'b0),
			.O_ENCODE_DATA (W_ENCODE_DATA_10BIT[1])
		);
	TMDS_ENCODE_MDL INST_TMDS_ENCODE_MDL_B
		(
			.I_PIXEL_CLK   (I_CLK_74M25),
			.I_SYS_RSTN    (I_SYS_RSTN),
			.I_DATA_EN     (I_PIXEL_DATA_EN),
			.I_PIXEL_DATA  (I_PIXEL_DATA_B),
			.I_CTRL0       (I_HSYNC),
			.I_CTRL1       (I_VSYNC),
			.O_ENCODE_DATA (W_ENCODE_DATA_10BIT[0])
		);
// | ODDR OBUFDS 原语例化
// CH0
   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT        (1'b0       ),  // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE      ("SYNC"     )   // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_CH0 (
      .Q  (W_ODDR_Q[0]      ),     // 1-bit DDR output
      .C  (I_CLK_371M25     ),     // 1-bit clock input
      .CE (1'b1             ),     // 1-bit clock enable input
      .D1 (R_TMDS_CH0_D1[0] ),     // 1-bit data input (positive edge)
      .D2 (R_TMDS_CH0_D2[0] ),     // 1-bit data input (negative edge)
      .R  (1'b0             ),     // 1-bit reset
      .S  (1'b0             )      // 1-bit set
   );
   OBUFDS #(
      .IOSTANDARD("DEFAULT"),      // Specify the output I/O standard
      .SLEW      ("SLOW"   )       // Specify the output slew rate
   ) OBUFDS_CH0 (
      .O  (O_TMDS_DATA_P[0]),      // Diff_p output (connect directly to top-level port)
      .OB (O_TMDS_DATA_N[0]),      // Diff_n output (connect directly to top-level port)
      .I  (W_ODDR_Q[0]     )       // Buffer input
   );

// CH1
   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT        (1'b0       ),  // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE      ("SYNC"     )   // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_CH1 (
      .Q  (W_ODDR_Q[1]      ),     // 1-bit DDR output
      .C  (I_CLK_371M25     ),     // 1-bit clock input
      .CE (1'b1             ),     // 1-bit clock enable input
      .D1 (R_TMDS_CH1_D1[0] ),     // 1-bit data input (positive edge)
      .D2 (R_TMDS_CH1_D2[0] ),     // 1-bit data input (negative edge)
      .R  (1'b0             ),     // 1-bit reset
      .S  (1'b0             )      // 1-bit set
   );
   OBUFDS #(
      .IOSTANDARD("DEFAULT"),      // Specify the output I/O standard
      .SLEW      ("SLOW"   )       // Specify the output slew rate
   ) OBUFDS_CH1 (
      .O  (O_TMDS_DATA_P[1]),      // Diff_p output (connect directly to top-level port)
      .OB (O_TMDS_DATA_N[1]),      // Diff_n output (connect directly to top-level port)
      .I  (W_ODDR_Q[1]     )       // Buffer input
   );

// CH2
   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT        (1'b0       ),  // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE      ("SYNC"     )   // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_CH2 (
      .Q  (W_ODDR_Q[2]      ),     // 1-bit DDR output
      .C  (I_CLK_371M25     ),     // 1-bit clock input
      .CE (1'b1             ),     // 1-bit clock enable input
      .D1 (R_TMDS_CH2_D1[0] ),     // 1-bit data input (positive edge)
      .D2 (R_TMDS_CH2_D2[0] ),     // 1-bit data input (negative edge)
      .R  (1'b0             ),     // 1-bit reset
      .S  (1'b0             )      // 1-bit set
   );
   OBUFDS #(
      .IOSTANDARD("DEFAULT"),      // Specify the output I/O standard
      .SLEW      ("SLOW"   )       // Specify the output slew rate
   ) OBUFDS_CH2 (
      .O  (O_TMDS_DATA_P[2]),      // Diff_p output (connect directly to top-level port)
      .OB (O_TMDS_DATA_N[2]),      // Diff_n output (connect directly to top-level port)
      .I  (W_ODDR_Q[2]     )       // Buffer input
   );

// CH3
   ODDR #(
      .DDR_CLK_EDGE("SAME_EDGE"),  // "OPPOSITE_EDGE" or "SAME_EDGE" 
      .INIT        (1'b0       ),  // Initial value of Q: 1'b0 or 1'b1
      .SRTYPE      ("SYNC"     )   // Set/Reset type: "SYNC" or "ASYNC" 
   ) ODDR_CH3 (
      .Q  (W_ODDR_Q[3]      ),     // 1-bit DDR output
      .C  (I_CLK_371M25     ),     // 1-bit clock input
      .CE (1'b1             ),     // 1-bit clock enable input
      .D1 (R_TMDS_CH3_D1[0] ),     // 1-bit data input (positive edge)
      .D2 (R_TMDS_CH3_D2[0] ),     // 1-bit data input (negative edge)
      .R  (1'b0             ),     // 1-bit reset
      .S  (1'b0             )      // 1-bit set
   );
   OBUFDS #(
      .IOSTANDARD("DEFAULT"),      // Specify the output I/O standard
      .SLEW      ("SLOW"   )       // Specify the output slew rate
   ) OBUFDS_CH3 (
      .O  (O_TMDS_CLK_P),          // Diff_p output (connect directly to top-level port)
      .OB (O_TMDS_CLK_N),          // Diff_n output (connect directly to top-level port)
      .I  (W_ODDR_Q[3] )           // Buffer input
   );
endmodule

 

HDMI显示方法

思路

共有两种演示模式,由拨码开关来切换。

开关为 1:彩条轮播;

开关为 0:显示图片;

图片为:(忽略水印)

图片尺寸大小:160*277 (由于FPGA的ROM资源有限,此处显示小图片)

ROM配置 : 位宽 24位,深度 160*277

像素时钟:74.25MHz

串行发送时钟:371.25MHz

分辨率:1280*720@60Hz

实现

工程结构

源代码分享

测试顶层:

// | ===================================================---------------------------===================================================
// | --------------------------------------------------- HDMI 数据发送测试顶层模块 ---------------------------------------------------
// | ===================================================---------------------------===================================================
// | 创建时间 : 2022-12-22
// | 完成时间 : 2022-12-22
// | 作    者 :Xu Y. B.(CSDN 用户名:在路上,正出发)
// | 功能说明 :
// |			-1- 仅包含视频数据发送(无音频)
// |			-2- 1280 * 720 分辨率
// | 			-3- 
// |
// |
// | ================================= 		模块修改历史纪录 	  =================================
// | 修改日期:
// | 修改作者:
// | 修改注解:

// Resolution_640x480    //时钟为25.175MHz
// Resolution_800x480    //时钟为33MHz,可兼容TFT5.0
// Resolution_800x600    //时钟为40MHz
// Resolution_1024x600   //时钟为51MHz
// Resolution_1024x768   //时钟为65MHz
// Resolution_1280x720   //时钟为74.25MHz
// Resolution_1920x1080  //时钟为148.5MHz

// 宏定义
`define DEF_H_Total_Time    12'd1650
`define DEF_H_Right_Border  12'd0
`define DEF_H_Front_Porch   12'd110
`define DEF_H_Sync_Time     12'd40
`define DEF_H_Back_Porch    12'd220
`define DEF_H_Left_Border   12'd0

`define DEF_V_Total_Time    12'd750
`define DEF_V_Bottom_Border 12'd0
`define DEF_V_Front_Porch   12'd5
`define DEF_V_Sync_Time     12'd5
`define DEF_V_Back_Porch    12'd20
`define DEF_V_Top_Border    12'd0


module HDMI_DISP_TEST_MDL(
// | ==================================== 模块输入输出端口声明 ==================================== 
input 												   	I_SYS_CLK  ,
input												   	I_SYS_RSTN ,

input 													I_DISP_SEL,

output 													O_HDMI_EN,
output 				[2:0]								O_TMDS_DATA_P,
output 				[2:0]								O_TMDS_DATA_N,
output 													O_TMDS_CLK_P,
output 													O_TMDS_CLK_N

    );

// | ====================================   模块内部参数声明   ====================================
localparam 			LP_DISP_WIDTH			=			1280;
localparam 			LP_DISP_HEIGHT          =			720;

//颜色编码
localparam 			LP_BLACK    			= 			24'h000000; //黑色
localparam 			LP_BLUE     			= 			24'h0000FF; //蓝色
localparam 			LP_RED      			= 			24'hFF0000; //红色
localparam 			LP_PURPPLE  			= 			24'hFF00FF; //紫色
localparam 			LP_GREEN    			= 			24'h00FF00; //绿色
localparam 			LP_CYAN     			= 			24'h00FFFF; //青色
localparam 			LP_YELLOW   			= 			24'hFFFF00; //黄色
localparam 			LP_WHITE    			= 			24'hFFFFFF; //白色
    
localparam 			LP_H_DATA_BEGIN   		=			`DEF_H_Sync_Time  + `DEF_H_Back_Porch    + `DEF_H_Left_Border - 1'b1;
localparam 			LP_H_DATA_END     		=			`DEF_H_Total_Time - `DEF_H_Right_Border  - `DEF_H_Front_Porch - 1'b1;
localparam 			LP_V_DATA_BEGIN   		=			`DEF_V_Sync_Time  + `DEF_V_Back_Porch    + `DEF_V_Top_Border  - 1'b1;
localparam 			LP_V_DATA_END     		=			`DEF_V_Total_Time - `DEF_V_Bottom_Border - `DEF_V_Front_Porch - 1'b1;


// | ====================================   模块内部信号声明   ====================================
wire 													W_CLK_100M;
wire													W_CLK_74M25;
wire 													W_CLK_371M25;

wire 													W_MMCM_LOCKED1;
wire													W_MMCM_LOCKED2;

wire 				[11:0]								W_H_ADDR;
wire 				[11:0]								W_V_ADDR;
reg 				[11:0]								R_H_SCAN_CNT;
reg 				[11:0]								R_V_SCAN_CNT;
wire 													W_H_CNT_OVER;
wire 													W_V_CNT_OVER;
reg 													R_PIXEL_DATA_REQ;
reg 				[23:0]								R_PIXEL_DATA;
reg 													R_H_SYNC;
reg 													R_V_SYNC;
reg 				[7:0]								R_PIXEL_DATA_R;
reg 				[7:0]								R_PIXEL_DATA_G;
reg 				[7:0]								R_PIXEL_DATA_B;


wire 													W_R0_FLAG;//第 0 行标志位 
wire 													W_R1_FLAG;//第 1 行标志位 
wire 													W_R2_FLAG;//第 2 行标志位 
wire 													W_R3_FLAG;//第 3 行标志位

wire 													W_C0_FLAG;//第 0 列标志位
wire 													W_C1_FLAG;//第 1 列标志位
wire 													W_C2_FLAG;//第 0 列标志位
wire 													W_C3_FLAG;//第 1 列标志位

reg 				[8*24-1:0]							R_COLOR;
reg 				[24:0]								R_CNT_25M;
wire 													W_PULSE;

// ROM
wire 				[15:0]								W_ROM_ADDR;
wire 				[23:0]								W_ROM_DATA;

// | ====================================   模块内部逻辑设计   ====================================
// 行标志
assign 		W_R0_FLAG 		 = (W_V_ADDR >= 0                 ) && (W_V_ADDR < LP_DISP_HEIGHT/4  );   
assign 		W_R1_FLAG 		 = (W_V_ADDR >= LP_DISP_HEIGHT/4  ) && (W_V_ADDR < LP_DISP_HEIGHT/2  );   
assign 		W_R2_FLAG 		 = (W_V_ADDR >= LP_DISP_HEIGHT/2  ) && (W_V_ADDR < LP_DISP_HEIGHT/4*3);   
assign 		W_R3_FLAG 		 = (W_V_ADDR >= LP_DISP_HEIGHT/4*3) && (W_V_ADDR < LP_DISP_HEIGHT    );   
// 列标志
assign 		W_C0_FLAG 		 = (W_H_ADDR >= 0                 ) && (W_H_ADDR < LP_DISP_WIDTH/4   );   
assign 		W_C1_FLAG 		 = (W_H_ADDR >= LP_DISP_WIDTH/4   ) && (W_H_ADDR < LP_DISP_WIDTH/2   );  
assign 		W_C2_FLAG 		 = (W_H_ADDR >= LP_DISP_WIDTH/2   ) && (W_H_ADDR < LP_DISP_WIDTH/4*3 );   
assign 		W_C3_FLAG 		 = (W_H_ADDR >= LP_DISP_WIDTH/4*3 ) && (W_H_ADDR < LP_DISP_WIDTH     ); 

always @ (posedge I_SYS_CLK)
begin
	if(~I_SYS_RSTN)
	begin
		R_CNT_25M <= 25'd0;
		R_COLOR   <= {LP_BLACK,LP_BLUE,LP_RED,LP_PURPPLE,LP_GREEN,LP_CYAN,LP_YELLOW,LP_WHITE};
	end
	else
	begin
		if(R_CNT_25M == 25'd25_000_000)
		begin
			R_CNT_25M <= 25'd0;
		end
		else
		begin
			R_CNT_25M <= R_CNT_25M + 1;
		end

		if(W_PULSE)
		begin
			R_COLOR <= {R_COLOR[0+:7*24],R_COLOR[(8*24-1)-:24]};
		end
		else
		begin
			R_COLOR <= R_COLOR;
		end
	end
end

assign W_PULSE = (R_CNT_25M == 25'd25_000_000);
// 像素数据
always@(*)
begin
	if(~I_SYS_RSTN)
	begin
		R_PIXEL_DATA = 24'd0;
	end
	else if(R_PIXEL_DATA_REQ)
	begin
		if(I_DISP_SEL)
		begin
			case({W_R0_FLAG,W_R1_FLAG,W_R2_FLAG,W_R3_FLAG})
				4'b1000:
				begin
					R_PIXEL_DATA = W_C0_FLAG ? R_COLOR[4*24+:24] : 
								   W_C1_FLAG ? R_COLOR[0*24+:24] : 
								   W_C2_FLAG ? R_COLOR[0*24+:24] : 
								   W_C3_FLAG ? R_COLOR[4*24+:24] :  R_COLOR[0*24+:24];
				end
				4'b0100:
				begin
					R_PIXEL_DATA = W_C0_FLAG ? R_COLOR[0*24+:24] : 
								   W_C1_FLAG ? R_COLOR[7*24+:24] : 
								   W_C2_FLAG ? R_COLOR[7*24+:24] : 
								   W_C3_FLAG ? R_COLOR[0*24+:24] :  R_COLOR[0*24+:24];
	
				end
				4'b0010:
				begin
					R_PIXEL_DATA = W_C0_FLAG ? R_COLOR[0*24+:24] : 
								   W_C1_FLAG ? R_COLOR[7*24+:24] : 
								   W_C2_FLAG ? R_COLOR[7*24+:24] : 
								   W_C3_FLAG ? R_COLOR[0*24+:24] :  R_COLOR[0*24+:24];
	
				end
				4'b0001:
				begin
					R_PIXEL_DATA = W_C0_FLAG ? R_COLOR[4*24+:24] : 
								   W_C1_FLAG ? R_COLOR[0*24+:24] : 
								   W_C2_FLAG ? R_COLOR[0*24+:24] : 
								   W_C3_FLAG ? R_COLOR[4*24+:24] :  R_COLOR[0*24+:24];
	
				end
				default:
				begin
					R_PIXEL_DATA = 24'hFFFFFF;
				end
			endcase
		end
		else
		begin
			if((W_H_ADDR >= 12'd499) && (W_H_ADDR <= 12'd776) && (W_V_ADDR >= 12'd279) && (W_V_ADDR <= 12'd439))
			begin
				R_PIXEL_DATA = W_ROM_DATA;
			end
			else
			begin
				R_PIXEL_DATA = 24'hFFFFFF;
			end
		end
	end
	else
	begin
		R_PIXEL_DATA = 24'hFFFFFF;
	end
end

assign W_ROM_ADDR = ((W_H_ADDR >= 12'd499) && (W_H_ADDR <= 12'd776) && (W_V_ADDR >= 12'd279) && (W_V_ADDR <= 12'd439)) ?
					((W_H_ADDR-12'd499) * 160 + (W_V_ADDR - 12'd279)) : 16'd0;
// 行扫描
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_H_SCAN_CNT <= 12'd0;
	end
	else if(W_H_CNT_OVER)
	begin
		R_H_SCAN_CNT <= 12'd0;
	end
	else
	begin
		R_H_SCAN_CNT <= R_H_SCAN_CNT + 1;
	end

end

assign W_H_CNT_OVER = (R_H_SCAN_CNT >= (`DEF_H_Total_Time - 1));

// 场扫描
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_V_SCAN_CNT <= 12'd0;
	end
	else if(W_H_CNT_OVER)
	begin
		if(W_V_CNT_OVER)
		begin
			R_V_SCAN_CNT <= 12'd0;
		end
		else
		begin
			R_V_SCAN_CNT <= R_V_SCAN_CNT + 1;
		end
	end
	else
	begin
		R_V_SCAN_CNT <= R_V_SCAN_CNT ;
	end

end

assign W_V_CNT_OVER = (R_V_SCAN_CNT >= (`DEF_V_Total_Time - 1));

// 行同步
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_H_SYNC <= 1'b0;
	end
	else
	begin
		R_H_SYNC <= (R_H_SCAN_CNT > (`DEF_H_Sync_Time - 1));
	end 
end
// 场同步
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_V_SYNC <= 1'b0;
	end
	else
	begin
		R_V_SYNC <= (R_V_SCAN_CNT > (`DEF_V_Sync_Time - 1));
	end 
end
// RGB 数据
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_PIXEL_DATA_R <= 8'd0;
		R_PIXEL_DATA_G <= 8'd0;
		R_PIXEL_DATA_B <= 8'd0;
	end
	else if(R_PIXEL_DATA_REQ)
	begin
		R_PIXEL_DATA_R <= R_PIXEL_DATA[16+:8];
		R_PIXEL_DATA_G <= R_PIXEL_DATA[8+:8];
		R_PIXEL_DATA_B <= R_PIXEL_DATA[0+:8];
	end 
	else
	begin
		R_PIXEL_DATA_R <= 8'd0;
		R_PIXEL_DATA_G <= 8'd0;
		R_PIXEL_DATA_B <= 8'd0;		
	end
end
// 数据使能
always @ (posedge W_CLK_74M25)
begin
	if(~W_MMCM_LOCKED2)
	begin
		R_PIXEL_DATA_REQ <= 1'b0;
	end
	else
	begin
		R_PIXEL_DATA_REQ <= (R_H_SCAN_CNT >= LP_H_DATA_BEGIN) && (R_H_SCAN_CNT < LP_H_DATA_END)&&
							(R_V_SCAN_CNT >= LP_V_DATA_BEGIN) && (R_V_SCAN_CNT < LP_V_DATA_END);
	end 
end

// 行 场 地址
assign W_H_ADDR = R_PIXEL_DATA_REQ ? (R_H_SCAN_CNT - LP_H_DATA_BEGIN) : 12'd0;
assign W_V_ADDR = R_PIXEL_DATA_REQ ? (R_V_SCAN_CNT - LP_V_DATA_BEGIN) : 12'd0;

assign O_HDMI_EN = 1'b1;

// | ====================================   模块内部模块例化   ====================================
// | 时钟 IP例化
  MMCM_HDMI INST_MMCM_HDMI
   (
    // Clock out ports
    .O_CLK_74M25(W_CLK_74M25),     // output O_CLK_74M25
    .O_CLK_371M25(W_CLK_371M25),     // output O_CLK_371M25
    // Status and control signals
    .reset(!I_SYS_RSTN ), // input reset
    .locked(W_MMCM_LOCKED2),       // output locked
   // Clock in ports
    .I_CLK_50M(I_SYS_CLK));      // input I_CLK_100M

// | HDMI 数据发送模块例化
	HDMI_DATA_TX_MDL INST_HDMI_DATA_TX_MDL
		(
			.I_CLK_74M25     (W_CLK_74M25),
			.I_CLK_371M25    (W_CLK_371M25),
			.I_SYS_RSTN      (W_MMCM_LOCKED2),
			.I_PIXEL_DATA_EN (R_PIXEL_DATA_REQ),
			.I_PIXEL_DATA_R  (R_PIXEL_DATA_R),
			.I_PIXEL_DATA_G  (R_PIXEL_DATA_G),
			.I_PIXEL_DATA_B  (R_PIXEL_DATA_B),
			.I_HSYNC         (R_H_SYNC),
			.I_VSYNC         (R_V_SYNC),
			.O_TMDS_DATA_P   (O_TMDS_DATA_P),
			.O_TMDS_DATA_N   (O_TMDS_DATA_N),
			.O_TMDS_CLK_P    (O_TMDS_CLK_P),
			.O_TMDS_CLK_N    (O_TMDS_CLK_N)
		);
// ROM
ROM_RGB_DATA INST_ROM_RGB_DATA (
  .clka(W_CLK_74M25),    // input wire clka
  .ena(1'b1),      // input wire ena
  .addra(W_ROM_ADDR),  // input wire [15 : 0] addra
  .douta(W_ROM_DATA)  // output wire [23 : 0] douta
);
endmodule

ROM 初始化文件 .coe 生成 MATLAB源码 

%% -------- 1280 * 720 像素数据提取 存入 .coe文件 --------
% 作    者:Xu Y. B.(CSDN 用户名:在路上,正出发)
% 创建日期:2022-12-22
% 完成日期:2022-12-22


%% 准备
clc;
clearvars;
close all;

%% 图片读取
File_Path = "D:\VIVADO_WORK_SPACE\XC7A35T_DESIGN\Figure\";
Figure4_Name = "Figure4.png";

Figure_Data = imread(strcat(File_Path,Figure4_Name));

imshow(Figure_Data(:,:,:))

DATA_R = uint32(reshape(Figure_Data(:,:,1),[],1));
DATA_G = uint32(reshape(Figure_Data(:,:,2),[],1));
DATA_B = uint32(reshape(Figure_Data(:,:,3),[],1));

DATA_COE = uint32(DATA_R * 256^2 + DATA_G * 256 + DATA_B);

str='D:\VIVADO_WORK_SPACE\XC7A35T_DESIGN\COE_FILE\FIGURE_DATA.coe';%该字符串为文件的路径
fid_coe=fopen(str,'w+');%打开文件获得ID
fprintf(fid_coe,'memory_initialization_radix=10;\n');%写入第一行
fprintf(fid_coe,'memory_initialization_vector=\n');%写入第二行
fprintf(fid_coe,'%d,\n',DATA_COE((1:end-1),1));%写入数据并以逗号隔开
fprintf(fid_coe,'%d;',DATA_COE(end,1));%写入最后一个数据以分号结束

板级调试视频

基于FPGA的TMDS编码以及HDMI驱动 演示视频icon-default.png?t=M85Bhttps://live.csdn.net/v/264920



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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【IE】信息抽取任务简述

1 信息抽取任务 信息抽取&#xff08;Information extraction&#xff0c;IE&#xff09;任务指从非结构化或半结构化的文本中抽取出结构化信息。根据被抽取的对象&#xff0c;信息抽取可以分为以下4个任务&#xff1a; &#xff08;1&#xff09; 实体抽取&#xff08;Entity…

单商户商城系统功能拆解51—应用中心—评价助手

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

用维度概念来定义初级、中级、高级程序员

网络上众说纷纭&#xff0c;大都站立在对某一技术的知识掌握量上来界定&#xff0c;或者有些人说着说着&#xff0c;发现无法自圆其说&#xff0c;然后就说这三种人就是一种叫法&#xff0c;你觉得你是高级你就高级了&#xff0c;从概念上讲&#xff0c;这三者之间必然有质的区…

Apache Karaf 存在远程代码执行漏洞

漏洞描述 Apache Karaf 是一个用于部署业务代码或应用程​​序的 modulith 运行时环境。 Apache Karaf 的受影响版本中由于 jaas.modules.src.main.java.porg.apache.karaf.jass.modules.jdbc.JDBCUtils#doCreateDatasourceuse 中的 lookup 方法没有对 jndiName 有效过滤从而…

疫情感染开始,大多居家办公

健康无价&#xff0c;有人卖掉了

docker 安装 mysql

一、下载安装MySQL镜像 sudo docker pull mysql:5.7 【注】docker pull mysql 如果不指定版本&#xff0c;默认安装最新版本。 sudo是linux系统管理指令&#xff0c;是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具。不想用sudo&#xff0c;使用命令su root&…

一款强大的免费开源的基于流量分析的扫描器结合不同场景的实际使用与漏-洞及木-马发现实践

一款强大的免费开源的基于流量分析的扫描器结合不同场景的实际使用与漏-洞及木-马发现实践。 关于安全领域内漏-洞的发现,技术手段非常多,工具也非常多,大致阶段可分为事前、事中、事后来处理。事前大多采用SDL、白盒扫描等;事中、事后有NIDS及漏-洞感知,甚至还有WAF来拦…

借力 StarRocks,“陆战之王“ 大润发如何在零售业数字化转型中抢占先机?

作者&#xff1a;大润发大数据团队 自 1998 年在上海开设第一家大型超市以来&#xff0c;大润发已在中国大陆地区成功开设近 500 家综合性大型超市&#xff0c;覆盖全国 29 个省市及自治区达 230 多个城市&#xff0c;年销售额过千亿。大润发优鲜、淘鲜达、饿了么、天猫超市线…

四、网络层(二)路由算法与路由选择协议

目录 2.1 静态路由与动态路由 2.2 层次路由与自治系统 2.3 距离-向量路由算法之路由信息协议&#xff08;RIP&#xff09; 2.3.1 RIP的基本特点 2.3.2 距离向量算法 2.4 链路状态路由算法之开放最短路径优先&#xff08;OSPF&#xff09;协议 2.4.1 OSPF协议的基本特点…

DELL Precison 7670 不能加载系统固态硬盘

xiaokcehui: 电脑无法开机 戴尔技术支持: 诸葛小戴检测到您这是台笔记本电脑&#xff0c;小戴会带着您做4个操作尝试帮您解决问题&#xff1a; 戴尔技术支持: [1/4] 请您参考小戴发给您的图片做一下重置RTC的操作 ✅RTC是集成电路&#xff0c;通常称为时钟芯片&#xff0c;如…

React基础知识(事件处理、受控组件与非受控组件、高阶函数、组件的生命周期)(三)

系列文章目录 第一章&#xff1a;React基础知识&#xff08;React基本使用、JSX语法、React模块化与组件化&#xff09;&#xff08;一&#xff09; 第二章&#xff1a;React基础知识&#xff08;组件实例三大核心属性state、props、refs&#xff09;&#xff08;二&#xff0…

使用 Pygame Zero 构建一个捕捉游戏(详细步骤含源码)

Pygame zero 是一个用于教育的工具,适合任何开始学习使用 Python 创建游戏的人。那么让我们从制作一个小的捕捉游戏开始吧:) 您可以使用 pip 安装 pygame 零,如图所示 pip install pgzero你好 Pygamezero! 要开始使用 pygamezero,请将以下代码复制到文件catching_game.py…

Word处理控件Aspose.Words功能演示:在 Java 中将 DOC 或 DOCX 转换为 JPG

Aspose.Words是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和打印文档&#xff0c;而无需在跨平台应用程序中直接使用Microsoft Word。此外&#xff0c; Aspose API支持流行文件格式处…

GEO芯片数据基本分析

GEO数据挖掘&#xff0c;表达芯片分析 举例&#xff1a;王同学近期拟通过生物信息学相关软件与数据库来探讨女性非抽烟者的非小细胞肺癌预后相关的显著性基因及潜在的治疗靶点&#xff0c;他在NCBI上查询到了1套芯片数据GSE19804。请帮助他完成该项目的设计与分析。 一、一般…

基于Redis实现登录

1.发送短信验证码 Overridepublic Result sendCode(String phone, HttpSession session) {//校验手机号if(RegexUtils.isPhoneInvalid(phone)){//如果不符合&#xff0c;返回错误信息。return Result.fail("手机号格式错误&#xff01;");}//生成验证码String code …

Codeforces Round #699 (Div. 2) C. Fence Painting

翻译&#xff1a; You finally woke up after this crazy dream and decided to walk around to clear your head. Outside you saw your houses fence — so plain and boring, that youd like to repaint it. You have a fence consisting of &#x1d45b;n planks, where …

网络实验之VTP协议

一、VTP协议简介 VLAN中继协议&#xff0c;VTP&#xff0c;VLAN TRUNKING PROTOCOL&#xff0c;是CISCO专用协议&#xff0c;大多数交换机都支持该协议。VTP负责在VTP域内同步VLAN信息&#xff0c;这样就不必在每个交换上配置相同的VLAN信息。如协议名称&#xff0c;VTP协议需要…

“世界上最鸽派”的央行转鹰,透露了什么信号?

​当地时间周二&#xff0c;日本中央银行结束货币政策会议后宣布&#xff0c;部分调整当前超宽松货币政策&#xff0c;将长期利率波动幅度由正负0.25%扩展至正负0.5%。这一“黑天鹅”令全球投资者感到大为震惊。长期以来&#xff0c;投资者将日本央行看作是最后一家尚未放弃其长…

【Linux】---文件基础I/O(上)

文章目录回顾C语言文件操作接口文件相关的系统调用接口打开和关闭文件文件的打开方式文件描述符文件描述符的分配规则write、read重定向dup2mysell回顾C语言文件操作接口 在C语言中对于文件的操作有着几个常用的接口可以调用 fopen//打开文件 fclose//关闭文件 fprintf//输出…

L1-070 吃火锅(分数 15)

以上图片来自微信朋友圈&#xff1a;这种天气你有什么破事打电话给我基本没用。但是如果你说“吃火锅”&#xff0c;那就厉害了&#xff0c;我们的故事就开始了。 本题要求你实现一个程序&#xff0c;自动检查你朋友给你发来的信息里有没有 chi1 huo3 guo1。 输入格式&#x…