本原創文章由深圳市小眼睛科技有限公司創作,版權歸本公司所有,如需轉載,需授權并注明出處(www.meyesemi.com)
1. 實驗簡介
實驗目的:
? ? ??完成 HDMI 回環實驗
實驗環境:
? ? ? Window11
? ? ? PDS2022.2-SP6.4
硬件環境:
? ? ??MES2L676-100HP
2. 實驗原理
? ? ??HDMI 輸入接口采用宏晶微 MS7200 HMDI 接收芯片,HDMI 輸出接口采用宏晶微 MS7210 HMDI 發送芯片。 芯片兼容 HDMI1.4b 及以下標準視頻的 3D 傳輸格式,最高分辨率高達 4K@30Hz,最高采樣率達到 300MHz, 支持 YUV 和 RGB 之間的色彩空間轉換,數字接口支持 YUV 及 RGB 格式。
? ? ??MS7200 和 MS7210 的 IIC 配置接口與 FPGA 的 IO 相連,通過 FPGA 的編程來對芯片進行初始化和配置操作。
? ? ??MES2L100HP 開發板上將 MS7200 的 SA 管腳下拉到地,故 IIC 的 ID 地址為 0x56,將 MS7210 的 SA 管腳 上拉到電源電壓,故 IIC 的 ID 地址為 0xB2。
2.1. 顯示原理
? ? ??下圖表示一個 8*8 像素的畫面,圖中每個格子表示一個像素點,顯示圖像時像素點快速點亮的過程按表格中 編號的順序逐個點亮,從左到右,從上到下,按圖中箭頭方向的“Z”字形順序。
?
? ? ??以上圖為例,每行 8 個像素點,每完成一行信號的傳輸,會轉到下一行信號傳輸,直到完成第 8 行數據的傳輸, 就完成了一個畫面的數據傳輸了,一個畫面也稱為一場或一幀,顯示每秒中刷新的幀數稱為幀率。比如 1920*1080P 像素,就是 1 行有效像素點 1920,一場有效行為 1080 行。
? ? ??每個像素點的像素值數據,對應每個像素點的顏色。常見的像素值表示格式比如:RGB888,RGB 分別代表: 紅 R,綠 G,藍 B,888 是指 R、G、B 分別有 8bit,也就是 R、G、B 每一色光有 28=256 級階調,通過 RGB 三色光的 不同組合,一個像素上最多可顯示 24 位的 256*256*256 =16,777,216 色。
? ? ??HDMI 顯示的數據源采用 verilog 編寫的顯示時序產生模塊 sync_vg 實現上圖的時序,彩條生成模塊 pattern_vg 根據像素點所在位置,即列數和行數確定像素值,實現彩條圖案。
2.2. HDMI_PHY 配置
? ? ??MS7200 為 HMDI 接收芯片,MS7210 為 HMDI 發送芯片,芯片的 IIC 配置接口已與 FPGA 的 IO 相連,芯片 正常使用需要通過 FPGA 的對芯片進行初始化和配置操作。寄存器配置切忌修改。具體配置可以參考 demo。
3. 接口列表
頂層模塊接口如下所示:
4. 工程說明
? ? ??系統時鐘 sys_clk 通過 pll 鎖相環 IP 分出 cfg_clk 給到 ms72xx_ctl 模塊,該模塊通過 IIC 配置 MS7200 與 MS7210 芯片。HDMI 輸入的數據經過 MS7200 芯片解碼后轉成標準 RGB 格式的數據輸入到 FPGA 中。再將該數 據輸出到 MS7210 芯片。MS7210 將 RGB 格式的數據編碼成 TMDS 信號對外輸出。
5. 代碼模塊說明
Ms72xx_ctl.v 模塊
module ms72xx_ctl(input clk,input rst_n,output init_over,output iic_tx_scl,inout iic_tx_sda,output iic_scl,inout iic_sda
);reg rstn_temp1, rstn_temp2;reg rstn;always @(posedge clk or negedge rst_n) beginif (!rst_n)rstn_temp1 <= 1'b0;elserstn_temp1 <= rst_n;endalways @(posedge clk) beginrstn_temp2 <= rstn_temp1;rstn <= rstn_temp2;endwire init_over_rx;wire [7:0] device_id_rx;wire iic_trig_rx;wire w_r_rx;wire [15:0] addr_rx /*synthesis PAP_MARK_DEBUG="true"*/;wire [7:0] data_in_rx;wire busy_rx;wire [7:0] data_out_rx;wire byte_over_rx;wire [7:0] device_id_tx;wire iic_trig_tx;wire w_r_tx;wire [15:0] addr_tx /*synthesis PAP_MARK_DEBUG="true"*/;wire [7:0] data_in_tx;wire busy_tx;wire [7:0] data_out_tx;wire byte_over_tx;ms7200_ctl ms7200_ctl(.clk (clk), // input.rstn (rstn), // input.init_over(init_over_rx), // output reg.device_id(device_id_rx), // output [7:0].iic_trig (iic_trig_rx), // output reg.w_r (w_r_rx), // output reg.addr (addr_rx), // output reg [15:0].data_in (data_in_rx), // output reg [7:0].busy (busy_rx), // input.data_out (data_out_rx), // input [7:0].byte_over(byte_over_rx) // input);ms7210_ctl ms7210_ctl(.clk (clk), // input.rstn (init_over_rx), // input.init_over(init_over), // output reg.device_id(device_id_tx), // output [7:0].iic_trig (iic_trig_tx), // output reg.w_r (w_r_tx), // output reg.addr (addr_tx), // output reg [15:0].data_in (data_in_tx), // output reg [7:0].busy (busy_tx), // input.data_out (data_out_tx), // input [7:0].byte_over(byte_over_tx) // input);wire sda_in /*synthesis PAP_MARK_DEBUG="true"*/;wire sda_out /*synthesis PAP_MARK_DEBUG="true"*/;wire sda_out_en /*synthesis PAP_MARK_DEBUG="true"*/;iic_dri #(.CLK_FRE (27'd10_000_000), // system clock frequency.IIC_FREQ (20'd400_000), // I2c clock frequency.T_WR (10'd1), // I2c transmit delay ms.ADDR_BYTE (2'd2), // I2C addr byte number.LEN_WIDTH (8'd3), // I2C transmit byte width.DATA_BYTE (2'd1) // I2C data byte number) iic_dri_rx (.clk (clk),.rstn (rstn),.device_id (device_id_rx),.pluse (iic_trig_rx), // I2C transmit trigger.w_r (w_r_rx), // I2C transmit direction 1:send 0:receive.byte_len (4'd1), // I2C transmit data byte length.addr (addr_rx), // I2C transmit addr.data_in (data_in_rx), // I2C send data.busy (busy_rx), // I2C bus status.byte_over (byte_over_rx), // I2C byte transmit over flag.data_out (data_out_rx), // I2C receive data.scl (iic_scl),.sda_in (sda_in),.sda_out (sda_out),.sda_out_en (sda_out_en));assign iic_sda = sda_out_en ? sda_out : 1'bz;assign sda_in = iic_sda;wire sda_tx_in /*synthesis PAP_MARK_DEBUG="true"*/;wire sda_tx_out /*synthesis PAP_MARK_DEBUG="true"*/;wire sda_tx_out_en /*synthesis PAP_MARK_DEBUG="true"*/;iic_dri #(.CLK_FRE (27'd10_000_000), // system clock frequency.IIC_FREQ (20'd400_000), // I2c clock frequency.T_WR (10'd1), // I2c transmit delay ms.ADDR_BYTE (2'd2), // I2C addr byte number.LEN_WIDTH (8'd3), // I2C transmit byte width.DATA_BYTE (2'd1) // I2C data byte number) iic_dri_tx (.clk (clk),.rstn (rstn),.device_id (device_id_tx),.pluse (iic_trig_tx), // I2C transmit trigger.w_r (w_r_tx), // I2C transmit direction 1:send 0:receive.byte_len (4'd1), // I2C transmit data byte length.addr (addr_tx), // I2C transmit addr.data_in (data_in_tx), // I2C send data.busy (busy_tx), // I2C bus status.byte_over (byte_over_tx), // I2C byte transmit over flag.data_out (data_out_tx), // I2C receive data.scl (iic_tx_scl),.sda_in (sda_tx_in),.sda_out (sda_tx_out),.sda_out_en (sda_tx_out_en));assign iic_tx_sda = sda_tx_out_en ? sda_tx_out : 1'bz;assign sda_tx_in = iic_tx_sda;endmodule
? ? ??該模塊主要完成對 ms7210 和 ms7200 芯片的 IIC 配置。具體代碼不詳細分析,按照 IIC 協議去完成即可, 然后就是配置 ms7210 和 ms7200 的寄存器即可。以下給出 IIC 協議的時序說明,如下圖所示:
? ? ??當 SDA 和 SCL 都處于高電平時,表示空閑狀態,因此在硬件設計時其實也要通過上拉電阻將信號拉高,表示 空閑。當 SCL 保持高電平時,SDA 拉低時表示 IIC 總線啟動,標志一次數據傳輸的開始,在開始前,IIC 總線必須處 于空閑狀態。在數據傳輸過程中,SDA 上逐位串行傳輸每一位數據,在 SCL 高電平期間,SDA 必須保持穩定。當 SCL 為低電平時,SDA 才允許改變。
? ? ??IIC 總線每次傳輸一個字節,也就是傳輸 8 個 bit,每 8bit 后要收到一個來自接收方反饋的 ACK(應答信號), 該應答信號為高電平時,表示接收方接收字節失敗。為低電平時,表示有效。之后,在 SCL 高電平期間,SDA 重新 拉高,則表示傳輸結束,IIC 總線回到空閑狀態。
6. 實驗現象
連接好 MES2L100HP 開發板、視頻源和顯示器;
? ? ? 注意視頻源必須為 1920*1080P@60,下圖為設置分辨率步驟,下載程序,可以看到顯示器顯示與視頻源一致的圖像。
? ? ? 上圖為 FPGA 的 HDMI_OUT 輸出的圖像。
? ? ? 注意事項:
? ? ? 需要插上 HDMI 接口,板子上電時才會對 HDMI 芯片進行配置,否則將配置失敗。
? ? ? 我們對 HDMI 芯片配置時使用的是 RGB888 協議,如果視頻源的顏色格式不是 RGB888,會出現一些問題。 如上圖,視頻源的顏色格式是 YCbCr444,回環實驗中,在顯示器上顯示視頻源的畫面,顯示器上的畫面顏色會偏綠。