查看: 1239|回复: 0
打印 上一主题 下一主题

1602液晶的驱动(verilog)

[复制链接]
跳转到指定楼层
沙发
发表于 2016-6-4 01:35:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

(原文件名:elsonx.jpg)

module LCD1602 (clk_500Hz, rst_n, update, addr, data, lcd_rw, lcd_rs, lcd_en, lcd_data);

input clk_500Hz, rst_n, update;
input[4:0] addr;
input[7:0] data;

output lcd_rw, lcd_rs, lcd_en;
output[7:0] lcd_data;

reg lcd_rs;
wire lcd_en;
reg[7:0] lcd_data;

reg[9:0] current_state, next_state;
reg[4:0] addr_cnt;
reg[7:0] disp_buf1[15:0];
reg[7:0] disp_buf2[15:0];

parameter         IDLE        = 10'b00_0000_0000,
        CLEAR          = 10'b00_0000_0010,
        DISPOFF         = 10'b00_0000_0100,
        SETLCDMODE  = 10'b00_0000_1000,
        SETCURSOR   = 10'b00_0001_0000,
        CURSORMODE         = 10'b00_0010_0000,
        WRITEADDR1  = 10'b00_0100_0000,
        WRITEADDR2          = 10'b00_1000_0000,
        WRITEDATA1   = 10'b01_0000_0000,
        WRITEDATA2          = 10'b10_0000_0000;

assign lcd_rw = 1'b0;
assign lcd_en = clk_500Hz;

task init_buf;
        disp_buf1[0] <= "T";
        disp_buf1[1] <= "o";
        disp_buf1[2] <= ":";
        disp_buf1[3] <= "w";
        disp_buf1[4] <= "w";
        disp_buf1[5] <= "w";
        disp_buf1[6] <= ".";
        disp_buf1[7] <= "o";
        disp_buf1[8] <= "u";
        disp_buf1[9] <= "r";
        disp_buf1[10] <= "d";
        disp_buf1[11] <= "e";
        disp_buf1[12] <= "v";
        disp_buf1[13] <= ".";
        disp_buf1[14] <= "c";
        disp_buf1[15] <= "n";
        
        disp_buf2[0] <= " ";
        disp_buf2[1] <= " ";
        disp_buf2[2] <= " ";
        disp_buf2[3] <= " ";
        disp_buf2[4] <= " ";
        disp_buf2[5] <= " ";
        disp_buf2[6] <= " ";
        disp_buf2[7] <= "b";
        disp_buf2[8] <= "y";
        disp_buf2[9] <= " ";
        disp_buf2[10] <= "E";
        disp_buf2[11] <= "l";
        disp_buf2[12] <= "s";
        disp_buf2[13] <= "o";
        disp_buf2[14] <= "n";
        disp_buf2[15] <= "x";
endtask

always @ (posedge clk_500Hz or negedge rst_n)
  begin
        if (!rst_n)
                current_state <= IDLE;
        else
                current_state <= next_state;
  end
  
always @ (current_state or addr_cnt)
  begin
        next_state = 4'hx;
        case (current_state)
                IDLE:                next_state = SETLCDMODE;
               
                SETLCDMODE:        next_state = DISPOFF;

                DISPOFF:                   next_state = CLEAR;
               
                CLEAR:                next_state = SETCURSOR;
               
                SETCURSOR:          next_state = CURSORMODE;
               
                CURSORMODE:        next_state = WRITEADDR1;
        
                WRITEADDR1:        next_state = WRITEDATA1;
        
                WRITEADDR2:        next_state = WRITEDATA2;
        
                WRITEDATA1:
                  begin
                        if(addr_cnt == 16)
                                next_state = WRITEADDR2;
                        else
                                next_state = WRITEDATA1;
                  end
                WRITEDATA2:
                  begin
                        if(addr_cnt == 16)
                                next_state = WRITEADDR1;
                        else
                                next_state = WRITEDATA2;
                  end
                default: next_state = IDLE;
        
        endcase
  end
  
always @ (posedge clk_500Hz or negedge rst_n)
  begin
        if (!rst_n)
                addr_cnt <= 0;
        else
        case (next_state)
                IDLE:
                  begin
                    lcd_rs = 0;
                        lcd_data = 8'hxx;
                  end
                SETLCDMODE:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h38;
                  end
                DISPOFF:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h08;
                  end
                CLEAR:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h1;
                  end
                SETCURSOR:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h06;
                  end
                CURSORMODE:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h0C;
                  end
                WRITEADDR1:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'h80;
                  end
                WRITEADDR2:
                  begin
                        lcd_rs = 0;
                        lcd_data = 8'hc0;
                  end
                WRITEDATA1:
                  begin
                        lcd_rs = 1;
                        lcd_data = disp_buf1[addr_cnt];
                        addr_cnt <= addr_cnt + 1;
                  end
                WRITEDATA2:
                  begin
                        lcd_rs = 1;
                        lcd_data = disp_buf2[addr_cnt];
                        addr_cnt <= addr_cnt + 1;
                  end
        endcase
  end

always @ (posedge update or negedge rst_n)
  begin
        if (!rst_n)
                init_buf;
        else if (!addr[4])
                disp_buf1[addr[3:0]] <= data;
        else
                disp_buf2[addr[3:0]] <= data;
  end
  
endmodule

代码贴上来好像缩进有点乱了~~~

点击此处下载 LCD1602.rar(文件大小:960字节) (原文件名CD1602.rar)







回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

快速回复 返回顶部 返回列表