HDMI之TMDS编码原理

 TMDS算法原理

TDMS算法原理图

 笔者将这个TDMS算法原理按编码顺序分成两个阶段:初步编码和最终编码

第一阶段:初步编码

初步编码就是生成9位编码值q_m,后续称之为初步编码值

本文结合野火FPGA教程的hdmi显示器驱动设计与验证进行讲解

第一个周期

输入data_in

第二个周期

首先获取data_in中1的个数

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
    data_in_n1 <= 4'd0;
else
    data_in_n1 <= data_in[0] + data_in[1] + data_in[2]+ data_in[3] + data_in[4] + data_in[5]+ data_in[6] + data_in[7];

 其次对输入数据进行打拍,为了给condition_1做判断

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
    data_in_reg <= 8'b0;
else
    data_in_reg <= data_in;

最后condition_1通过data_in_in1和data_in_reg[0]来判断是否为1 

assign condition_1 = ((data_in_n1 > 4'd4) || ((data_in_n1 == 4'd4)&& (data_in_reg[0] == 1'b1)));
ssign q_m[0] = data_in_reg[0];
assign q_m[1] = (condition_1) ? (q_m[0] ^~ data_in_reg[1]) : (q_m[0] ^ data_in_reg[1]);
assign q_m[2] = (condition_1) ? (q_m[1] ^~ data_in_reg[2]) : (q_m[1] ^ data_in_reg[2]);
assign q_m[3] = (condition_1) ? (q_m[2] ^~ data_in_reg[3]) : (q_m[2] ^ data_in_reg[3]);
assign q_m[4] = (condition_1) ? (q_m[3] ^~ data_in_reg[4]) : (q_m[3] ^ data_in_reg[4]);
assign q_m[5] = (condition_1) ? (q_m[4] ^~ data_in_reg[5]) : (q_m[4] ^ data_in_reg[5]);
assign q_m[6] = (condition_1) ? (q_m[5] ^~ data_in_reg[6]) : (q_m[5] ^ data_in_reg[6]);
assign q_m[7] = (condition_1) ? (q_m[6] ^~ data_in_reg[7]) : (q_m[6] ^ data_in_reg[7]);
assign q_m[8] = (condition_1) ? 1'b0 : 1'b1;

第三个周期

获取q_m中1和0的个数

always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
begin
    q_m_n1 <= 4'd0;
    q_m_n0 <= 4'd0;
end
else
begin
    q_m_n1<=q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];
    q_m_n0<=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]);
end

 对q_m进行打拍得到q_m_reg

//数据打拍,为了各数据同步
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
 begin
     de_reg1 <= 1'b0;
     de_reg2 <= 1'b0;
     c0_reg1 <= 1'b0;
     c0_reg2 <= 1'b0;
     c1_reg1 <= 1'b0;
     c1_reg2 <= 1'b0;
     q_m_reg <= 9'b0;
 end
 else
 begin
     de_reg1 <= de;
     de_reg2 <= de_reg1;
     c0_reg1 <= c0;
     c0_reg2 <= c0_reg1;
     c1_reg1 <= c1;
     c1_reg2 <= c1_reg1;
     q_m_reg <= q_m;
 end

第二阶段:最终编码

最终编码会将初步编码值编码成10位数的最终编码值

 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 begin
     data_out <= 10'b0;
     cnt <= 5'b0;
 end
 else
 begin
 if(de_reg2 == 1'b1)
 begin
 if(condition_2 == 1'b1)
 begin
     data_out[9] <= ~q_m_reg[8];//第10位和第9位相反,因此计数器判断第10和第9位的个数差值
     data_out[8] <= q_m_reg[8];
     data_out[7:0]<=(q_m_reg[8])?q_m_reg[7:0] : ~q_m_reg[7:0];
     cnt<=(~q_m_reg[8])?(cnt+q_m_n0-q_m_n1):(cnt+q_m_n1-q_m_n0);
 end
 else
 begin
 if(condition_3 == 1'b1)
 begin
     data_out[9] <= 1'b1;
     data_out[8] <= q_m_reg[8];
     data_out[7:0] <= ~q_m_reg[7:0];
     cnt<=cnt+{q_m_reg[8],1'b0}+(q_m_n0-q_m_n1);//假如第9位是1,那么cnt加2,假如第9位是0,则cnt加0,另外cnt-(q_m_n1-q_m_n0)=cnt+q_m_n0-q_m_n1,这是因为q_m_reg取反了
 end
 else
 begin
     data_out[9] <= 1'b0;
     data_out[8] <= q_m_reg[8];
     data_out[7:0] <= q_m_reg[7:0];
     cnt<= cnt-{~q_m_reg[8],1'b0}+(q_m_n1-q_m_n0);//已知第10位是0,假如第9位是1,那么cnt减0,假如第9位是0,则cnt减2
 end

 end
 end
 else
 begin
 case ({c1_reg2, c0_reg2})
     2'b00: data_out <= DATA_OUT0;
     2'b01: data_out <= DATA_OUT1;
     2'b10: data_out <= DATA_OUT2;
     default:data_out <= DATA_OUT3;
 endcase
 cnt <= 5'b0;
 end
 end

同时会有一个符号型计数器cnt来记录最终编码中1和0的差值;当1的个数多于0的个数时,cnt大于0,反之,cnt小于0.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值