5.3 OSERDESE2 配置属性信号说明

class="table-box">
端口名称端口说明
DATA_RATE_OQ定义数据是以单倍数据速率 (SDR) 还是双倍数据速率 (DDR) 进行处理
DATA_RATE_TQ定义是否将三态控制处理为单数据速率 (SDR) 还是双数据速率 (DDR)
DATA_WIDTH定义并串转换器的并行数据输入宽度。此属性的可能值取决于 DATA_RATE_OQ 属性。当 DATA_RATE_OQ 设置为 SDR 时,DATA_WIDTH 属性的可能值为 2、3、4、5、6、7 和 8。当 DATA_RATE_OQ 设置为 DDR 时,DATA_WIDTH 属性的可能值为 4、6、8、10 和 14。当 DATA_WIDTH 设置为大于 8 的宽度时,必须将一对 OSERDES 配置为主从配置
INIT_OQ定义 OQ 输出的初始值
INIT_OQ定义 TQ 输出的初始值
SERDES_MODE定义使用宽度扩展时 OSERDES 模块是主模块还是从模块
SRVAL_OQ定义调用 SR 时OQ输出的值
SRVAL_TQ调用 SR 时 TQ 输出的值
TBYTE_CTL DDR3 模式启用三态 BYTE 操作。这允许三态信号从作为源的三态输出之一获取值
TBYTE_SRC启用 OSERDES 作为 DDR3 模式下三态字节操作的源
TRISTATE_WIDTH定义 3 态控制并串转换器的并行 3 态输入宽度。此属性的可能值取决于 DATA_RATE_TQ 属性。当 DATA_RATE_TQ 设置为 SDR 或 BUF 时,TRISTATE_WIDTH 属性只能设置为 1。 当 DATA_RATE_TQ 设置为 DDR 时,TRISTATE_WIDTH 属性的可能值为 4。 TRISTATE_WIDTH 不能设置为大于 4 的宽度。当 DATA_WIDTH 大于 4 时,请将 TRISTATE_WIDTH 设置为 1。
class="table-box">

5.4 OSERDESE2 例化模板

  例化模板如下:

OSERDESE2 #(
      .DATA_RATE_OQ("DDR"),   // DDR, SDR
      .DATA_RATE_TQ("DDR"),   // DDR, BUF, SDR
      .DATA_WIDTH(4),         // Parallel data width (2-8,10,14)
      .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(4)      // 3-state converter width (1,4)
   )
   OSERDESE2_inst (
      .OFB(OFB),             // 1-bit output: Feedback path for data
      .OQ(OQ),               // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1(SHIFTOUT1),
      .SHIFTOUT2(SHIFTOUT2),
      .TBYTEOUT(TBYTEOUT),   // 1-bit output: Byte group tristate
      .TFB(TFB),             // 1-bit output: 3-state control
      .TQ(TQ),               // 1-bit output: 3-state control
      .CLK(CLK),             // 1-bit input: High speed clock
      .CLKDIV(CLKDIV),       // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1(D1),
      .D2(D2),
      .D3(D3),
      .D4(D4),
      .D5(D5),
      .D6(D6),
      .D7(D7),
      .D8(D8),
      .OCE(OCE),             // 1-bit input: Output data clock enable
      .RST(RST),             // 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(T1),
      .T2(T2),
      .T3(T3),
      .T4(T4),
      .TBYTEIN(TBYTEIN),     // 1-bit input: Byte group tristate
      .TCE(TCE)              // 1-bit input: 3-state clock enable
   );
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

5.5 调用OSERDESE2级联原语

module oserdese2_10to1 (
    input                                               sys_rstn    ,   //系统复位
    input                                               clk ,           //并行数据时钟
    input                                               clk_5x  ,       //串行数据时钟,因为10位转1位,使用DDR模式所以是5倍并行时钟
    input           [9:0]                               data_in ,       //需要转换的10bit数据
    output                                              data_out        //转换后的串行数据
);
    
    wire                                                SLAVE_SHIFTOUT1   ;   //级联信号1
    wire                                                SLAVE_SHIFTOUT2   ;   //级联信号2


OSERDESE2 #(
      .DATA_RATE_OQ("DDR"),   // DDR, SDR :设置单倍速率或者双倍速率
      .DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR
      .DATA_WIDTH(10),         // 并行数据位宽
      .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(),                   // 1-bit output: Feedback path for data
      .OQ(data_out),            // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1(),
      .SHIFTOUT2(),
      .TBYTEOUT(),              // 1-bit output: Byte group tristate
      .TFB(),                   // 1-bit output: 3-state control
      .TQ(),                    // 1-bit output: 3-state control
      .CLK(clk_5x),             // 1-bit input: High speed clock
      .CLKDIV(clk),             // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1(data_in[0]),
      .D2(data_in[1]),
      .D3(data_in[2]),
      .D4(data_in[3]),
      .D5(data_in[4]),
      .D6(data_in[5]),
      .D7(data_in[6]),
      .D8(data_in[7]),
      .OCE(1'b1),             // 1-bit input: Output data clock enable
      .RST(!sys_rstn),             // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1(SLAVE_SHIFTOUT1),
      .SHIFTIN2(SLAVE_SHIFTOUT2),
      // 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),     // 1-bit input: Byte group tristate
      .TCE(1'b0)              // 1-bit input: 3-state clock enable
   );

   OSERDESE2 #(
      .DATA_RATE_OQ("DDR"),   // DDR, SDR :设置单倍速率或者双倍速率
      .DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR
      .DATA_WIDTH(10),         // 并行数据位宽
      .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(),                   // 1-bit output: Feedback path for data
      .OQ(),            // 1-bit output: Data path output
      // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
      .SHIFTOUT1(SLAVE_SHIFTOUT1),
      .SHIFTOUT2(SLAVE_SHIFTOUT2),
      .TBYTEOUT(),              // 1-bit output: Byte group tristate
      .TFB(),                   // 1-bit output: 3-state control
      .TQ(),                    // 1-bit output: 3-state control
      .CLK(clk_5x),             // 1-bit input: High speed clock
      .CLKDIV(clk),             // 1-bit input: Divided clock
      // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
      .D1(1'b0),
      .D2(1'b0),
      .D3(data_in[8]),
      .D4(data_in[9]),
      .D5(1'b0),
      .D6(1'b0),
      .D7(1'b0),
      .D8(1'b0),
      .OCE(1'b1),                // 1-bit input: Output data clock enable
      .RST(!sys_rstn),          // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1(),
      .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),     // 1-bit input: Byte group tristate
      .TCE(1'b0)              // 1-bit input: 3-state clock enable
   );

   // End of OSERDESE2_inst instantiation

endmodule
 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  接下来把上面所有模块都用顶层文件调用起来,框图如下:

在这里插入图片描述

六、HDMI显示系统

  以上我们实现了HDMI的发送接口,现在我们将前面的文章《VTC视频时序控制器原理以及Verilog实现》中的VTC模块调用过来,这样就能产生一个正确的视频时序给HDMI接口了,只有时序还是不够,没有数据,因此我们还需要一个TPG模块来产生想要显示的图像数据。

6.1 TPG模块编写

  本次让显示器显示16*16的黑白交替方格代码如下:

module tpg(
    input                                               clk ,
    input                                               rst_n   ,
    input                                               vs_in   ,
    input                                               hs_in   ,
    input                                               de_in   ,
    output  reg                                         vs_out  ,
    output  reg                                         hs_out  ,
    output  reg                                         de_out  ,
    output  reg     [23:0]                              data_out    
);


    reg                                                 vs_in_reg   ;   //对vs信号打一拍
    reg                                                 hs_in_reg   ;   //对hs信号打一拍
    reg                                                 de_in_reg   ;   //对de信号打一拍
    reg             [11:0]                              v_cnt   ; //视频垂直方向,行计数器
    reg             [11:0]                              h_cnt   ; //视频水平方向,列计数器
    reg             [7:0]                               grid_data   ;

//对vs hs de寄存一拍
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)begin
        vs_in_reg <= 1'b0;
        hs_in_reg <= 1'b0;
        de_in_reg <= 1'b0;
    end
    else begin
        vs_in_reg <= vs_in;
        hs_in_reg <= hs_in;
        de_in_reg <= de_in;
    end
end

//列计数器
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        h_cnt <= 12'd0;
    else if(de_in == 1'b1)
        h_cnt <= h_cnt + 1'b1;
    else
        h_cnt <= h_cnt;
end

//行计数器
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        v_cnt <= 12'd0;
    else if (vs_in_reg == 1'b1)
        v_cnt <= 12'd0;
    else if((hs_in == 1'b1)&&(hs_in_reg == 1'b0))
        v_cnt <= v_cnt + 1'b1;
    else
        v_cnt <= v_cnt;
end

always @(posedge clk)begin
	grid_data <= ((v_cnt[4]==1'b1) ^ (h_cnt[4]==1'b1)) ? 8'h00 : 8'hff; //方格大小16*16,黑白交替
end

always @(posedge clk)begin
	vs_out  <= vs_in_reg;
    hs_out  <= hs_in_reg;
    de_out  <= de_in_reg;
    data_out  <={grid_data,grid_data,grid_data};
end

endmodule

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

6.2 显示系统顶层模块

  参考文章《VTC视频时序控制器原理以及Verilog实现》里的常见信号长度表可知:如果要显示19201080P的画面,并行时钟就需要148.5M,TMDS编码需要5倍的时钟,则还需要生成一个742.5M时钟,显然这对FPGA来说有点难度。因此本次实验显示一个1280720*60HZ的画面,这样只需要生成74.25M并行时钟以及371.25M的串行时钟。现在通过一个顶层文件,把PLL模块、VTC模块,TPG模块以及HDMI模块链接起来,代码如下:

module hdmi_display_top(
    input                                               sys_clk ,

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

    wire                                                locked  ;
    wire                                                vga_clk ;
    wire                                                vga_clk_5x  ;
    wire                                                vs_in   ;
    wire                                                hs_in   ;
    wire                                                de_in   ;
    wire                                                vs_out  ;
    wire                                                hs_out  ;
    wire                                                de_out  ;
    wire            [23:0]                              data_out    ;


clk_wiz_0 u_clk
(
    .clk_out1       (vga_clk        ),     
    .clk_out2       (vga_clk_5x     ),     
    .locked         (locked         ),       
    .clk_in1        (sys_clk        )
);      

tpg u_tpg(
    .clk            ( vga_clk       ),
    .rst_n          ( locked        ),
    .vs_in          ( vs_in         ),
    .hs_in          ( hs_in         ),
    .de_in          ( de_in         ),
    .vs_out         ( vs_out        ),
    .hs_out         ( hs_out        ),
    .de_out         ( de_out        ),
    .data_out       ( data_out      )
);

vtc#(
    .H_SYNC           ( 40          ),
    .H_BACK_PORCH     ( 220         ),
    .H_ACTIVE         ( 1280        ),
    .H_FRONT_PORCH    ( 110         ),
    .V_SYNC           ( 5           ),
    .V_BACK_PORCH     ( 20          ),
    .V_ACTIVE         ( 720         ),
    .V_FRONT_PORCH    ( 5           )
)u_vtc(   
    .clk              ( vga_clk      ),
    .rst_n            ( locked       ),
    .vs               ( vs_in        ),
    .hs               ( hs_in        ),
    .de               ( de_in        ),
    .h_end            (              )
);

hdmi_trans_top u_hdmi_trans_top(
    .clk          ( vga_clk             ),
    .clk_5x       ( vga_clk_5x          ),
    .sys_rstn     ( locked              ),
    .video_din    ( data_out            ),
    .video_hsync  ( hs_out              ),
    .video_vsync  ( vs_out              ),
    .video_de     ( de_out              ),
    .tmds_clk_p   ( tmds_clk_p          ),
    .tmds_clk_n   ( tmds_clk_n          ),
    .tmds_data_p  ( tmds_data_p         ),
    .tmds_data_n  ( tmds_data_n         )
);


endmodule

 class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">

  连接后的系统框图如下:
在这里插入图片描述

七、显示结果

  经过全编译以及下板后,将HDMI接口连接到显示器可以看到如下画面:
在这里插入图片描述

  画面成功显示16*16的黑白交替方格,我们打开显示器的显示信息观察:
在这里插入图片描述

  显示器信息显示当前输入的是HDMI信号,分辨率为1280×720@60HZ,因此本次HDMI接口成功实现。再修改一下TPG的显示数据,让屏幕显示七色彩条,显示结果如下:

在这里插入图片描述
  显示色彩也没问题。


参考

《High-Definition Multimedia Interface Specification Version 1.4b 》
《UG471》

注:本文转载自blog.csdn.net的爱奔跑的虎子的文章"https://blog.csdn.net/qq_43156031/article/details/139600968"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接

评论记录:

未查询到任何数据!