fpga vga转hdmi 8位转十位 encoder模块

发布于:2024-12-18 ⋅ 阅读:(257) ⋅ 点赞:(0)

case语句写法 理解在这里插入图片描述

//为了完成 RGB 图像数据 8b 转 10b 的编码
//此为xilinx 官方提供的编码模块代码
// TMDS 通过逻辑算法将 8 位字符数据通过编码转换为 10 位字符数据,前 8 位数据由原始信号经运算后
// 获得,第 9 位表示运算的方式,1 表示异或 0 表示异或非。经过 DC 平衡后(第 10 位),采用差分信号传输
// 数据。第 10 位实际是一个反转标志位,1 表示进行了反转而 0 表示没有反转,从而达到 DC 平衡。
// D	D:输入视频像素信号
// C1 C0	C1,C0:控制信号
// DE	DE:使能信号
// Cnt	Cnt寄存上次编码过程中0的个数减1的个数
// N1{X}	输入视频像素信号中1的个数
// N0{X}	输入视频像素信号中0的个数
// q_out	编码输出信号

// 首先要判断输入的像素数据1的个数是否大于4或者输入像素等于4且最低位为0,即(N1{D}>4)|| (N1{D}==4 && D[0]==0)为真,
// 则执行右边的运算,如果上述条件为假,则执行左边的运算。q_m只是一个临时寄存器,用来寄存中间数据。
// 右边的运算是对输入的像素数据进行同或运算(将输入数据最低位寄存在q_m最低位,
// 然后q_m的低位与输入数据的下一位数据同或得到q_m当前位数据),并且第9比特q_m[8]赋值为0,左边的运算是对输入的像素数据进行异或运算,
// 并且第9比特q_m[8]赋值为1。第9位就是用来表示TMDS对输入数据采用异或还是同或运算的  
`timescale 1 ps / 1ps
 module dvi_encoder (
  input            clkin,    // 
  input            rstin,    // 
  input      [7:0] din,      // 
  input            c0,       // 行同步信号
  input            c1,       // 场同步信号
  input            de,       // 使能
  output reg [9:0] dout      // 
);
 reg [3:0] n1d; //number of 1s in din
 reg [7:0] din_q;
 //计算像素数据中“1”的个数
always @ (posedge clkin) begin
  n1d <=#1 din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + 
din[6] + din[7];
  din_q <=#1 din;
 end
 wire decision1; //1或者0  
 assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 
1'b0));
 wire [8:0] q_m;///先转换为9位
 assign q_m[0] = din_q[0];
 assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ 
din_q[1]);
 assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ 
din_q[2]);
 assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ 
din_q[3]);
assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ 
din_q[4]);
 assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ 
din_q[5]);
 assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ 
din_q[6]);
 assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ 
din_q[7]);
 assign q_m[8] = (decision1) ? 1'b0 : 1'b1;
 reg [3:0] n1q_m, n0q_m; 
always @ (posedge clkin) begin
  n1q_m  <=#1 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中1的数量
  n0q_m  <=#1 4'h8 - (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中0的数量
 end
 parameter CTRLTOKEN0 = 10'b1101010100;
 parameter CTRLTOKEN1 = 10'b0010101011;
 parameter CTRLTOKEN2 = 10'b0101010100;
 parameter CTRLTOKEN3 = 10'b1010101011;
 reg [4:0] cnt; 
wire decision2, decision3;
 assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m);
 assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > 
n1q_m));
 reg       de_q, de_reg;
 reg       c0_q, c1_q;
 reg       c0_reg, c1_reg;
 reg [8:0] q_m_reg;
 always @ (posedge clkin) begin //使能  场同步 行同步  q_m缓存
  de_q    <=#1 de;
  de_reg  <=#1 de_q;
  
  c0_q    <=#1 c0;
  c0_reg  <=#1 c0_q;
 c1_q    <=#1 c1;
  c1_reg  <=#1 c1_q;
  q_m_reg <=#1 q_m;
 end
 always @ (posedge clkin or posedge rstin) begin
  if(rstin) begin
    dout <= 10'h0;
    cnt <= 5'h0;
  end else begin
    if (de_reg) begin  //de使能
      if(decision2) begin
        dout[9]   <=#1 ~q_m_reg[8]; 
        dout[8]   <=#1 q_m_reg[8]; 
        dout[7:0] <=#1 (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0];
        cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + 
n1q_m - n0q_m);
      end else begin
        if(decision3) begin
          dout[9]   <=#1 1'b1;
          dout[8]   <=#1 q_m_reg[8];
          dout[7:0] <=#1 ~q_m_reg[7:0];
          cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m);
        end else begin
          dout[9]   <=#1 1'b0;
          dout[8]   <=#1 q_m_reg[8];
          dout[7:0] <=#1 q_m_reg[7:0];
          cnt <=#1 cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m);
        end
      end
    end else begin//de不使能
      case ({c1_reg, c0_reg})
        2'b00:   dout <=#1 CTRLTOKEN0;
        2'b01:   dout <=#1 CTRLTOKEN1;
        2'b10:   dout <=#1 CTRLTOKEN2;
        default: dout <=#1 CTRLTOKEN3;
      endcase
      cnt <=#1 5'h0;
    end
  end
 end
  
endmodule 

网站公告

今日签到

点亮在社区的每一天
去签到