0
HDMI显示
这次搞个9K的HDMI例程。
先把源文件放上来,大家看完再测试!
- module elefans03
- (
- input I_clk , //27Mhz
- input I_rst_n ,
- output O_tmds_clk_p_o ,
- output O_tmds_clk_n_o ,
- output [2:0] O_tmds_data_p_o ,//{r,g,b}
- output [2:0] O_tmds_data_n_o
- );
- // 建立几个线 用于连接子模块
- wire I_serial_clk_i;
- wire I_rgb_clk_i;
- wire I_rgb_vs_i ;
- wire I_rgb_hs_i ;
- wire I_rgb_de_i ;
- wire [7:0] I_rgb_r_i ;
- wire [7:0] I_rgb_g_i ;
- wire [7:0] I_rgb_b_i ;
- // 这个地方是倍频,不用多说吧
- wire CLK_SYS;
- Gowin_rPLL Gowin_rPLL_instance(
- .clkout(CLK_SYS), //output clkout
- .clkoutd(I_serial_clk_i), //output clkoutd
- .clkin(I_clk) //input clkin
- );
- // 变量 和上一个内容基本一样
- reg [15:0] PixelCount;
- reg [15:0] LineCount;
- localparam v_total = 16'd628;
- localparam v_fporch = 16'd1;
- localparam v_sync = 16'd4;
- localparam v_bporch = 16'd23;
- localparam v_res = 16'd600;
- localparam h_total = 16'd1056;
- localparam h_fporch = 16'd40;
- localparam h_sync = 16'd128;
- localparam h_bporch = 16'd88;
- localparam h_res = 16'd800;
- // 色带宽度 这次是800 我整了20个色带
- localparam Width_bar = 40;
- // 注意这个地方我们其实操作的还是RGB 不是HDMI 所以我们要用的是RGB_CLK
- // 并不是传输到外面的HDMI_CLK 所以是 40mhz
- // 里面的内容不用多说,和LCD那个一样,时序图的话可以去查一下
- // CTA-861-F 和 VESA DMT
- always @( posedge I_rgb_clk_i or negedge I_rst_n )begin
- if( !I_rst_n ) begin
- LineCount <= 16'b0;
- PixelCount <= 16'b0;
- end
- else if( PixelCount == h_total ) begin
- PixelCount <= 16'b0;
- LineCount <= LineCount + 1'b1;
- end
- else if( LineCount == v_total ) begin
- LineCount <= 16'b0;
- PixelCount <= 16'b0;
- end
- else
- PixelCount <= PixelCount + 1'b1;
- end
- assign I_rgb_de_i = ((PixelCount>=(h_sync+h_bporch))&(PixelCount<=(h_sync+h_bporch+h_res-1'b1)))&
- ((LineCount>=(v_sync+v_bporch))&(LineCount<=(v_sync+v_bporch+v_res-1'b1))) ;
- assign I_rgb_hs_i = ~((PixelCount>=12'd0) & (PixelCount<=(h_sync-1'b1))) ;
- assign I_rgb_vs_i = ~((LineCount>=12'd0) & (LineCount<=(v_sync-1'b1))) ;
- assign I_rgb_r_i = PixelCount
- (PixelCount<(Width_bar*2 + h_sync + h_bporch) ? 8'b00000100 :
- (PixelCount<(Width_bar*3 + h_sync + h_bporch) ? 8'b00001000 :
- (PixelCount<(Width_bar*4 + h_sync + h_bporch) ? 8'b00010000 :
- (PixelCount<(Width_bar*5 + h_sync + h_bporch) ? 8'b00100000 :
- (PixelCount<(Width_bar*6 + h_sync + h_bporch) ? 8'b01000000 :
- (PixelCount<(Width_bar*7 + h_sync + h_bporch) ? 8'b10000000 : 8'b00000000 ))))));
- assign I_rgb_g_i = PixelCount
- (PixelCount<(Width_bar*9 + h_sync + h_bporch) ? 8'b00000010 :
- (PixelCount<(Width_bar*10 + h_sync + h_bporch) ? 8'b00001000 :
- (PixelCount<(Width_bar*11 + h_sync + h_bporch) ? 8'b00010000 :
- (PixelCount<(Width_bar*12 + h_sync + h_bporch) ? 8'b00100000 :
- (PixelCount<(Width_bar*13 + h_sync + h_bporch) ? 8'b01000000 :
- (PixelCount<(Width_bar*14 + h_sync + h_bporch) ? 8'b10000000 : 8'b00000000 ))))));
- assign I_rgb_b_i = PixelCount
- (PixelCount<(Width_bar*16 + h_sync + h_bporch) ? 8'b00001000 :
- (PixelCount<(Width_bar*17 + h_sync + h_bporch) ? 8'b00010000 :
- (PixelCount<(Width_bar*18 + h_sync + h_bporch) ? 8'b00100000 :
- (PixelCount<(Width_bar*19 + h_sync + h_bporch) ? 8'b01000000 :
- (PixelCount<(Width_bar*20 + h_sync + h_bporch) ? 8'b10000000 : 8'b00000000 )))));
- // 分频复制过来的
- Gowin_CLKDIV Gowin_CLKDIV_instance(
- .clkout(I_rgb_clk_i), //output clkout
- .hclkin(I_serial_clk_i), //input hclkin
- .resetn(I_rst_n) //input resetn
- );
- /* 输出的地方我们不用管,直接把他们和HDMI管脚连到一起即可。
- 输入我们可以看到很熟悉,和第二章的驱动LCD一摸一样,所以真的为我们省了很大的麻烦!*/
- DVI_TX_Top DVI_TX_Top_instance(
- .I_rst_n(I_rst_n), //input I_rst_n
- .I_serial_clk(I_serial_clk_i), //input I_serial_clk
- .I_rgb_clk(I_rgb_clk_i), //input I_rgb_clk
- .I_rgb_vs(I_rgb_vs_i), //input I_rgb_vs
- .I_rgb_hs(I_rgb_hs_i), //input I_rgb_hs
- .I_rgb_de(I_rgb_de_i), //input I_rgb_de
- .I_rgb_r(I_rgb_r_i), //input [7:0] I_rgb_r
- .I_rgb_g(I_rgb_g_i), //input [7:0] I_rgb_g
- .I_rgb_b(I_rgb_b_i), //input [7:0] I_rgb_b
- .O_tmds_clk_p(O_tmds_clk_p_o), //output O_tmds_clk_p
- .O_tmds_clk_n(O_tmds_clk_n_o), //output O_tmds_clk_n
- .O_tmds_data_p(O_tmds_data_p_o), //output [2:0] O_tmds_data_p
- .O_tmds_data_n(O_tmds_data_n_o) //output [2:0] O_tmds_data_n
- );
- endmodule
复制代码
9K的HDMI例程官方没有,不过有4K的,4K的是包括摄像头录入数据,然后通过SRAM,然后HDMI显示,很复杂,不适合咱们新手玩,咱们就一个一个功能的玩。官方4K例程没有讲解,我来简单的说一些,不对的话大佬评论。
HDMI要分成两块,一块是数据传输,一块是SPI信息传输,我们先把SPI信息传输抛过去。数据传输这块有4x3=12个线,分别对应着D0 D1 D2 CK,每个线又有P N S,我们这次主要就是要用的4对线,S直接连地了。然后,D0 D1 D2又分别对应RGB,然后我们这次传输就可以传输真实的8位数据了。
不过,LCD有数据手册,HDMI的数据手册去哪里找,也是可以找到的哈,但不要去HDMI那里了,HDMI有两个组织的传输方法,而且都有手册,不过不好整,而且太大的话,主频也需要跟上来,HDMI与LCD不同的一个点还在于,HDMI需要LCD的5倍频率,也就是说,LCD显示一个点的时钟,需要HDMI5个时钟,所以你可以直接去这个地方去找。
我这次显示的是800x600的,我怕我的小9撑不住啊!
值得一提的是,你可以不用真的一个管脚一个管脚的对他进行设置,IP CORE已经给你写好模块,你只需要按照我第2篇文章的思路开搞即可以。
废话不多说,按照我的第1篇文章先创建工程,再次提醒注意芯片选择。
创建以后,还是按照第2篇的内容找一个合适的频率,我就直说了,需要40x5=200mhz,这个地方没那么整数,我选的是0.5的误差。
然后,我们把生成的文件复制过去,然后在进行分频,还是在IP CORE里面选择CLOCK下的CLKDIV分成5倍,如下所示。复制过去。
再然后打开IP CORE,然后选择MultiMedia里面的DVI TX模块,按照我的配置,记得选择ELV那个,还有把用外部始终勾上。也复制过去。
好了,开搞!去开头去取.v文件!
这个地方去绑定脚的时候,会发现拖一个上两个,其实是对的。
烧写成功,看效果,我视频里面的显示器有些老化,其实是色条正确的,只是不明显而已!
|
评分
-
查看全部评分
|