【【RTC实时时钟实验 -- 在HDMI上显示-FPGA 小实验】】

这篇具有很好参考价值的文章主要介绍了【【RTC实时时钟实验 -- 在HDMI上显示-FPGA 小实验】】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

RTC实时时钟实验 – 在HDMI上显示

top.v

module RTS_TOP#(
    parameter   TIME_INIT   =   48'h24_01_06_11_08_00     ,
    parameter   WAIT_TIME   =   13'd8000                  ,
    parameter   SLAVE_ADDR  =   7'b1010001                , // E2PROM 浠庢満鍦板潃
    parameter   CLK_FREQ    =   26'd50_000_000            , // 50MHz 鐨勬椂閽熼锟�?
    parameter   I2C_FREQ    =   18'd250_000                 // SCL 鐨勬椂閽熼锟�?     
)(
    input                            sys_clk       ,
    input                            rst_n         ,
    
    // to HDMI 
    output       tmds_clk_p                    ,    // TMDS 鏃堕挓閫氶亾
    output       tmds_clk_n                    ,
    output [2:0] tmds_data_p                   ,   // TMDS 鏁版嵁閫氶亾
    output [2:0] tmds_data_n                   ,

    // I2C 閫氶亾
    output                         scl      ,
    inout                             sda
);
//-----------------------------------------------------
//-----------------------------------------------------
// next   is  wire  and  reg  define  

wire      [15 : 0]   i2c_addr      ;
wire      [7  : 0]   i2c_data_w    ;                    
wire                 i2c_rh_wl     ;                     
wire                 i2c_exec      ;      
wire                 dri_clk       ;
wire      [7  : 0]   i2c_data_r    ;
wire                 i2c_ack       ;
wire                 i2c_done      ;

wire      [7 : 0 ]   sec           ;
wire      [7 : 0 ]   min           ;
wire      [7 : 0 ]   hour          ;
wire      [7 : 0 ]   day           ;
wire      [7 : 0 ]   mon           ;
wire      [7 : 0 ]   year          ;                           
                        
                              
            





//--------------------------------------------------------
//--------------------------------------------------------

IIC_CONTROL#(
    .SLAVE_ADDR   ( 7'b1010001 ),
    .CLK_FREQ     ( 26'd50_000_000 ),
    .I2C_FREQ     ( 18'd250_000 )
)u_IIC_CONTROL(
    .clk          ( sys_clk          ),
    .rst_n        ( rst_n        ),
    .i2c_addr     ( i2c_addr     ),
    .i2c_data_w   ( i2c_data_w   ),
    .i2c_rh_wl    ( i2c_rh_wl    ),
    .bit_control  ( 0  ),
    .i2c_exec     ( i2c_exec     ),
    .dri_clk      ( dri_clk      ),
    .i2c_data_r   ( i2c_data_r   ),
    .i2c_ack      ( i2c_ack      ),
    .i2c_done     ( i2c_done     ),
    .scl          ( scl          ),
    .sda          (  sda    )
);

PCF8563#(
    .TIME_INIT   ( TIME_INIT ),
    .WAIT_TIME   ( WAIT_TIME )
)u_PCF8563(
    .clk         ( dri_clk         ),
    .rst_n       ( rst_n       ),
    .i2c_done    ( i2c_done    ),
    .i2c_data_r  ( i2c_data_r  ),
    .i2c_rh_wl   ( i2c_rh_wl   ),
    .i2c_exec    ( i2c_exec    ),
    .i2c_addr    ( i2c_addr    ),
    .i2c_data_w  ( i2c_data_w  ),
    .sec         ( sec         ),
    .min         ( min         ),
    .hour        ( hour        ),
    .day         ( day         ),
    .mon         ( mon         ),
    .year        ( year        )
);




hdmi_top u_hdmi_top(
    .sys_clk      ( sys_clk      ),
    .sys_rst_n    ( rst_n    ),
    .tmds_clk_p   ( tmds_clk_p   ),
    .tmds_clk_n   ( tmds_clk_n   ),
    .tmds_data_p  ( tmds_data_p  ),
    .tmds_data_n  ( tmds_data_n  ),
    .sec          ( sec          ),
    .min          ( min          ),
    .hour         ( hour         ),
    .day          ( day          ),
    .mon          ( mon          ),
    .year         ( year         )
);


endmodule 

dvi_transmitter_top.v

module dvi_transmitter_top(
    input                pclk          ,
    input                sys_rst_n     ,
    input                pclk_x5       ,
    input                video_hsync   ,
    input                video_vsync   ,
    input                video_de      ,
    input   [23 : 0]     video_din     ,
    output               tmds_clk_p    ,
    output               tmds_clk_n    ,
    output  [2 : 0]      tmds_data_p   ,
    output  [2 : 0]      tmds_data_n   ,
    output               tmds_oen  
);


assign tmds_oen = 1 ; 

// next is  define  
wire  reset ;
wire [9:0] blue_10bit ;
wire [9:0] green_10bit ;
wire [9:0] red_10bit ;


wire [2:0] tmds_data_serial ; 
wire       tmds_clk_serial  ;



reset_syn u_reset_syn(
    .pclk     ( pclk     ),
    .reset_n  ( sys_rst_n  ),
    .reset    ( reset    )
);


dvi_encoder u_dvi_encoder_blue(
    .clkin ( pclk ),
    .rstin ( reset ),
    .din   ( video_din[7:0]   ),
    .c0    ( video_hsync    ),
    .c1    ( video_vsync    ),
    .de    ( video_de    ),
    .dout  ( blue_10bit  )
);

dvi_encoder u_dvi_encoder_green(
    .clkin ( pclk ),
    .rstin ( reset ),
    .din   ( video_din[15:8]   ),
    .c0    ( 1'b0    ),
    .c1    ( 1'b0    ),
    .de    ( video_de    ),
    .dout  ( green_10bit  )
);


dvi_encoder u_dvi_encoder_red(
    .clkin ( pclk ),
    .rstin ( reset ),
    .din   ( video_din[23:16]   ),
    .c0    ( 1'b0    ),
    .c1    ( 1'b0    ),
    .de    ( video_de    ),
    .dout  ( red_10bit  )
);

serializer10 u_serializer10_blue(
    .reset          ( reset          ),
    .paralell_clk   ( pclk   ),
    .serial_clk_5x  ( pclk_x5  ),
    .paralell_data  ( blue_10bit  ),
    .serial_data_out  ( tmds_data_serial[0]  )
);

serializer10 u_serializer10_green(
    .reset          ( reset          ),
    .paralell_clk   ( pclk   ),
    .serial_clk_5x  ( pclk_x5  ),
    .paralell_data  ( green_10bit  ),
    .serial_data_out  ( tmds_data_serial[1]  )
);

serializer10 u_serializer10_red(
    .reset          ( reset          ),
    .paralell_clk   ( pclk   ),
    .serial_clk_5x  ( pclk_x5  ),
    .paralell_data  ( red_10bit  ),
    .serial_data_out  ( tmds_data_serial[2]  )
);

serializer10 u_serializer10_clk(
    .reset          ( reset          ),
    .paralell_clk   ( pclk   ),
    .serial_clk_5x  ( pclk_x5  ),
    .paralell_data  ( 10'b1111100000  ),
    .serial_data_out  ( tmds_clk_serial  )
);


//转换差分信号  
OBUFDS #(
    .IOSTANDARD         ("TMDS_33")    // I/O电平标准为TMDS
) TMDS0 (
    .I                  (tmds_data_serial[0]),
    .O                  (tmds_data_p[0]),
    .OB                 (tmds_data_n[0]) 
);

OBUFDS #(
    .IOSTANDARD         ("TMDS_33")    // I/O电平标准为TMDS
) TMDS1 (
    .I                  (tmds_data_serial[1]),
    .O                  (tmds_data_p[1]),
    .OB                 (tmds_data_n[1]) 
);

OBUFDS #(
    .IOSTANDARD         ("TMDS_33")    // I/O电平标准为TMDS
) TMDS2 (
    .I                  (tmds_data_serial[2]), 
    .O                  (tmds_data_p[2]), 
    .OB                 (tmds_data_n[2])  
);

OBUFDS #(
    .IOSTANDARD         ("TMDS_33")    // I/O电平标准为TMDS
) TMDS3 (
    .I                  (tmds_clk_serial), 
    .O                  (tmds_clk_p),
    .OB                 (tmds_clk_n) 
);
endmodule  

encoder.v

module dvi_encoder (
  input            clkin,    // pixel clock input
  input            rstin,    // async. reset input (active high)
  input      [7:0] din,      // data inputs: expect registered
  input            c0,       // c0 input
  input            c1,       // c1 input
  input            de,       // de input
  output reg [9:0] dout      // data outputs
);

  
  // Counting number of 1s and 0s for each incoming pixel
  // component. Pipe line the result.
  // Register Data Input so it matches the pipe lined adder
  // output
  
  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

  ///
  // Stage 1: 8 bit -> 9 bit
  // Refer to DVI 1.0 Specification, page 29, Figure 3-5
  ///
  wire decision1;

  assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0));

  wire [8:0] q_m;
  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;

  /
  // Stage 2: 9 bit -> 10 bit
  // Refer to DVI 1.0 Specification, page 29, Figure 3-5
  /
  reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_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];
    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]);
  end

  parameter CTRLTOKEN0 = 10'b1101010100;
  parameter CTRLTOKEN1 = 10'b0010101011;
  parameter CTRLTOKEN2 = 10'b0101010100;
  parameter CTRLTOKEN3 = 10'b1010101011;

  reg [4:0] cnt; //disparity counter, MSB is the sign bit
  wire decision2, decision3;

  assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m);
  /
  // [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)]
  /
  assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m));

  
  // pipe line alignment
  
  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
    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

  ///
  // 10-bit out
  // disparity counter
  ///
  always @ (posedge clkin or posedge rstin) begin
    if(rstin) begin
      dout <= 10'h0;
      cnt <= 5'h0;
    end else begin
      if (de_reg) begin
        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
        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 

hdmi_display.v

module video_display(
    input                     pixel_clk       ,
    input                     sys_rst_n       ,
    input       [ 11 : 0 ]    pixel_xpos_w    ,
    input       [ 11 : 0 ]    pixel_ypos_w    ,
    output reg  [ 23 : 0 ]    pixel_data_w    ,
    // display
    input      [ 7 : 0]       sec          ,
    input      [ 7 : 0]       min          ,
    input      [ 7 : 0]       hour         ,


    input      [ 7 : 0]       day          ,
    input      [ 7 : 0]       mon          ,
    input      [ 7 : 0]       year
  );

  // 我不想显示年月日?? 直接存起??
  wire [7 : 0] year1 ;
  wire [7 : 0] mon1  ;
  wire [7 : 0] day1  ;
  assign day1  = day  ;
  assign year1 = year ;
  assign mon1  = mon  ;

  // 暂存起来






  //parameter define
  localparam CHAR_X_START = 11'd50;      //字符起始点横坐标
  localparam CHAR_Y_START = 11'd100;    //字符起始点纵坐标




  localparam CHAR_WIDTH  = 10'd88;    //字符宽度 32*11 = 352

  localparam CHAR_HEIGHT = 10'd16;     //字符高度


  //棰滆??
  localparam BACK_COLOR  = 24'hE0FFFF; //背景色,浅蓝??
  localparam CHAR_COLOR  = 24'hff0000; //字符颜色,红??


  reg   [127:0] char[10:0];  //字符数组


  // 这里是字符的显示 我想做的??
  //----------------------
  //  09 : 20  00
  //  两个+空格+冒号+空格+两个+空格+空格+两个  11??
  //
  //
  //----------------------


  always @(posedge pixel_clk)
  begin
   char[0] =   128'h00000018244242424242424224180000;/*"0",0*/
   char[1] =   128'h000000083808080808080808083E0000;/*"1",1*/
   char[2] =   128'h0000003C4242420204081020427E0000;/*"2",2*/
   char[3] =   128'h0000003C4242020418040242423C0000;/*"3",3*/
   char[4] =   128'h000000040C0C142424447F04041F0000;/*"4",4*/
   char[5] =   128'h0000007E404040784402024244380000;/*"5",5*/
   char[6] =   128'h000000182440405C62424242221C0000;/*"6",6*/
   char[7] =   128'h0000007E420404080810101010100000;/*"7",7*/
   char[8] =   128'h0000003C4242422418244242423C0000;/*"8",8*/
   char[9] =   128'h0000003844424242463A020224180000;/*"9",9*/
   char[10] =  128'h00000000000018180000000018180000;/*":",10*/
 
  end

  // 准备显示



  always@( posedge pixel_clk or negedge sys_rst_n)
  begin
    if( sys_rst_n == 0)
    begin
      pixel_data_w <=BACK_COLOR ;
    end
    else
      // //09 : 20  00
      //  两个+空格+冒号+空格+两个+空格+空格+两个  11??
      // 小时的十??
      if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*0)
              && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*1)
              && (pixel_ypos_w >= CHAR_Y_START)
              && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[hour[7 : 4]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                    -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    // 小时的个??
      else  if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*1)
                    && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*2)
                    && (pixel_ypos_w >= CHAR_Y_START)
                    && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[hour[3 : 0]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                    -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    // 空格
      else   if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*2)
                     && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*3)
                     && (pixel_ypos_w >= CHAR_Y_START)
                     && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin

        pixel_data_w <=BACK_COLOR ;
      end
    // 冒号
      else  if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*3)
                    && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*4)
                    && (pixel_ypos_w >= CHAR_Y_START)
                    && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[10][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                           -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    // 空格
      else   if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*4)
                     && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*5)
                     && (pixel_ypos_w >= CHAR_Y_START)
                     && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin

        pixel_data_w <=BACK_COLOR ;
      end
    // 分钟的十??

      else    if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*5)
                      && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*6)
                      && (pixel_ypos_w >= CHAR_Y_START)
                      && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[min[7 : 4]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                   -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    // 分钟的个??
      else  if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*6)
                    && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*7)
                    && (pixel_ypos_w >= CHAR_Y_START)
                    && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[min[3 : 0]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                   -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    //空格
    // 空格
      else   if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*7)
                     && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*8)
                     && (pixel_ypos_w >= CHAR_Y_START)
                     && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin

        pixel_data_w <=BACK_COLOR ;
      end
    // 空格
      else   if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*8)
                     && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*9)
                     && (pixel_ypos_w >= CHAR_Y_START)
                     && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin

        pixel_data_w <=BACK_COLOR ;
      end
    // 秒的十位

      else    if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*9)
                      && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*10)
                      && (pixel_ypos_w >= CHAR_Y_START)
                      && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[sec[7 : 4]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                   -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end
    // 分钟的个??
      else  if(     (pixel_xpos_w >= CHAR_X_START + CHAR_WIDTH/11*10)
                    && (pixel_xpos_w <  CHAR_X_START + CHAR_WIDTH/11*11)
                    && (pixel_ypos_w >= CHAR_Y_START)
                    && (pixel_ypos_w <  CHAR_Y_START + CHAR_HEIGHT)  )
      begin
        if(   char[sec[3 : 0]][    (CHAR_HEIGHT + CHAR_Y_START - pixel_ypos_w) * 8
                                   -((pixel_xpos_w - (CHAR_X_START)) % 8) -1      ]   )
          pixel_data_w <=CHAR_COLOR ;
        else
          pixel_data_w <=BACK_COLOR ;
      end

      else
      begin
        pixel_data_w <= BACK_COLOR;    //屏幕背景为白??
      end
  end






endmodule

HDMI_top.v

module hdmi_top(
    input        sys_clk,
    input        sys_rst_n,

    output       tmds_clk_p,    // TMDS 时钟通道
    output       tmds_clk_n,
    output [2:0] tmds_data_p,   // TMDS 数据通道
    output [2:0] tmds_data_n ,

    // next is from PCF
input      [ 7 : 0]       sec          ,
input      [ 7 : 0]       min          ,
input      [ 7 : 0]       hour         ,
input      [ 7 : 0]       day          ,
input      [ 7 : 0]       mon          ,
input      [ 7 : 0]       year
  );

  //wire define
  wire          pixel_clk;
  wire          pixel_clk_5x;
  wire          clk_locked;

  wire  [10:0]  pixel_xpos_w;
  wire  [10:0]  pixel_ypos_w;
  wire  [23:0]  pixel_data_w;

  wire          video_hs;
  wire          video_vs;
  wire          video_de;
  wire  [23:0]  video_rgb;

  // next is main code
  clk_wiz_0 instance_name1
            (
              // Clock out ports
              .clk_out1(pixel_clk),     // output clk_out1
              .clk_out2(pixel_clk_5x),     // output clk_out2
              // Status and control signals
              .reset(~sys_rst_n), // input reset
              .locked(clk_locked),       // output locked
              // Clock in ports
              .clk_in1(sys_clk)
              );

video_driver u_video_driver(
    .pixel_clk   ( pixel_clk   ),
    .rst_n       ( sys_rst_n       ),
    .pixel_data  ( pixel_data_w  ),
    .video_rgb   ( video_rgb   ),
    .video_hs    ( video_hs    ),
    .video_vs    ( video_vs    ),
    .video_de    ( video_de    ),
    .pixel_xpos  ( pixel_xpos_w  ),
    .pixel_ypos  ( pixel_ypos_w  )
);

video_display u_video_display(
    .pixel_clk     ( pixel_clk     ),
    .sys_rst_n     ( sys_rst_n     ),
    .pixel_xpos_w  ( pixel_xpos_w  ),
    .pixel_ypos_w  ( pixel_ypos_w  ),
    .pixel_data_w  ( pixel_data_w  ),
    .sec           ( sec           ),
    .min           ( min           ),
    .hour          ( hour          ),
    .day           ( day           ),
    .mon           ( mon           ),
    .year          ( year          )
);


dvi_transmitter_top u_dvi_transmitter_top(
    .pclk         ( pixel_clk         ),
    .sys_rst_n    ( sys_rst_n & clk_locked    ),
    .pclk_x5      ( pixel_clk_5x      ),
    .video_hsync  ( video_hs  ),
    .video_vsync  ( video_vs  ),
    .video_de     ( video_de     ),
    .video_din    ( video_rgb    ),
    .tmds_clk_p   ( tmds_clk_p   ),
    .tmds_clk_n   ( tmds_clk_n   ),
    .tmds_data_p  ( tmds_data_p  ),
    .tmds_data_n  ( tmds_data_n  ),
    .tmds_oen     ( )
);

endmodule 

I2c_dri.v

module IIC_CONTROL #(
    parameter             SLAVE_ADDR = 7'b1010001         , // E2PROM 从机地址
    parameter             CLK_FREQ   = 26'd50_000_000     , // 50MHz 的时钟频率
    parameter             I2C_FREQ   = 18'd250_000          // SCL 的时钟频率
  )
  (
    input                            clk                  ,
    input                            rst_n                ,
    //  ----------------------------------------------  //
    input            [15 : 0]         i2c_addr            ,    // 地址
    input            [7  : 0]         i2c_data_w          ,    // 数据
    input                             i2c_rh_wl           ,    // 判断 是 read or write
    input                             bit_control         ,    // 1是 16位 0 是 8位
    input                             i2c_exec            ,

    // ------------------------------------------------    //
    output   reg                      dri_clk             ,
    output   reg     [7 : 0]          i2c_data_r          ,
    output   reg                      i2c_ack             ,
    output   reg                      i2c_done            ,

    // -------------------------------------------------- //
    output   reg                      scl                 ,
    inout                             sda
  );


  // --------------------------------------------------------//
  //    next is  define                                       //
  // --------------------------------------------------------//
  reg         [9 : 0]             clk_cnt              ;
  wire        [8 : 0]             dri_cnt              ;
  reg         [2 : 0]             state                ;
  reg         [2 : 0]             next_state           ;
  reg                             st_done              ; // 在 状态机里面用来提示数据完成可以跳转
  reg                             sda_dir              ; // sda方向控制器
  reg                             sda_out              ; // 选择FPGA输入模式之后赋予sda线上
  wire                            sda_in               ; // sda输入信号
  reg         [6 : 0]             cnt                  ; // 我们为了第三部分状态机而准备的

  reg         [15: 0]             addr_save            ; // 地址存储
  reg         [7 : 0]             data_w_save          ; // 数据写的暂存
  reg                             wr_flag              ; // 0 是 写 1 是 读
  // 这三个是 暂存的方便调度的

  reg         [7 : 0]             data_r_save          ; // 读到的数据存储方便整合

  // --------------------------------------------------------- //
  //  parameter define                                         //
  parameter                 st_idle      =  3'b000        ;  // 空闲状态
  parameter                 st_sladdr    =  3'b001        ;  // 发送器件地址
  parameter                 st_addr16    =  3'b010        ;  // 发送高八位地址
  parameter                 st_addr8     =  3'b011        ;  // 发送低八位地址
  parameter                 st_data_wr   =  3'b100        ;  // 写数据
  parameter                 st_addr_rd   =  3'b101        ;  // 再次发送器件地址读
  parameter                 st_data_rd   =  3'b110        ;  // 读数据
  parameter                 st_stop      =  3'b111        ;  // 结束操作停止位


  //    ---------------------------------------------------- //
  //    next is main  code                                   //
  // -------------------------------------------------------//
  assign dri_cnt = (CLK_FREQ/I2C_FREQ ) >> 2                ;

  always@(posedge clk or negedge rst_n )
  begin
    if(rst_n == 0)
    begin
      dri_clk   <=  0         ;
      clk_cnt   <=  0         ;
    end
    else if( clk_cnt == dri_cnt[8:1] - 1)
    begin
      clk_cnt   <=  0         ;
      dri_clk   <=  ~dri_clk  ;
    end
    else
    begin
      dri_clk   <=  dri_clk     ;
      clk_cnt   <=  clk_cnt + 1 ;
    end
  end

  // 下面开始状态机的叙述




  // 同步时序描述状态转移
  always@(posedge dri_clk or negedge rst_n)
  begin
    if(rst_n == 0)
    begin
      state <= st_idle ;
    end // 处于空闲状态
    else
    begin
      state <= next_state ;
    end
  end



  // 组合逻辑判断状态转移条件
  always@(*)
  begin
    next_state <= st_idle ;
    case(state)

      st_idle :
      begin
        if(i2c_exec == 1)
        begin
          next_state      <= st_sladdr ;
        end
        else
        begin
          next_state      <= st_idle   ;
        end
      end
      // 当触发了i2c_exec 时候 可以由 空闲状态转移到

      st_sladdr :
      begin
        if(st_done == 1)
        begin
          if(bit_control == 1)
            next_state <= st_addr16 ;
          else
            next_state <= st_addr8  ;
        end
        else
        begin
          next_state <= st_sladdr ;
        end
      end

      // 当 触发了 st_done 之后 通过 bit_control 选择是低八位 还是高八位的传输

      st_addr16 :
      begin
        if(st_done == 1)
        begin
          next_state <= st_addr8 ;
        end
        else
        begin
          next_state <= st_addr16 ;
        end
      end

      // 高位 用完 轮到 低位的 传输

      st_addr8  :
      begin
        if(st_done == 1)
        begin
          if(wr_flag == 0)
            next_state <= st_data_wr ;
          else
            next_state <= st_addr_rd ;
        end
        else
        begin
          next_state <= st_addr8 ;
        end
      end

      // 先来判断 写数据的 st_data_wr 数据代号是 4
      st_data_wr :
      begin
        if(st_done == 1)
        begin
          next_state <= st_stop ;
        end
        else
        begin
          next_state <= st_data_wr ;
        end
      end

      //

      st_addr_rd :
      begin
        if(st_done == 1)
        begin
          next_state <= st_data_rd ;
        end
        else
        begin
          next_state <= st_addr_rd ;
        end
      end

      //

      st_data_rd :
      begin
        if(st_done == 1)
        begin
          next_state <= st_stop ;
        end
        else
        begin
          next_state <= st_data_rd ;
        end
      end

      //

      st_stop :
      begin
        if(st_done == 1)
        begin
          next_state <= st_idle ;
        end
        else
        begin
          next_state <= st_stop ;
        end
      end

      default:
        next_state <= st_idle ;
    endcase
  end

  / 下面来考虑另一个状态机的第三部分   --- 时序电路描述状态输出
  // 设置一个变量 来控制 SDA的朝向
  assign     sda    = sda_dir ? sda_out : 1'bz   ;  // sda_dir 为1 FPGA控制
  assign     sda_in = sda                        ;  // 把sda当成了输出


  always@(posedge dri_clk or negedge rst_n )
  begin
    if( rst_n == 0)
    begin
      //首先根据输入输出 来判断 SCL 与 SDA 必须都为高
      scl         <=    1 ;
      sda_dir     <=    1 ;
      sda_out     <=    1 ;
      // 剩下的输出 i2c_data_r(输出) == data_r_save
      i2c_data_r  <=    0 ;
      data_r_save <=    0 ;
      // 下面是端口的另外两个输出 i2c_ack 和 i2c_done
      i2c_ack     <=    0 ;
      i2c_done    <=    0 ;

      // 接下里是 内部信号的调节  这两个一个是内部后续的计数 还有一个本次case完成的结束信号
      cnt         <=    0 ;
      st_done     <=    0 ;

      // 下面是三个暂存信号一个是 读写标志位 还有 传入的地址暂存 传入的数据暂存
      wr_flag     <=    0 ;
      addr_save   <=    0 ;
      data_w_save <=    0 ;
    end
    else
    begin
      st_done   <=    0    ;    // 脉冲信号
      cnt       <= cnt + 1 ;
      //这里写在了 case之前就代表了 不用刻意在内部去调配 st_done 或是cnt
      case(state)
        st_idle :
        begin
          scl         <=    1 ;
          sda_dir     <=    1 ;
          sda_out     <=    1 ;
          //这两个写不写不所谓 因为根本没用到
          i2c_data_r  <=    0 ;
          data_r_save <=    0 ;
          i2c_done    <=    0 ;
          //
          cnt         <=    0 ;
          st_done     <=    0 ;
          // 开始
          if( i2c_exec == 1) begin
          wr_flag     <=    i2c_rh_wl  ;
          addr_save   <=    i2c_addr   ;
          data_w_save <=    i2c_data_w ;
          i2c_ack     <=    0 ;
           end
        end
        // 这里先传递的是
        st_sladdr :
        begin
          case(cnt)
            7'd1  :
              sda_out <=  0             ;
            7'd3  :
              scl     <=  0             ;
            7'd4  :
              sda_out <=  SLAVE_ADDR[6] ;

            7'd5  :
              scl     <=  1'b1          ;
            7'd7  :
              scl     <=  1'b0          ;
            7'd8  :
              sda_out <=  SLAVE_ADDR[5] ;

            7'd9  :
              scl     <=  1'b1          ;
            7'd11 :
              scl     <=  1'b0          ;
            7'd12 :
              sda_out <=  SLAVE_ADDR[4] ;

            7'd13 :
              scl     <=  1'b1          ;
            7'd15 :
              scl     <=  1'b0          ;
            7'd16 :
              sda_out <=  SLAVE_ADDR[3] ;

            7'd17 :
              scl     <=  1'b1          ;
            7'd19 :
              scl     <=  1'b0          ;
            7'd20 :
              sda_out <=  SLAVE_ADDR[2] ;

            7'd21 :
              scl     <=  1'b1          ;
            7'd23 :
              scl     <=  1'b0          ;
            7'd24 :
              sda_out <=  SLAVE_ADDR[1] ;

            7'd25 :
              scl     <=  1'b1          ;
            7'd27 :
              scl     <=  1'b0          ;
            7'd28 :
              sda_out <=  SLAVE_ADDR[0] ;

            7'd29 :
              scl     <=  1'b1          ;
            7'd31 :
              scl     <=  1'b0          ;
            7'd32 :
              sda_out <=  1'b0          ;
            // 此处完成了 数据的传递 接下来的任务是 反馈

            7'd33 :
              scl     <=  1'b1          ;
            7'd35 :
              scl     <=  1'b0          ;
            7'd36 :
              sda_dir <=  1'b0          ;   // 下放控制权给从机端口

            7'd37 :
              scl     <=  1'b1          ;
            // 下一时刻判断是否 有正确的反馈拉低 并确定 st_done = 1
            7'd38 :
            begin
              st_done         <=  1'b1          ;
              if( sda_in == 1)
                i2c_ack         <=  1'b1          ;
            end

            7'd39 :
            begin
              scl             <=  1'b0          ;
              cnt             <=  7'b0          ;
            end
            default :
              ;
          endcase
        end


        //发送高8位字节
        st_addr16 :
        begin
          case(cnt)
            7'd0 :
            begin   // 39之后移动一格就是0 0 此处即可以开始
              //把使能交还给FPGA端
              sda_dir     <=    1'b1              ;
              sda_out     <=    addr_save[15]     ;
            end

            // 第一个转换有点时序差距 后面都是 每隔4 sda变化一次

            7'd1   :
              scl         <=   1'b1             ;
            7'd3   :
              scl         <=   1'b0             ;
            7'd4   :
              sda_out     <=   addr_save[14]    ;

            7'd5   :
              scl         <=   1'b1             ;
            7'd7   :
              scl         <=   1'b0             ;
            7'd8   :
              sda_out     <=   addr_save[13]    ;

            7'd9   :
              scl         <=   1'b1             ;
            7'd11  :
              scl         <=   1'b0             ;
            7'd12  :
              sda_out     <=   addr_save[12]    ;

            7'd13  :
              scl         <=   1'b1             ;
            7'd15  :
              scl         <=   1'b0             ;
            7'd16  :
              sda_out     <=   addr_save[11]    ;

            7'd17  :
              scl         <=   1'b1             ;
            7'd19  :
              scl         <=   1'b0             ;
            7'd20  :
              sda_out     <=   addr_save[10]    ;

            7'd21  :
              scl         <=   1'b1             ;
            7'd23  :
              scl         <=   1'b0             ;
            7'd24  :
              sda_out     <=   addr_save[9]     ;

            7'd25  :
              scl         <=   1'b1             ;
            7'd27  :
              scl         <=   1'b0             ;
            7'd28  :
              sda_out     <=   addr_save[8]     ;
            // 29 拉升 31下降 32放控制权 33拉升 34结束并作判断 35 拉低 cnt归零为下一状态准备

            7'd29  :
              scl         <=   1'b1             ;
            7'd31  :
              scl         <=   1'b0             ;
            7'd32  :
              sda_dir     <=   1'b0             ;
            7'd33  :
              scl         <=   1'b1             ;

            7'd34  :
            begin
              st_done     <=   1'b1             ; //完成
              if(sda_in == 1)
                i2c_ack     <=   1'b1             ; // scl拉高时 反馈 i2c_ack = 1 表示有错误
            end

            7'd35  :
            begin
              scl         <=   1'b0             ;
              cnt         <=   7'b0             ;
            end
            default :
              ;
          endcase
        end



        //发送低8位字节
        st_addr8 :
        begin
          // 和上面这个写法是一样的 对于cnt = 0 sda_dir 交回FPGA控制权 并立刻赋值
          case(cnt)
            7'd0:
            begin
              sda_dir <= 1'b1 ;
              sda_out <= addr_save[7];         //字地址
            end
            7'd1  :
              scl     <= 1'b1;
            7'd3  :
              scl     <= 1'b0;
            7'd4  :
              sda_out <= addr_save[6];

            7'd5  :
              scl <= 1'b1;
            7'd7  :
              scl <= 1'b0;
            7'd8  :
              sda_out <= addr_save[5];

            7'd9  :
              scl <= 1'b1;
            7'd11 :
              scl <= 1'b0;
            7'd12 :
              sda_out <= addr_save[4];

            7'd13 :
              scl <= 1'b1;
            7'd15 :
              scl <= 1'b0;
            7'd16 :
              sda_out <= addr_save[3];

            7'd17 :
              scl <= 1'b1;
            7'd19 :
              scl <= 1'b0;
            7'd20 :
              sda_out <= addr_save[2];

            7'd21 :
              scl <= 1'b1;
            7'd23 :
              scl <= 1'b0;
            7'd24 :
              sda_out <= addr_save[1];

            7'd25 :
              scl <= 1'b1;
            7'd27 :
              scl <= 1'b0;
            7'd28 :
              sda_out <= addr_save[0];



            7'd29  :
              scl         <=   1'b1             ;
            7'd31  :
              scl         <=   1'b0             ;
            7'd32  :
              sda_dir     <=   1'b0             ;
            7'd33  :
              scl         <=   1'b1             ;

            7'd34  :
            begin
              st_done     <=   1'b1             ; //完成
              if(sda_in == 1)
                i2c_ack     <=   1'b1             ; // scl拉高时 反馈 i2c_ack = 1 表示有错误
            end

            7'd35  :
            begin
              scl         <=   1'b0             ;
              cnt         <=   7'b0             ;
            end
            default :
              ;
          endcase
        end



        //
        st_data_wr :
        begin
          // 和上面这个写法是一样的 对于cnt = 0 sda_dir 交回FPGA控制权 并立刻赋值
          case(cnt)
            7'd0:
            begin
              sda_dir <= 1'b1 ;
              sda_out <= data_w_save[7];         //字地址
            end
            7'd1  :
              scl     <= 1'b1;
            7'd3  :
              scl     <= 1'b0;
            7'd4  :
              sda_out <= data_w_save[6];

            7'd5  :
              scl <= 1'b1;
            7'd7  :
              scl <= 1'b0;
            7'd8  :
              sda_out <= data_w_save[5];

            7'd9  :
              scl <= 1'b1;
            7'd11 :
              scl <= 1'b0;
            7'd12 :
              sda_out <= data_w_save[4];

            7'd13 :
              scl <= 1'b1;
            7'd15 :
              scl <= 1'b0;
            7'd16 :
              sda_out <= data_w_save[3];

            7'd17 :
              scl <= 1'b1;
            7'd19 :
              scl <= 1'b0;
            7'd20 :
              sda_out <= data_w_save[2];

            7'd21 :
              scl <= 1'b1;
            7'd23 :
              scl <= 1'b0;
            7'd24 :
              sda_out <= data_w_save[1];

            7'd25 :
              scl <= 1'b1;
            7'd27 :
              scl <= 1'b0;
            7'd28 :
              sda_out <= data_w_save[0];

            // 29 拉升 31下降 32放控制权 33拉升 34结束并作判断 35 拉低 cnt归零为下一状态准备

            7'd29  :
              scl         <=   1'b1             ;
            7'd31  :
              scl         <=   1'b0             ;
            7'd32  :
              sda_dir     <=   1'b0             ;
            7'd33  :
              scl         <=   1'b1             ;

            7'd34  :
            begin
              st_done     <=   1'b1             ; //完成
              if(sda_in == 1)
                i2c_ack     <=   1'b1             ; // scl拉高时 反馈 i2c_ack = 1 表示有错误
            end

            7'd35  :
            begin
              scl         <=   1'b0             ;
              cnt         <=   7'b0             ;
            end
            default :
              ;
          endcase
        end


        // 读控制信号 可以开始读了
        st_addr_rd :
        begin
          // 这里的过程应该和上面的那个 st_sladdr一样 先写地址
          //  一样又不太一样
          case(cnt)
            7'd0 :
            begin
              sda_dir <= 1'b1;
              sda_out <= 1'b1;
            end
            7'd1 :
              scl <= 1'b1;
            7'd2 :
              sda_out <= 1'b0;          //重新开始
            7'd3 :
              scl <= 1'b0;
            7'd4 :
              sda_out <= SLAVE_ADDR[6]; //传送器件地址
            7'd5 :
              scl <= 1'b1;
            7'd7 :
              scl <= 1'b0;
            7'd8 :
              sda_out <= SLAVE_ADDR[5];
            7'd9 :
              scl <= 1'b1;
            7'd11:
              scl <= 1'b0;
            7'd12:
              sda_out <= SLAVE_ADDR[4];
            7'd13:
              scl <= 1'b1;
            7'd15:
              scl <= 1'b0;
            7'd16:
              sda_out <= SLAVE_ADDR[3];
            7'd17:
              scl <= 1'b1;
            7'd19:
              scl <= 1'b0;
            7'd20:
              sda_out <= SLAVE_ADDR[2];
            7'd21:
              scl <= 1'b1;
            7'd23:
              scl <= 1'b0;
            7'd24:
              sda_out <= SLAVE_ADDR[1];
            7'd25:
              scl <= 1'b1;
            7'd27:
              scl <= 1'b0;
            7'd28:
              sda_out <= SLAVE_ADDR[0];
            7'd29:
              scl <= 1'b1;
            7'd31:
              scl <= 1'b0;
            7'd32:
              sda_out <= 1'b1;          //1:读
            7'd33:
              scl <= 1'b1;
            7'd35:
              scl <= 1'b0;
            7'd36:
            begin
              sda_dir <= 1'b0;
              sda_out <= 1'b1;
            end
            7'd37:
              scl     <= 1'b1;
            7'd38:
            begin                     //从机应答
              st_done <= 1'b1;
              if(sda_in == 1'b1)           //高电平表示未应答
                i2c_ack <= 1'b1;         //拉高应答标志位
            end
            7'd39:
            begin
              scl <= 1'b0;
              cnt <= 7'b0;
            end
            default :
              ;
          endcase
        end

        st_data_rd :
        begin                        //读取数据(8 bit)
          case(cnt)
            7'd0:
              sda_dir <= 1'b0;
            7'd1:
            begin
              data_r_save[7] <= sda_in;
              scl       <= 1'b1;
            end
            7'd3:
              scl  <= 1'b0;
            7'd5:
            begin
              data_r_save[6] <= sda_in ;
              scl       <= 1'b1   ;
            end
            7'd7:
              scl  <= 1'b0;
            7'd9:
            begin
              data_r_save[5] <= sda_in;
              scl       <= 1'b1  ;
            end
            7'd11:
              scl  <= 1'b0;
            7'd13:
            begin
              data_r_save[4] <= sda_in;
              scl       <= 1'b1  ;
            end
            7'd15:
              scl  <= 1'b0;
            7'd17:
            begin
              data_r_save[3] <= sda_in;
              scl       <= 1'b1  ;
            end
            7'd19:
              scl  <= 1'b0;
            7'd21:
            begin
              data_r_save[2] <= sda_in;
              scl       <= 1'b1  ;
            end
            7'd23:
              scl  <= 1'b0;
            7'd25:
            begin
              data_r_save[1] <= sda_in;
              scl       <= 1'b1  ;
            end
            7'd27:
              scl  <= 1'b0;
            7'd29:
            begin
              data_r_save[0] <= sda_in;
              scl       <= 1'b1  ;
            end


            7'd31:
              scl  <= 1'b0;
            7'd32:
            begin
              sda_dir <= 1'b1;
              sda_out <= 1'b1;
            end
            7'd33:
              scl     <= 1'b1;
            7'd34:
              st_done <= 1'b1;          //非应答
            7'd35:
            begin
              scl <= 1'b0;
              cnt <= 7'b0;
              i2c_data_r <= data_r_save;
            end
            default  :
              ;
          endcase
        end


        st_stop:
        begin                           //结束I2C操作
          case(cnt)
            7'd0:
            begin
              sda_dir <= 1'b1;             //结束I2C
              sda_out <= 1'b0;
            end
            7'd1 :
              scl     <= 1'b1;
            7'd3 :
              sda_out <= 1'b1;
            7'd15:
              st_done <= 1'b1;
            7'd16:
            begin
              cnt      <= 7'b0;
              i2c_done <= 1'b1;            //向上层模块传递I2C结束信号
            end
            default  :
              ;
          endcase
        end
      endcase
    end
  end

endmodule

PCF8563.v

module PCF8563#(
    parameter   TIME_INIT   =   48'h24_01_06_14_30_00  ,
    parameter   WAIT_TIME   =   13'd8000
  )(
    input                        clk         ,
    input                        rst_n       ,
    input                        i2c_done    ,
    input         [7 : 0]        i2c_data_r  ,  // this thing from i2c to HDMI
    //
    output   reg                 i2c_rh_wl   ,
    output   reg                 i2c_exec    ,
    output   reg  [15 : 0]       i2c_addr    ,
    output   reg  [ 7 : 0]       i2c_data_w  ,  // this is give to i2c
    //
    output   reg  [ 7 : 0]       sec          ,
    output   reg  [ 7 : 0]       min          ,
    output   reg  [ 7 : 0]       hour         ,
    output   reg  [ 7 : 0]       day          ,
    output   reg  [ 7 : 0]       mon          ,
    output   reg  [ 7 : 0]       year
  );


  // parameter  and define

  reg  [3  : 0] reg_cnt    ;
  reg  [12 : 0] wait_cnt   ;








  //

  always@(posedge clk or negedge rst_n)
  begin
    if(rst_n == 0 )
    begin
      i2c_rh_wl      <=   0 ;
      i2c_exec       <=   0 ;
      i2c_addr       <=   0 ;
      i2c_data_w     <=   0 ;
      sec            <=   0 ;
      min            <=   0 ;
      hour           <=   0 ;
      day            <=   0 ;
      mon            <=   0 ;
      year           <=   0 ;
      reg_cnt        <=   0 ;
      wait_cnt       <=   0 ;

    end
    else
    begin
      i2c_exec <= 0 ;
      case(reg_cnt)
        4'd0 :
        begin   // ��???
          i2c_exec  <= 0  ;
          if(wait_cnt == WAIT_TIME   )
          begin
            wait_cnt <= 0 ;
            reg_cnt  <= reg_cnt +1 ;
          end
          else
            wait_cnt <= wait_cnt + 1 ;
        end
        //---------------------------------------------------------------------
        4'd1 :
        begin  // ??  ??
          i2c_exec   <=  1                 ;
          i2c_addr   <=  8'h02            ;
          reg_cnt    <=  reg_cnt + 1       ;
          i2c_data_w <=  TIME_INIT[7 : 0]  ;
        end

        4'd2 :
        begin  // ?? ??
          if(i2c_done == 1)
          begin
            sec     <=  i2c_data_r[6 : 0]  ;
            reg_cnt <=  reg_cnt + 1        ;
          end
        end
        //--------------------------------------------------------------------------
        4'd3  :   // ?? ����
        begin
          i2c_exec   <=  1                 ;
          i2c_addr   <=  8'h03            ;
          reg_cnt    <=  reg_cnt + 1       ;
          i2c_data_w <=  TIME_INIT[15: 8]  ;
        end

        4'd4 : // ?? ����
        begin  //
          if(i2c_done == 1)
          begin
            min     <=  i2c_data_r[6 : 0]  ;
            reg_cnt <=  reg_cnt + 1        ;
          end
        end
        //---------------------------------------------------------------
        4'd5  :   // ?? Сʱ
        begin
          i2c_exec   <=  1                  ;
          i2c_addr   <=  8'h04             ;
          reg_cnt    <=  reg_cnt + 1        ;
          i2c_data_w <=  TIME_INIT[23: 16]  ;
        end

        4'd6 : // ?? Сʱ
        begin  //
          if(i2c_done == 1)
          begin
            hour    <=  i2c_data_r[5 : 0]  ;
            reg_cnt <=  reg_cnt + 1        ;
          end
        end
        //---------------------------------------------------------------
        4'd7  :   // ?? ??
        begin
          i2c_exec   <=  1                  ;
          i2c_addr   <=  8'h05             ;
          reg_cnt    <=  reg_cnt + 1        ;
          i2c_data_w <=  TIME_INIT[31: 24]  ;
        end

        4'd8 : // ?? ??
        begin  //
          if(i2c_done == 1)
          begin
            day     <=  i2c_data_r[5 : 0]  ;
            reg_cnt <=  reg_cnt + 1        ;
          end
        end
        //----------------------------------------------------------------------
        4'd9  :   // ?? ??
        begin
          i2c_exec   <=  1                  ;
          i2c_addr   <=  8'h07             ;
          reg_cnt    <=  reg_cnt + 1        ;
          i2c_data_w <=  TIME_INIT[39: 32]  ;
        end

        4'd10 : // ?? ??
        begin  //
          if(i2c_done == 1)
          begin
            mon     <=  i2c_data_r[4 : 0]  ;
            reg_cnt <=  reg_cnt + 1        ;
          end
        end
        //------------------------------------------------------------------------
        4'd11  :   // ?? ??
        begin
          i2c_exec   <=  1                  ;
          i2c_addr   <=  8'h08             ;
          reg_cnt    <=  reg_cnt + 1        ;
          i2c_data_w <=  TIME_INIT[47: 40]  ;
        end

        4'd12 : // ?? ??
        begin  //
          if(i2c_done == 1)
          begin
            year      <=  i2c_data_r[7 : 0]  ;
            i2c_rh_wl <=  1        ;
            reg_cnt   <=  1        ;
          end
        end
        default : reg_cnt <= 0 ;

      endcase
   end
end
endmodule 

reset_syn.v

module  reset_syn(
    input            pclk     ,
    input            reset_n  ,
    output   reg     reset
  );

  reg reset1 ;


  always@( posedge pclk   or  negedge reset_n)
  begin
    if( reset_n == 0)
    begin
      reset1 <= 1 ;
    end
    else
    begin
      reset1 <= 0      ;
      reset  <= reset1 ;
    end
  end
endmodule

serializer.v

module serializer10 (
    input                       reset           ,  // 复位,高有效
    input                       paralell_clk    ,  // 输入并行数据时钟 
    input                       serial_clk_5x   ,   // 输入串行数据时钟
    input        [9 : 0]        paralell_data   ,   // 输入并行数据
    output                      serial_data_out          // 输出串行数据
);



//wire define
 wire cascade1 ; //用于两个 OSERDESE2 级联的信号
 wire cascade2 ;



// 此处的代码 来自 vivado的 原语 和 正点原子的同时调配 
// 这是 master接口 



OSERDESE2 #(
    .DATA_RATE_OQ("DDR"),   // 设置双倍数据速率
    .DATA_RATE_TQ("DDR"),   // DDR, BUF, SDR
    .DATA_WIDTH(10),         // 输入的并行数据宽度为 10bit
   // .INIT_OQ(1'b0),         // Initial value of OQ output (1'b0,1'b1)
   // .INIT_TQ(1'b0),         // Initial value of TQ output (1'b0,1'b1)
    .SERDES_MODE("MASTER"), // MASTER, SLAVE
    //.SRVAL_OQ(1'b0),        // OQ output value when SR is used (1'b0,1'b1)
   // .SRVAL_TQ(1'b0),        // TQ output value when SR is used (1'b0,1'b1)
    .TBYTE_CTL("FALSE"),    // Enable tristate byte operation (FALSE, TRUE)
    .TBYTE_SRC("FALSE"),    // Tristate byte source (FALSE, TRUE)
    .TRISTATE_WIDTH(1)      // 3-state converter width (1,4)
 )
 OSERDESE2_MASTER (
    .OFB(),             // 未使用
    .OQ(serial_data_out),               // 串行输出数据
    // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
    .SHIFTOUT1(),  // SHIFTIN1 用于位宽扩展
    .SHIFTOUT2(),  // SHIFTIN2 用于位宽扩展
    .TBYTEOUT(),   // 未使用
    .TFB(),             // 未使用
    .TQ(),               // 未使用
    .CLK(serial_clk_5x),    // 串行数据时钟,5 倍时钟频率
    .CLKDIV(paralell_clk),  // 并行数据时钟
    // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
    .D1(paralell_data[0]),
    .D2(paralell_data[1]),
    .D3(paralell_data[2]),
    .D4(paralell_data[3]),
    .D5(paralell_data[4]),
    .D6(paralell_data[5]),
    .D7(paralell_data[6]),
    .D8(paralell_data[7]),
    .OCE(1'b1),             // 1-bit input: Output data clock enable
    .RST(reset),             // 1-bit input: Reset
    // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
    .SHIFTIN1(cascade1),     // SHIFTIN1 用于位宽扩展
    .SHIFTIN2(cascade2),     // SHIFTIN2  用于位宽扩展
    // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
    .T1(1'b0),                // 未使用
    .T2(1'b0),                // 未使用
    .T3(1'b0),                // 未使用
    .T4(1'b0),                // 未使用
    .TBYTEIN(1'b0),     // 未使用
    .TCE(1'b0)              // 未使用
 );


// slave接口 
 OSERDESE2 #(
    .DATA_RATE_OQ("DDR"),   // 设置双倍数据速率
    .DATA_RATE_TQ("DDR"),   // DDR, BUF, SDR
    .DATA_WIDTH(10),         // 输入的并行数据宽度为 10bit
   // .INIT_OQ(1'b0),         // Initial value of OQ output (1'b0,1'b1)
   // .INIT_TQ(1'b0),         // Initial value of TQ output (1'b0,1'b1)
    .SERDES_MODE("SLAVE"), // MASTER, SLAVE
    //.SRVAL_OQ(1'b0),        // OQ output value when SR is used (1'b0,1'b1)
   // .SRVAL_TQ(1'b0),        // TQ output value when SR is used (1'b0,1'b1)
    .TBYTE_CTL("FALSE"),    // Enable tristate byte operation (FALSE, TRUE)
    .TBYTE_SRC("FALSE"),    // Tristate byte source (FALSE, TRUE)
    .TRISTATE_WIDTH(1)      // 3-state converter width (1,4)
 )
 OSERDESE2_SLAVE (
    .OFB(),             // 未使用
    .OQ(),               // 串行输出数据
    // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
    .SHIFTOUT1(cascade1),  // SHIFTIN1 用于位宽扩展
    .SHIFTOUT2(cascade2),  // SHIFTIN2 用于位宽扩展
    .TBYTEOUT(),   // 未使用
    .TFB(),             // 未使用
    .TQ(),               // 未使用
    .CLK(serial_clk_5x),    // 串行数据时钟,5 倍时钟频率
    .CLKDIV(paralell_clk),  // 并行数据时钟
    // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
    .D1(1'b0),
    .D2(1'b0),
    .D3(paralell_data[8]),
    .D4(paralell_data[9]),
    .D5(1'b0),
    .D6(1'b0),
    .D7(1'b0),
    .D8(1'b0),
    .OCE(1'b1),             // 1-bit input: Output data clock enable
    .RST(reset),             // 1-bit input: Reset
    // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
    .SHIFTIN1(),     // SHIFTIN1 用于位宽扩展
    .SHIFTIN2(),     // SHIFTIN2  用于位宽扩展
    // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
    .T1(1'b0),                // 未使用
    .T2(1'b0),                // 未使用
    .T3(1'b0),                // 未使用
    .T4(1'b0),                // 未使用
    .TBYTEIN(1'b0),     // 未使用
    .TCE(1'b0)              // 未使用
 );

endmodule 

video_driver.v

module video_driver
(
  input                         pixel_clk    ,
  input                         rst_n        ,
  input        [ 23 : 0 ]       pixel_data   ,

  output       [ 23 : 0 ]       video_rgb    ,
  output                        video_hs     ,     //  行同步信号
  output                        video_vs     ,     //  场同步信号
  output                        video_de     ,     //  数据使能
  output       [ 11 : 0 ]       pixel_xpos   ,     //  像素点横坐标  1280
  output       [ 11 : 0 ]       pixel_ypos        //  像素点横坐标  720
);

  //parameter define

  //1280*720  分辨率时序参数    时钟频率74.25
  parameter  H_SYNC   =  12'd40;   //行同步
  parameter  H_BACK   =  12'd220;  //行显示后沿
  parameter  H_DISP   =  12'd1280; //行有效数据
  parameter  H_FRONT  =  12'd110;  //行显示前沿
  parameter  H_TOTAL  =  12'd1650; //行扫描周期

  parameter  V_SYNC   =  12'd5;    //场同步
  parameter  V_BACK   =  12'd20;   //场显示后沿
  parameter  V_DISP   =  12'd720;  //场有效数据
  parameter  V_FRONT  =  12'd5;    //场显示前沿
  parameter  V_TOTAL  =  12'd750;  //场扫描周期



  //  reg define
  reg [11 : 0]   cnt_h ;
  reg [11 : 0]   cnt_v ;

 wire data_reg ; 
  // define








  //  next is main code
  always@(posedge pixel_clk or negedge rst_n)
  begin
    if( rst_n == 0)
    begin
      cnt_h <= 0 ;
    end
    else
    begin
      if(cnt_h == H_TOTAL - 1)
      begin
        cnt_h <= 0 ;
      end
      else
        cnt_h <= cnt_h + 1 ;
    end
  end


  always@(posedge pixel_clk or negedge rst_n)
  begin
    if( rst_n == 0)
    begin
      cnt_v = 0 ;
    end
    else
    begin
      if( cnt_h == H_TOTAL - 1)
      begin
        if(cnt_v == V_TOTAL - 1)
        begin
          cnt_v <= 0 ;
        end
        else
        begin
          cnt_v <= cnt_v + 1 ;
        end
      end
    end
  end



//    =======================main code============\\
 // video_rgb 
 // video_hs  
 // video_vs  
 // video_de  
 // pixel_xpos
 // pixel_ypos 
assign video_hs = 1 ; 
assign video_vs = 1 ; 

assign video_rgb  =   video_de ? pixel_data : 24'b0 ; 

assign video_de   =  (((cnt_h >= H_SYNC+H_BACK) && (cnt_h < H_SYNC+H_BACK+H_DISP))
&&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
?  1'b1 : 1'b0;

assign data_reg   =  (((cnt_h >= H_SYNC+H_BACK - 1) && (cnt_h < H_SYNC+H_BACK+H_DISP - 1))
&&((cnt_v >= V_SYNC+V_BACK) && (cnt_v < V_SYNC+V_BACK+V_DISP)))
?  1'b1 : 1'b0;

assign pixel_xpos = data_reg ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 0;
assign pixel_ypos = data_reg ? (cnt_v - (V_SYNC + V_BACK - 1'b1)) : 0;

endmodule 

README.md

## RTC实时时钟实验 -- 在HDMI上显示 



### 将整体设计分为3部分 
( HDMI部分 中间模块  IIC 转接口 
其实 HDMI的部分 只要在于修改 display 的显示
对于 IIC 转接口 直接使用上一个项目的 示例   )

先了解难度最大的中间模块的书写
在第一次上电 将初始值赋予i2c_dri 这是写 部分 接下来都是进入循环的读
其实我觉得他这个思路挺好的 就是记录一个 i2c_done 如果没有接收到done 信号 就一直执行
接收到了



这里有一个值得思考的地方为什么正点原子把 i2c_addr,明明是 16位 在赋值的时候只搞8位
难道不会出现问题嘛?可恶!!!

在完成中间模块 和 IIC的模块之后 
我们接下来考虑的是 HDMI的接口 
HDMI 下属又分为几个小的模块 主要修改的 
dvi_transmitter_top
encoder
reset_syn
serializer
top            //  修改 
video_display  //  修改 
video_driver

文章来源地址https://www.toymoban.com/news/detail-781452.html

到了这里,关于【【RTC实时时钟实验 -- 在HDMI上显示-FPGA 小实验】】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(四)

            在介绍完OV7725初始化配置和视频采集模块后,就到了整个项目的核心部分即DDR3乒乓存储图像模块,为了实现整个FPGA项目工程当中良好的实时性,乒乓操作在广泛应用在FPGA视频加速处理和数字信号处理中。        关于乒乓操作,有很多的FPGA相关书籍都多多少少做了

    2024年02月02日
    浏览(48)
  • FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(一)

           在例程“OV7725摄像头实时采集送HDMI显示”中,我们将走近FPGA图像处理的世界,图像处理、数字信号、高速接口也一直被业界公认为FPGA应用的三大主流领域,这个例程主要基于OV7725摄像头的视频图像采集项目,进行了详细地需求分析,从顶层到底层,从框架到功能,

    2024年02月02日
    浏览(51)
  • FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(三)

           在详细介绍过OV7725 CMOS Sensor的相关背景知识和如何初始化其内部寄存器达到输出预期视频流的目的后,就到了该例程的核心内容即把OV7725输出的视频流预先缓存到外部DDR3颗粒,接着按照HDMI的视频格式把DDR3颗粒内存储的一帧一帧图像数据送显到屏幕上显示,如图1所示

    2024年01月17日
    浏览(55)
  • Verilog语言fpga小脚丫数字时钟(整点报时,调时,显示秒钟等功能)

    学弟加油!                                                                       ———来自科大焯人 最近刚好学习了数电有关知识,就做了这个项目(闹钟过于繁琐就没有做了) 希望给还在学习的大伙一点参考,完整代码在最后 在这里先附上两串代码分别是d

    2024年02月07日
    浏览(47)
  • FPGA实验报告 Verilog HDL:7人表决器 巴克码信号发生器 FPGA数字时钟

    写在前面:本文提供以下三个任务的思路讲解和代码实现, 如需参考引脚配置说明,可以点击下方链接跳转查看完整实验报告 ;本实验使用的是Altera公司的cycloneⅢ类型的芯片。 Verilog HDL实现:7人表决器 信号发生器 多功能数字时钟 实验目标:实现7人投票表决电路,支持人

    2024年02月05日
    浏览(46)
  • RTC实时时钟源码分析

    1.先来看一下RTC的配置过程  2.RTC源码讲解 我们的工程中加入了 rtc.c 源文件和 rtc.h头文件,同时,引入了 stm32f10x_rtc.c 和 stm32f10x_bkp.c 库文件。 说明,首先是 RTC_Init,其代码如下: 该函数用来初始化 RTC 时钟,但是只在第一次的时候设置时间,以后如果重新上电/复位都不会再

    2024年02月05日
    浏览(48)
  • RTC实时时钟

    RTC实时时钟通常是指一个集成电路,RTC本质上是一个独立的定时器,通常情况下需要外接一个32.768KHZ的晶振和匹配电容(10~33pf),由于时间是不停止的,为了满足这一要求,所以RTC实时时钟有两种供电方式: 1)在设备正常运行的时候,RTC实时时钟模块是由MCU主电源进行供电

    2024年03月20日
    浏览(42)
  • 实时时钟 RTC(2)

    RTC 使能与停止 RTC 上电后立即启动,不可关闭,软件应在32K 晶体振荡器完全起振后再设置当前时间;在晶体振荡器起振之前芯片使用内部环振计时,偏差较大。 RTC 时间设置 软件可以在任意时刻直接设置RTC 时间寄存器;由于设置时间寄存器的操作与RTC 走时为异步操作关系,

    2024年02月06日
    浏览(37)
  • STM32--RTC实时时钟

    Unix 时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒 。 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量。 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间。 GMT : GMT(Greenwich Mean Time), 格林威治平时(也称格林

    2024年02月10日
    浏览(49)
  • STM32——RTC实时时钟

    Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 时间戳存储在一个秒计数器中,秒计数器为32位/64位的整型变量 世界上所有时区的秒计数器相同,不同时区通过添加偏移来得到当地时间 底层使用秒计数器可以节省硬件设计电路,

    2024年01月23日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包