FPGA小白养成记--RGB-LCD彩条显示实验

1.原理

本次实验的目的是在LCD上显示五条不同颜色的彩带,本次我们采用的像素格式是RGB888,一个像素点为24Bit。
接下来是关于LCD如何显示一帧图像呢?我们是采取从左往右,从上往下的方式扫描每个像素点,并表明每个像素点对应的颜色。根据行显示的时序图,我们可以看到,整个构成并不只是由HSPW构成,它还由HBP+HOZVAL+HFP构成;场信号是一样的。
还有很多细节就不赘述了。
那么我们主要要实现一个什么样的东西呢?首先,我们接上LCD屏幕的时候,要能够自动判断出LCD的型号,也就是分辨率,从而可以给出适合的时钟频率(毕竟不同的型号时钟也不同),接下来再驱动LCD显示我们要求的数据。那我们大概可以分为这几个模块进行:(1)ID识别模块,(2)分频模块,(3)驱动模块,(4)显示模块。
接下来我们仔细介绍一下各个模块的思路。

2.设计思路

(1)ID模块
首先来说ID模块,端口方面我们需要的不多,时钟,复位,和lcd_rgb信号,这个信号需要重视一下,它其实是一个inout类型的信号,因为一方面,它要把信号给ID模块,让ID模块来识别,另一方面,它要负责把数据传给LCD以显示颜色,因此在这个模块里,它设为input类型就行了;然后最后,我们要输出一个lcd_id信号,把我们判断出来的ID传送给下一个模块。

代码:

module LCD_ID(
input clk,
input rst_n,
input [23:0] lcd_rgb,
output reg [15:0] lcd_id
    );
reg lcd_flag;


always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
    lcd_flag<=1'b0;
    lcd_id<=16'b0; 
    end

else begin
    if(lcd_flag==1'b0)begin
        lcd_flag<=1'b1;
        case({
   lcd_rgb[7],lcd_rgb[15],lcd_rgb[23]})
            3'b000 : lcd_id <= 16'h4342;
            3'b001 : lcd_id <= 16'h7084;
            3'b010 : lcd_id <= 16'h7016;
            3'b100 : lcd_id <= 16'h4384;
            3'b101 : lcd_id <= 16'h1018;
        default : lcd_id <= 16'd0;
        endcase
     end   
   end
end    
endmodule

那么大家是否会对

if(lcd_flag==1'b0)begin
        lcd_flag<=1'b1;
    这一部分产生疑问呢?
    其实这个设置还是比较巧妙,板子上电时,一般都有个复位操作,这个复位操作将lcd_flag拉到低电平,当低电平时触发条件,接下来将这一信号拉高,并进行接下来的操作;那么为什么我们要拉高呢?因为我们只需要进行一次ID的判断,如果反复进行其实是很浪费资源的一件事,因此我们拉高信号之后,就相当于只执行一次判断ID的操作,后面就不再执行了。
    至于case语句里的条件,即lcd_rgb得位数,那是特定的,不必深究。

(2)分频模块
那么分频怎么做到的呢?我们举个例子,拿二分频为例:

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        clk_25m <= 1'b0;
    else
        clk_25m <= ~clk_25m;
end

在这个always块里,每当clk到来时,触发条件,让clk-25m反转,大家可以自己在图上画一下,就可以很明白的看出来这就是二分频:
分频
四分频也是一样,接下来附上代码:

module LCD_DIV(
input clk,
input rst_n,
input [15:0] lcd_id,
output reg lcd_pclk
    );
reg clk_25m;
reg clk_12_5m;
reg div_cnt;   
    

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        clk_25m <= 1'b0;
    else
        clk_25m <= ~clk_25m;
end

always@(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        clk_12_5m <= 1'b0;
        div_cnt <= 1'b0;
        end
    else begin
        div_cnt <= div_cnt + 1'b1;
            if(div_cnt == 1)
            clk_12_5m <= ~clk_12_5m;
                                  
        end
    end    

always@(*)begin
   if(!rst_n)
       lcd_pclk <= 1'b0;
   else begin 
       case(lcd_id)
       16'h4342 : lcd_pclk = clk_12_5m;
       16'h7084 : lcd_pclk = clk_25m;
       16'h7016 : lcd_pclk = clk;
       16'h4384 : lcd_pclk = clk_25m;
       16'h1018 : lcd_pclk = clk;
       default :  lcd_pclk 
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值