16位 565 DVP 接口实现

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