一、HDMI接口的簡要介紹
最先接觸到的時VGA那么兩者有什么區別呢?主要區別如下:
1、HDMI接口:是數字信號接口,可傳輸音頻和視頻,硬件接口較小,支持熱插拔。
2、VGA接口:是模擬信號接口,只可傳輸視頻流數據,硬件接口較大,雖說不支持熱插拔,但是也沒什么問題,損壞顯卡而已。
HDMI接口就是在VGA接口的基礎上發展而來的,至於HDMI接口為什么可以做到那么小,主要是數據與VGA不同,是串行傳輸的。HDMI的實現方法有兩種,一種是使用HDMI芯片,另一種因為HDMI協議本身就是數字協議,所以我們來使用IO模擬,本次實驗使用的是第二種方法。
二、數據手冊中給出的HDMI協議簡介:
1、從西面的結構圖看一看出,一個HDMI包括三個TMDS數據通道,一個TMDS時鍾通道。TMDS是中通道以某種低唱的速率運行。該速率和視屏的圖像速率成比例。在每個TMDS通道中每一個都發送10bit 的數據。這個10位的字被編碼。采用8bit---10bit 的數據編碼方式。
2、輸入到信源端的數據;視屏像素、數據包、以及控制數據。數據包包括音頻數據和輔助以及相關的糾錯碼。
3、我們現在只是用到了圖傳數據,主要包括:chanel0的像素通道和行場時序;chanel1的像素通道;chanel2的像素通道。

用到的資源所組成的框圖:當然這只是大概框圖。

三、分模塊實現
1、VGA驅動模塊,這個模塊都不模式,直接上框圖:

注意:o_de 信號是指當靜茹有效顯示區域是,此信號拉高。是為了后面的編碼數據坐標值使用,當此信號拉高是開始,進行編碼轉換。實現的代碼如下:vga_drive.v
1 `timescale 1ns / 1ps 2 ////////////////////////////////////////////////////////////////////////////////// 3 // Company: 4 // Engineer: 5 // 6 // Create Date: 2020/06/26 16:37:42 7 // Design Name: 8 // Module Name: vga_drive 9 // Project Name: 10 // Target Devices: 11 // Tool Versions: 12 // Description: 13 // 14 // Dependencies: 15 // 16 // Revision: 17 // Revision 0.01 - File Created 18 // Additional Comments: 19 // 20 ////////////////////////////////////////////////////////////////////////////////// 21 22 module vga_drive ( 23 //system signals 24 input wire sclk , 25 input wire s_rst_n , 26 //vga interfaces 27 output reg [7:0] vga_r , 28 output reg [7:0] vga_g , 29 output reg [7:0] vga_b , 30 output wire o_hs , 31 output wire o_vs , 32 output reg o_de 33 34 35 ); 36 37 //========================================================================\ 38 // =========== Define Parameter and Internal signals =========== 39 //========================================================================/ 40 41 //480 X 640 @ 60HZ 42 43 parameter H_total_time = 800 ; 44 parameter H_sync_time = 96 ; 45 parameter H_back_porch = 40 ; 46 parameter H_left_border = 8 ; 47 parameter H_addr_time = 640 ; 48 49 parameter V_total_time = 525 ; 50 parameter V_sync_time = 2 ; 51 parameter V_back_porch = 25 ; 52 parameter V_top_border = 8 ; 53 parameter V_addr_time = 480 ; 54 55 56 reg [9:0] vga_h_cnt ; 57 reg [9:0] vga_v_cnt ; 58 59 60 //============================================================================= 61 //**************************** Main Code ******************************* 62 //============================================================================= 63 //vga_h_cnt 64 always @ (posedge sclk or negedge s_rst_n) begin 65 if(s_rst_n == 1'b0) 66 vga_h_cnt <= 'd0 ; 67 else if(vga_h_cnt == (H_total_time-1)) 68 vga_h_cnt <= 10'd0 ; 69 else 70 vga_h_cnt <= vga_h_cnt + 1'b1 ; 71 end 72 73 assign o_hs = (vga_h_cnt < H_sync_time ) ? 1'b1: 1'b0 ; 74 //vga_v_cnt 75 always @ (posedge sclk or negedge s_rst_n) begin 76 if(s_rst_n == 1'b0) 77 vga_v_cnt <= 10'd0 ; 78 else if(vga_v_cnt == (V_total_time-1)&&(H_total_time-1)) 79 vga_v_cnt <= 10'd0 ; 80 else if(vga_h_cnt == (H_total_time-1)) 81 vga_v_cnt <= vga_v_cnt + 1'b1 ; 82 end 83 84 assign o_vs = (vga_v_cnt < V_sync_time ) ? 1'b1 : 1'b0 ; 85 86 //generate RGB band 87 always @ (posedge sclk or negedge s_rst_n) begin 88 if(s_rst_n == 1'b0) 89 {vga_r,vga_g,vga_b} <= 24'h0 ; 90 else if((vga_h_cnt>=(H_sync_time + H_back_porch + H_left_border-1) && vga_h_cnt <(H_sync_time + H_back_porch + H_left_border-1+H_addr_time)) 91 && (vga_v_cnt>=(V_sync_time+V_top_border+V_back_porch-1) && vga_v_cnt<(V_sync_time+V_top_border+V_back_porch-1+160))) 92 {vga_r,vga_g,vga_b} <= {8'hff,8'h00,8'h00} ; 93 else if(vga_h_cnt>=(H_sync_time + H_back_porch + H_left_border-1) && vga_h_cnt <(H_sync_time + H_back_porch + H_left_border-1+H_addr_time) 94 && (vga_v_cnt>=(V_sync_time+V_top_border+V_back_porch-1+160) && vga_v_cnt<(V_sync_time+V_top_border+V_back_porch-1+320))) 95 {vga_r,vga_g,vga_b} <= {8'h00,8'hff,8'h00} ; 96 else if(vga_h_cnt>=(H_sync_time + H_back_porch + H_left_border-1) && vga_h_cnt <(H_sync_time + H_back_porch + H_left_border-1+H_addr_time) 97 && (vga_v_cnt>=(V_sync_time+V_top_border+V_back_porch-1+320) && vga_v_cnt<(V_sync_time+V_top_border+V_back_porch-1+V_addr_time))) 98 {vga_r,vga_g,vga_b} <= {8'h00,8'h00,8'hff} ; 99 else 100 {vga_r,vga_g,vga_b} <= 24'h0 ; 101 end 102 //o_de 103 always @ (posedge sclk or negedge s_rst_n) begin 104 if(s_rst_n == 1'b0) 105 o_de <= 1'b0 ; 106 else if(vga_h_cnt>=(H_sync_time + H_back_porch + H_left_border-1) && vga_h_cnt <(H_sync_time + H_back_porch + H_left_border-1+H_addr_time) 107 && (vga_v_cnt>=(V_sync_time+V_top_border+V_back_porch-1+320) && vga_v_cnt<(V_sync_time+V_top_border+V_back_porch-1+V_addr_time))) 108 o_de <= 1'b1 ; 109 end 110 endmodule
2、8bit --10bit的編碼模塊實現。這個模塊並不是自己實現的,而是官網上面有的。可以自行下載。把模塊圖和代碼貼在這邊,方便理解和使用。

如上圖模塊所示:其中在通道0 中使用到了c1和c2端口用來傳V-sync,h_sync.其他兩個通道都沒有用到c1和c0.這里的復位信號是是高復位有效。實現代碼:encode.v
1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // Xilinx, Inc. 2008 www.xilinx.com 4 // 5 ////////////////////////////////////////////////////////////////////////////// 6 // 7 // File name : encode.v 8 // 9 // Description : TMDS encoder 10 // 11 // Date - revision : Jan. 2008 - v 1.0 12 // 13 // Author : Bob Feng 14 // 15 // Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are 16 // provided to you "as is". Xilinx and its licensors make and you 17 // receive no warranties or conditions, express, implied, 18 // statutory or otherwise, and Xilinx specifically disclaims any 19 // implied warranties of merchantability, non-infringement,or 20 // fitness for a particular purpose. Xilinx does not warrant that 21 // the functions contained in these designs will meet your 22 // requirements, or that the operation of these designs will be 23 // uninterrupted or error free, or that defects in the Designs 24 // will be corrected. Furthermore, Xilinx does not warrantor 25 // make any representations regarding use or the results of the 26 // use of the designs in terms of correctness, accuracy, 27 // reliability, or otherwise. 28 // 29 // LIMITATION OF LIABILITY. In no event will Xilinx or its 30 // licensors be liable for any loss of data, lost profits,cost 31 // or procurement of substitute goods or services, or for any 32 // special, incidental, consequential, or indirect damages 33 // arising from the use or operation of the designs or 34 // accompanying documentation, however caused and on any theory 35 // of liability. This limitation will apply even if Xilinx 36 // has been advised of the possibility of such damage. This 37 // limitation shall apply not-withstanding the failure of the 38 // essential purpose of any limited remedies herein. 39 // 40 // Copyright © 2006 Xilinx, Inc. 41 // All rights reserved 42 // 43 ////////////////////////////////////////////////////////////////////////////// 44 `timescale 1 ps / 1ps 45 46 module encode ( 47 input clkin, // pixel clock input 48 input rstin, // async. reset input (active high) 49 input [7:0] din, // data inputs: expect registered 50 input c0, // c0 input 51 input c1, // c1 input 52 input de, // de input 53 output reg [9:0] dout // data outputs 54 ); 55 56 //////////////////////////////////////////////////////////// 57 // Counting number of 1s and 0s for each incoming pixel 58 // component. Pipe line the result. 59 // Register Data Input so it matches the pipe lined adder 60 // output 61 //////////////////////////////////////////////////////////// 62 reg [3:0] n1d; //number of 1s in din 63 reg [7:0] din_q; 64 65 always @ (posedge clkin) begin 66 n1d <= din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7]; 67 68 din_q <= din; 69 end 70 71 /////////////////////////////////////////////////////// 72 // Stage 1: 8 bit -> 9 bit 73 // Refer to DVI 1.0 Specification, page 29, Figure 3-5 74 /////////////////////////////////////////////////////// 75 wire decision1; 76 77 assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0)); 78 /* 79 reg [8:0] q_m; 80 always @ (posedge clkin) begin 81 q_m[0] <=#1 din_q[0]; 82 q_m[1] <=#1 (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]); 83 q_m[2] <=#1 (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]); 84 q_m[3] <=#1 (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]); 85 q_m[4] <=#1 (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]); 86 q_m[5] <=#1 (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]); 87 q_m[6] <=#1 (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]); 88 q_m[7] <=#1 (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]); 89 q_m[8] <=#1 (decision1) ? 1'b0 : 1'b1; 90 end 91 */ 92 wire [8:0] q_m; 93 assign q_m[0] = din_q[0]; 94 assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]); 95 assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]); 96 assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]); 97 assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]); 98 assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]); 99 assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]); 100 assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]); 101 assign q_m[8] = (decision1) ? 1'b0 : 1'b1; 102 103 ///////////////////////////////////////////////////////// 104 // Stage 2: 9 bit -> 10 bit 105 // Refer to DVI 1.0 Specification, page 29, Figure 3-5 106 ///////////////////////////////////////////////////////// 107 reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_m 108 always @ (posedge clkin) begin 109 n1q_m <= q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]; 110 n0q_m <= 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]); 111 end 112 113 parameter CTRLTOKEN0 = 10'b1101010100; 114 parameter CTRLTOKEN1 = 10'b0010101011; 115 parameter CTRLTOKEN2 = 10'b0101010100; 116 parameter CTRLTOKEN3 = 10'b1010101011; 117 118 reg [4:0] cnt; //disparity counter, MSB is the sign bit 119 wire decision2, decision3; 120 121 assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m); 122 ///////////////////////////////////////////////////////////////////////// 123 // [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)] 124 ///////////////////////////////////////////////////////////////////////// 125 assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m)); 126 127 //////////////////////////////////// 128 // pipe line alignment 129 //////////////////////////////////// 130 reg de_q, de_reg; 131 reg c0_q, c1_q; 132 reg c0_reg, c1_reg; 133 reg [8:0] q_m_reg; 134 135 always @ (posedge clkin) begin 136 de_q <= de; 137 de_reg <= de_q; 138 139 c0_q <= c0; 140 c0_reg <= c0_q; 141 c1_q <= c1; 142 c1_reg <= c1_q; 143 144 q_m_reg <= q_m; 145 end 146 147 /////////////////////////////// 148 // 10-bit out 149 // disparity counter 150 /////////////////////////////// 151 always @ (posedge clkin or posedge rstin) begin 152 if(rstin) begin 153 dout <= 10'h0; 154 cnt <= 5'h0; 155 end else begin 156 if (de_reg) begin 157 if(decision2) begin 158 dout[9] <= ~q_m_reg[8]; 159 dout[8] <= q_m_reg[8]; 160 dout[7:0] <= (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0]; 161 162 cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + n1q_m - n0q_m); 163 end else begin 164 if(decision3) begin 165 dout[9] <= 1'b1; 166 dout[8] <= q_m_reg[8]; 167 dout[7:0] <= ~q_m_reg[7:0]; 168 169 cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m); 170 end else begin 171 dout[9] <= 1'b0; 172 dout[8] <= q_m_reg[8]; 173 dout[7:0] <= q_m_reg[7:0]; 174 175 cnt <= cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m); 176 end 177 end 178 end else begin 179 case ({c1_reg, c0_reg}) 180 2'b00: dout <= CTRLTOKEN0; 181 2'b01: dout <= CTRLTOKEN1; 182 2'b10: dout <= CTRLTOKEN2; 183 default: dout <= CTRLTOKEN3; 184 endcase 185 186 cnt <= 5'h0; 187 end 188 end 189 end 190 191 endmodule
3、par2serders 模塊實現,就是總體框圖中的並轉串模塊。主要是調用了select_i/o的IP。配置為輸出模式,DDR的輸出(雙邊輸出模式)。輸出位寬為1bit ,長度是10.數據模式采用差分模式(和板子的電路圖有關);時鍾設置為單端模式。
產生IP。復位也是高電平有效。
1 selectio_wiz_0 chanel_2 2 ( 3 .data_out_from_device(temd_red), // input [9:0] data_out_from_device 4 .data_out_to_pins_p(hdmi_data_p[2]), // output [0:0] data_out_to_pins_p 5 .data_out_to_pins_n(hdmi_data_p[2]), // output [0:0] data_out_to_pins_n 6 .clk_in(clk_125M), // input clk_in 7 .clk_div_in(clk_25M), // input clk_div_in 8 .io_reset(~locked) // input io_reset 9 );
4、頂層模塊.把所有的子模塊實例化進去。這里主要涉及到一個時鍾的問題。因為數據經過selec_io ,也就是說,VGA的像素時鍾是25MHz,是並行輸入的。一下子輸入10Bit。然而並轉串模塊,需要一個一個的輸出。對時鍾就有要求了。在相同的時間內要保值正常工做,那么我的船型輸出時鍾,就得加倍。具體加多少倍呢。這和我們選擇的select_io的輸出出發模式有關。我們選擇的DDR觸發,也就是一個時鍾周期輸出兩個數據。那么可以的出串行輸出的時鍾為=10bit/2 *25MHz = 125MHz.所以PLL模塊如下:
1 clk_wiz_0 instance_name 2 ( 3 // Clock out ports 4 .clk_out1(clk_25M), // output clk_out1 25M 5 .clk_out2(clk_125M), // output clk_out2 125M 6 // Status and control signals 7 .reset(~s_rst_n), // input reset 8 .locked(locked), // output locked 9 // Clock in ports 10 .clk_in1_p(sclk_p), // input clk_in1_p 11 .clk_in1_n(sclk_n)); // input clk_in1_n
選用差分時鍾,是因為板子上給到HDMI的時鍾是差分的。
頂層模塊代碼:HDMI_TOP.v
1 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 // Project Name : 3 // Website : https://home.cnblogs.com/lgy-gdeu/ 4 // Author : LGY GUET Uiversity 5 // Weixin : li15226499835 6 // Email : 15277385992@163.com 7 // File : 8 // Create : 2020 9 // Revise : 10 // Editor : sublime text{SUBLIME_VERSION}, tab size ({TABS}) 11 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 12 // Modification History: 13 // Date By Version Change Description 14 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 // {DATE} {TIME} LGY 1.0 ++++++++++++++++ 16 // ********************************************************************************* 17 `timescale 1ns/1ns 18 19 module hdmi_top( 20 //systerm 21 input wire sclk_p ,//zedboard sigle clock port 22 input wire sclk_n , 23 input wire s_rst_n , 24 25 //hdmi 26 output wire [2:0] hdmi_data_p , 27 output wire [2:0] hdmi_data_n , 28 output wire hdmi_clk_p , 29 output wire hdmi_clk_n , 30 output wire hdmi_oen 31 ); 32 33 //========================================================================\ 34 // ################ Define Parameter and Internal signals ################ 35 //========================================================================/ 36 wire [7:0] vga_r ; 37 wire [7:0] vga_g ; 38 wire [7:0] vga_b ; 39 wire vga_hs ; 40 wire vga_vs ; 41 wire vga_de ; 42 43 44 wire clk_25M ;//vga pxil clock 25M 45 wire clk_125M ;//chuan xingshizhong xuyao 5 bei 46 47 //8-10bit 48 wire [9:0] temd_red ; 49 wire [9:0] temd_green; 50 wire [9:0] temd_blue ; 51 wire locked ; 52 53 54 //============================================================================= 55 //+++++++++++++++++++++++++ Main Code +++++++++++++++++++++++++++++++ 56 //============================================================================= 57 assign hdmi_oen = vga_de; 58 59 clk_wiz_0 instance_name 60 ( 61 // Clock out ports 62 .clk_out1(clk_25M), // output clk_out1 25M 63 .clk_out2(clk_125M), // output clk_out2 125M 64 // Status and control signals 65 .reset(~s_rst_n), // input reset 66 .locked(locked), // output locked 67 // Clock in ports 68 .clk_in1_p(sclk_p), // input clk_in1_p 69 .clk_in1_n(sclk_n)); // input clk_in1_n 70 71 72 vga_drive inst_vga_drive ( 73 .sclk (clk_25M), 74 .s_rst_n (s_rst_n), 75 .vga_r (vga_r), 76 .vga_g (vga_g), 77 .vga_b (vga_b), 78 .o_hs (vga_hs), 79 .o_vs (vga_vs), 80 .o_de (vga_de) 81 ); 82 83 encode encode_R ( 84 .clkin (clk_25M),// pixel clock input 85 .rstin (~locked),// async. reset input (active high) 86 .din (vga_r),// data inputs: expect registered 87 .c0 (1'b0),// c0 input 88 .c1 (1'b0),// c1 input 89 .de (vga_de),// de input 90 .dout (temd_red)// data outputs 91 ); 92 93 encode encode_G ( 94 .clkin (clk_25M),// pixel clock input 95 .rstin (~locked),// async. reset input (active high) 96 .din (vga_g),// data inputs: expect registered 97 .c0 (1'b0),// c0 input 98 .c1 (1'b0),// c1 input 99 .de (vga_de),// de input 100 .dout (temd_green)// data outputs 101 ); 102 103 encode encode_B ( 104 .clkin (clk_25M),// pixel clock input 105 .rstin (~locked),// async. reset input (active high) 106 .din (vga_b),// data inputs: expect registered 107 .c0 (vga_hs),// c0 input 108 .c1 (vga_vs),// c1 input 109 .de (vga_de),// de input 110 .dout (temd_blue)// data outputs 111 ); 112 113 selectio_wiz_0 chanel_0 114 ( 115 .data_out_from_device(temd_blue), // input [9:0] data_out_from_device 116 .data_out_to_pins_p(hdmi_data_p[0]), // output [0:0] data_out_to_pins_p 117 .data_out_to_pins_n(hdmi_data_p[0]), // output [0:0] data_out_to_pins_n 118 .clk_in(clk_125M), // input clk_in 119 .clk_div_in(clk_25M), // input clk_div_in 120 .io_reset(~locked) // input io_reset 121 ); 122 123 selectio_wiz_0 chanel_1 124 ( 125 .data_out_from_device(temd_green), // input [9:0] data_out_from_device 126 .data_out_to_pins_p(hdmi_data_p[1]), // output [0:0] data_out_to_pins_p 127 .data_out_to_pins_n(hdmi_data_p[1]), // output [0:0] data_out_to_pins_n 128 .clk_in(clk_125M), // input clk_in 129 .clk_div_in(clk_25M), // input clk_div_in 130 .io_reset(~locked) // input io_reset 131 ); 132 133 selectio_wiz_0 chanel_2 134 ( 135 .data_out_from_device(temd_red), // input [9:0] data_out_from_device 136 .data_out_to_pins_p(hdmi_data_p[2]), // output [0:0] data_out_to_pins_p 137 .data_out_to_pins_n(hdmi_data_p[2]), // output [0:0] data_out_to_pins_n 138 .clk_in(clk_125M), // input clk_in 139 .clk_div_in(clk_25M), // input clk_div_in 140 .io_reset(~locked) // input io_reset 141 ); 142 143 selectio_wiz_0 chanel_clk 144 ( 145 .data_out_from_device(10'b11111_00000), // input [9:0] data_out_from_device 146 .data_out_to_pins_p(hdmi_clk_p), // output [0:0] data_out_to_pins_p 147 .data_out_to_pins_n(hdmi_clk_p), // output [0:0] data_out_to_pins_n 148 .clk_in(clk_125M), // input clk_in 149 .clk_div_in(clk_25M), // input clk_div_in 150 .io_reset(~locked) // input io_reset 151 ); 152 153 endmodule
總體框圖:么畫完,有點丑。抽時間再畫

