16位 565 DVP 接口实现

  1 module lcd_dvp_drive
  2 #(
  3 parameter VBP= 21,   //OK
  4 parameter VFP= 18,  //OK
  5 parameter VSW= 6 ,  //OK
  6 parameter VDP= 480 ,//524
  7 
  8 parameter HBP= 106,   //ok
  9 parameter HFP= 16,  //ok
 10 parameter HSW= 16 , //ok
 11 parameter HDP= 720   //840
 12 
 13 )
 14 (   
 15      clk_i             ,                //时钟输入 840*524*2*60=52.819MHZ//实测53.82MHZ
 16 
 17      rst_i             ,             //复位输入
 18      display_on        ,             //显示开关输入
 19      data_rgb_i        ,             //16位红色数据输入
 20      data_rdy_o        ,             //数据输入请求信号输出
 21 
 22      hsync_o           ,              //行同步信号输出
 23      vsync_o           ,              //场同步信号输出
 24      lcd_de            ,              //LCD输出有效标志
 25 
 26      pclk_o            ,               //数据时钟输出
 27      Serial_data8_o    ,               //8位数据输出
 28      xpos_o            ,               //当前行计数输出
 29      ypos_o            ,               //当前列计数输出
 30      lcd_bl            ,               //背光开关控制 1亮背光 0灭背光
 31      out_vsync                         //帧复位,高有效 
 32  );
 33 localparam [16:0] HBP_X2= (HBP+HBP);//每个像素发送两次8位数据
 34 localparam [16:0] HFP_X2= (HFP+HFP);//每个像素发送两次8位数据
 35 localparam [16:0] HSW_X2= (HSW+HSW);//每个像素发送两次8位数据 
 36 localparam [16:0] HDP_X2= (HDP+HDP);//每个像素发送两次8位数据 
 37 localparam [16:0] H_TOTAL= (HSW_X2+HBP_X2+HDP_X2+HFP_X2);//每个像素发送两次8位数据
 38 localparam [16:0] V_TOTAL= (VBP+VFP+VSW+VDP);
 39                 
 40 input wire [0:0]  clk_i;
 41 input wire [0:0]  rst_i;
 42 
 43 input wire [0:0]  display_on;
 44 input wire [15:0]  data_rgb_i;
 45 
 46 output wire [0:0]  data_rdy_o;
 47 
 48 output wire  [0:0]  hsync_o;
 49 output wire  [0:0]  vsync_o;
 50 
 51 output wire  [0:0] pclk_o;
 52 output wire  [7:0] Serial_data8_o;
 53 
 54 output wire [15:0] xpos_o;
 55 output wire [15:0] ypos_o;  
 56 
 57 output wire  lcd_bl;
 58 output wire  out_vsync;
 59 output wire  lcd_de;
 60 
 61 reg [16:0]  H_X2CNT_R; 
 62 reg h_cnt_flag;
 63 
 64 reg [16:0]  V_CNT_R;   
 65 
 66 reg hsync_r;
 67 reg vsync_r;
 68 reg enable_r; 
 69 reg lcd_bl_r;
 70 reg [7:0]  Serial_data8_r;
 71 
 72 
 73 
 74 //行计数
 75 always @(negedge clk_i or negedge rst_i )
 76      begin
 77         if(rst_i==1'b0 || display_on==1'b0 )
 78             begin
 79                 h_cnt_flag<=1'b0;
 80             end
 81         else 
 82             begin
 83                 h_cnt_flag<=~h_cnt_flag;     
 84             end  
 85      end       
 86 
 87 always @(negedge clk_i or negedge rst_i )
 88      begin
 89         if(rst_i==1'b0 || display_on==1'b0 )
 90               begin
 91                 H_X2CNT_R<=17'd0;            
 92               end
 93         else if(H_X2CNT_R>=H_TOTAL-1'D1)
 94                 begin
 95                     H_X2CNT_R<=17'd0;                    
 96                 end
 97         else
 98                H_X2CNT_R<=H_X2CNT_R+1'd1;
 99        
100      end  
101                
102 
103 //列计数
104 always @(negedge clk_i or negedge rst_i )
105      begin
106         if(rst_i==1'b0 || display_on==1'b0 )
107                     V_CNT_R<=17'd0;
108         else if((V_CNT_R>=(V_TOTAL-1'D1)) && (H_X2CNT_R>=(H_TOTAL-1'D1)))
109                     V_CNT_R<=17'D0;
110         else if(H_X2CNT_R>=H_TOTAL-1'D1)
111                     V_CNT_R<=V_CNT_R+1'd1;
112              else
113                     V_CNT_R<=V_CNT_R;
114             
115      end  
116 
117 //输出VSYNC信号
118 always @(negedge clk_i or negedge rst_i )
119      begin
120         if(rst_i==1'b0 || display_on==1'b0 )
121             vsync_r<=1'b0;
122         else if((V_CNT_R>=(V_TOTAL-1'D1)) && (H_X2CNT_R>=H_TOTAL-1'D1)) 
123             vsync_r<=1'b0;
124         else if((V_CNT_R>=(VSW-1'd1))&&(H_X2CNT_R>=H_TOTAL-1'D1))
125             vsync_r<=1'b1;
126         else 
127             vsync_r<=vsync_r;
128      
129      end
130      
131 
132 //输出HSYNC信号
133 always @(negedge clk_i or negedge rst_i )
134      begin
135         if(rst_i==1'b0 || display_on==1'b0 )
136             hsync_r<=1'b0;
137         else if((H_X2CNT_R<HSW_X2-1'd1) ||(H_X2CNT_R>=H_TOTAL-1'd1)) 
138             hsync_r<=1'b0;
139         else
140             hsync_r<=1'b1;
141      
142      end     
143      
144 //输出ENABLE信号
145 always @(negedge clk_i or negedge rst_i )
146      begin  
147         if(rst_i==1'b0 || display_on==1'b0  )
148             enable_r<=1'b0;
149         else if((H_X2CNT_R>(HSW_X2+HBP_X2-2'd2)) && (H_X2CNT_R<(HSW_X2+HBP_X2+HDP_X2-1'd1)) && (V_CNT_R>(VSW+VBP-1'd1)) && (V_CNT_R<=(VSW+VBP+VDP-1'd1)))
150             enable_r<=1'b1;          
151         else 
152             enable_r<=1'b0;     
153      end
154      
155   
156 
157           
158 //向外发出数据输入请求
159 assign data_rdy_o=((H_X2CNT_R>(HSW_X2+HBP_X2-2'd2)) && (H_X2CNT_R<(HSW_X2+HBP_X2+HDP_X2-1'd1)) && (V_CNT_R>(VSW+VBP-1'd1)) && (V_CNT_R<=(VSW+VBP+VDP-1'd1)))? 1'b1:1'b0;    
160  
161 //输出当前行计数
162 //assign xpos_o = (data_rdy_o) ? (H_X2CNT_R-HSW_X2-HBP_X2):16'd0;
163 
164 reg [15:0]xpos_r;
165 always @(negedge clk_i or negedge rst_i  )
166      begin
167          if(rst_i==1'b0 || display_on==1'b0 )
168              xpos_r<=16'd0;
169          else if((H_X2CNT_R>(HSW_X2+HBP_X2-2'd2)) && (H_X2CNT_R<(HSW_X2+HBP_X2+HDP_X2-1'd1)) && (V_CNT_R>(VSW+VBP-1'd1)) && (V_CNT_R<=(VSW+VBP+VDP-1'd1)))
170              xpos_r<=(H_X2CNT_R+1'D1-HSW_X2-HBP_X2)/2'D2;
171          else 
172             xpos_r<=16'd0;
173      
174      end
175 //输出当前列计数
176 //assign ypos_o = (data_rdy_o) ? (V_CNT_R-VSW-VBP):16'd0; 
177 reg [15:0] ypos_r;
178 always @(negedge clk_i or negedge rst_i  )
179      begin
180          if(rst_i==1'b0 || display_on==1'b0  )
181              ypos_r<=16'd0;
182          else if((V_CNT_R>(VSW+VBP-1'D1)) && (V_CNT_R<=(VSW+VBP+VDP-1'd1)))
183                  ypos_r<=V_CNT_R-VSW-VBP;
184          else 
185             ypos_r<=16'd0;
186      
187      end
188 
189 
190 
191 
192 //输出显示数据
193 always @(negedge clk_i or negedge rst_i )
194      begin
195         if(rst_i==1'b0 || display_on==1'b0  )
196             begin                
197                 Serial_data8_r<=8'b0;
198                end
199         else if(h_cnt_flag==1'b1)
200                 Serial_data8_r<=data_rgb_i[15:8];                                      
201 
202         else if(h_cnt_flag==1'b0)
203                 Serial_data8_r<=data_rgb_i[7:0];  
204         else
205            begin                
206                 Serial_data8_r<=8'b0;    
207                end
208      
209      end 
210      
211 always @(negedge clk_i or negedge rst_i )
212      begin
213         if(rst_i==1'b0 || display_on==1'b0 )
214             lcd_bl_r<=1'b0;
215         else if(ypos_o>2'd2)
216             begin
217                 lcd_bl_r<=1'b1;
218             end
219         else 
220             begin
221                 lcd_bl_r<=lcd_bl_r;
222             end 
223      end           
224                     
225 //帧复位,高有效               
226 assign out_vsync = ((H_X2CNT_R <= 100) && (V_CNT_R == 1)) ? 1'b1 : 1'b0;
227 
228 assign hsync_o=(display_on==1'b1 )? hsync_r:1'b0 ;
229 assign vsync_o=(display_on==1'b1 )? vsync_r:1'b0 ;
230 assign lcd_de =(display_on==1'b1 )? enable_r:1'b0 ;
231 assign lcd_bl =(display_on==1'b1 )? lcd_bl_r:1'b0 ;
232 
233 
234 assign Serial_data8_o=(((H_X2CNT_R>(HSW_X2+HBP_X2-2'd1)) && (H_X2CNT_R<(HSW_X2+HBP_X2+HDP_X2)) && (V_CNT_R>(VSW+VBP-1'd1)) && (V_CNT_R<=(VSW+VBP+VDP-1'd1))))? Serial_data8_r:8'b0 ;
235 
236 //输出PCLK信号
237 assign pclk_o=(display_on==1'b1 )? clk_i:16'b0 ; 
238 assign xpos_o=(display_on==1'b1 )? xpos_r:16'b0 ;
239 assign ypos_o=(display_on==1'b1 )? ypos_r:16'b0 ;
240      
241     
242 
243 
244 endmodule
 1 `timescale 1ns/100ps
 2 module lcd_dvp_drive_tb();
 3 
 4 reg clk_i;
 5 reg rst_i;
 6 reg display_on;
 7 reg [15:0] data_rgb_i;
 8 wire      hsync_o       ;
 9 wire      vsync_o       ;
10 wire      lcd_de        ;   
11 wire      pclk_o        ;
12 wire[7:0] Serial_data8_o;
13 wire      xpos_o        ;
14 wire      ypos_o        ;
15 wire      lcd_bl        ;
16 wire      out_vsync     ;
17 wire      data_rdy_o    ;
18 
19 
20 initial begin
21             clk_i=1'b0;
22             display_on=0;
23             data_rgb_i=16'h0000;
24             rst_i=1'b0;
25             #200;
26             rst_i=1'b1; 
27             #200;
28             display_on=1; 
29             @(data_rdy_o==1'b1) 
30             data_rgb_i=16'hf800;
31              
32             @(posedge vsync_o ) 
33             #200;
34             @(posedge vsync_o )  
35             #200; 
36             @(posedge vsync_o )  
37             #200;             
38             $stop;      
39             
40     
41         end
42 always #0.5 clk_i<=~clk_i;
43 
44 
45 
46 
47 lcd_dvp_drive
48 #(
49 .VBP(16'd 21   ),//OK
50 .VFP(16'd 18  ),//OK
51 .VSW(16'd 6   ),//OK
52 .VDP(16'd 480 ),//524
53 .HBP(16'd 106   ),//ok
54 .HFP(16'd 16  ),//ok
55 .HSW(16'd 16  ),//ok
56 .HDP(16'd 720  ) //840
57 
58 )
59 u_lcd_dvp_drive
60 (   
61      .clk_i         ( clk_i         )    ,                //时钟输入 840*524*2*60=52.819MHZ//实测53.82MHZ
62      .rst_i         ( rst_i         )    ,             //复位输入
63      .display_on    ( display_on    )    ,             //显示开关输入
64      .data_rgb_i    ( data_rgb_i    )    ,             //16位红色数据输入
65      .data_rdy_o    ( data_rdy_o    )    ,             //数据输入请求信号输出
66      .hsync_o       ( hsync_o       )    ,              //行同步信号输出
67      .vsync_o       ( vsync_o       )    ,              //场同步信号输出
68      .lcd_de        ( lcd_de        )    ,              //LCD输出有效标志
69      .pclk_o        ( pclk_o        )    ,               //数据时钟输出
70      .Serial_data8_o( Serial_data8_o)    ,               //8位数据输出
71      .xpos_o        ( xpos_o        )    ,               //当前行计数输出
72      .ypos_o        ( ypos_o        )    ,               //当前列计数输出
73      .lcd_bl        ( lcd_bl        )    ,               //背光开关控制 1亮背光 0灭背光
74      .out_vsync     ( out_vsync     )                    //帧复位,高有效 
75  );
76 
77 
78 endmodule

 

 

 

posted @ 2023-11-25 10:00  xgj_0817  阅读(36)  评论(0编辑  收藏  举报