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"),
.DATA_RATE_TQ("DDR"),
.DATA_WIDTH(4),
.INIT_OQ(1'b0),
.INIT_TQ(1'b0),
.SERDES_MODE("MASTER"),
.SRVAL_OQ(1'b0),
.SRVAL_TQ(1'b0),
.TBYTE_CTL("FALSE"),
.TBYTE_SRC("FALSE"),
.TRISTATE_WIDTH(4)
)
OSERDESE2_inst (
.OFB(OFB),
.OQ(OQ),
.SHIFTOUT1(SHIFTOUT1),
.SHIFTOUT2(SHIFTOUT2),
.TBYTEOUT(TBYTEOUT),
.TFB(TFB),
.TQ(TQ),
.CLK(CLK),
.CLKDIV(CLKDIV),
.D1(D1),
.D2(D2),
.D3(D3),
.D4(D4),
.D5(D5),
.D6(D6),
.D7(D7),
.D8(D8),
.OCE(OCE),
.RST(RST),
.SHIFTIN1(SHIFTIN1),
.SHIFTIN2(SHIFTIN2),
.T1(T1),
.T2(T2),
.T3(T3),
.T4(T4),
.TBYTEIN(TBYTEIN),
.TCE(TCE)
);
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
5.5 调用OSERDESE2级联原语
module oserdese2_10to1 (
input sys_rstn ,
input clk ,
input clk_5x ,
input [9:0] data_in ,
output data_out
);
wire SLAVE_SHIFTOUT1 ;
wire SLAVE_SHIFTOUT2 ;
OSERDESE2 #(
.DATA_RATE_OQ("DDR"),
.DATA_RATE_TQ("SDR"),
.DATA_WIDTH(10),
.INIT_OQ(1'b0),
.INIT_TQ(1'b0),
.SERDES_MODE("MASTER"),
.SRVAL_OQ(1'b0),
.SRVAL_TQ(1'b0),
.TBYTE_CTL("FALSE"),
.TBYTE_SRC("FALSE"),
.TRISTATE_WIDTH(1)
)
OSERDESE2_master (
.OFB(),
.OQ(data_out),
.SHIFTOUT1(),
.SHIFTOUT2(),
.TBYTEOUT(),
.TFB(),
.TQ(),
.CLK(clk_5x),
.CLKDIV(clk),
.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),
.RST(!sys_rstn),
.SHIFTIN1(SLAVE_SHIFTOUT1),
.SHIFTIN2(SLAVE_SHIFTOUT2),
.T1(1'b0),
.T2(1'b0),
.T3(1'b0),
.T4(1'b0),
.TBYTEIN(1'b0),
.TCE(1'b0)
);
OSERDESE2 #(
.DATA_RATE_OQ("DDR"),
.DATA_RATE_TQ("SDR"),
.DATA_WIDTH(10),
.INIT_OQ(1'b0),
.INIT_TQ(1'b0),
.SERDES_MODE("SLAVE"),
.SRVAL_OQ(1'b0),
.SRVAL_TQ(1'b0),
.TBYTE_CTL("FALSE"),
.TBYTE_SRC("FALSE"),
.TRISTATE_WIDTH(1)
)
OSERDESE2_slave (
.OFB(),
.OQ(),
.SHIFTOUT1(SLAVE_SHIFTOUT1),
.SHIFTOUT2(SLAVE_SHIFTOUT2),
.TBYTEOUT(),
.TFB(),
.TQ(),
.CLK(clk_5x),
.CLKDIV(clk),
.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),
.RST(!sys_rstn),
.SHIFTIN1(),
.SHIFTIN2(),
.T1(1'b0),
.T2(1'b0),
.T3(1'b0),
.T4(1'b0),
.TBYTEIN(1'b0),
.TCE(1'b0)
);
endmodule
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
接下来把上面所有模块都用顶层文件调用起来,框图如下:

六、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 ;
reg hs_in_reg ;
reg de_in_reg ;
reg [11:0] v_cnt ;
reg [11:0] h_cnt ;
reg [7:0] grid_data ;
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;
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"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
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 ,
output tmds_clk_n ,
output [2:0] tmds_data_p ,
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"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
连接后的系统框图如下:

七、显示结果
经过全编译以及下板后,将HDMI接口连接到显示器可以看到如下画面:

画面成功显示16*16的黑白交替方格,我们打开显示器的显示信息观察:

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

显示色彩也没问题。
参考
《High-Definition Multimedia Interface Specification Version 1.4b 》
《UG471》
评论记录:
回复评论: