lcd_1602

module lcd_pdf(
        clk,lcd_data,
        lcd_rw,lcd_rs,
        lcd_en,rst_n
);

input                        clk;
input                        rst_n;
output    reg    [7:0]    lcd_data;
output    reg            lcd_rw;  // wirte      L
output    reg            lcd_en; 
output    reg            lcd_rs;

//clock 分频
reg    [24:0]    cnt;
reg                clk_10;
always @(posedge clk or negedge rst_n)
    if(!rst_n)begin
        cnt <= 25'd0;
        clk_10 <= 1'b0;
    end
    else begin
        if(cnt == 5)begin
            clk_10 =~ clk_10;
            cnt <= cnt + 1'b1;
        end
    end
        
//shixu
always @(posedge clk_10 or negedge rst_n)
    if(!rst_n)begin
        lcd_rw <= 1'b0;
        lcd_en <= 1'b0;
    end
    else begin
        case(cnt)
        100000:begin
                lcd_en <= 1'b0;
                lcd_data <= 8'h30;
                lcd_rw <= 1'b0;
                lcd_rs <= 1'b0;
            end
        100001:begin    
                lcd_en <= 1'b1;
            end
        100010:begin
                lcd_en <= 1'b0;
                lcd_data <= 8'h0c;
                lcd_rw <= 1'b0;
                lcd_rs <= 1'b0;
            end
        100011:begin
                lcd_en <= 1'b1;
            end
        100020:begin
                lcd_en <= 1'b0;
                lcd_data <= 8'h01;
                lcd_rw <= 1'b0;
                lcd_rs <= 1'b0;
            end
        100021:begin
                lcd_en <= 1'b1;
            end
        100030:begin                
                lcd_en <= 1'b0;
                lcd_data <= 8'h80;
                lcd_rw <= 1'b0;
                lcd_rs <= 1'b0;
            end
        100031:begin
                lcd_en <= 1'b1;
            end
        100040:begin
                lcd_en <= 1'b0;
                lcd_data <= 8'h30;//字符0
                lcd_rw <= 1'b0;
                lcd_rs <= 1'b1;
            end        
        100041:begin
                lcd_en <= 1'b1;
            end
        default:lcd_en <= 1'b0;
        endcase
    end
endmodule
            
                
                
        
                
        
            

主要还是按照时序图的时间顺序一步步的写,没有上机验证 而且tb在处理很大的数的时候不知道具体咋弄,留下以后解决

//-----------------------------------2-10号修改------------------------------------------//

module fsm_lcd(
        rs,rw,en,data,
        clk,rst_n
);

input        wire        clk;
input        wire        rst_n;
output    reg        rs;    //write_cmd -L  or write_data -H
output    wire        rw;  //write - L
output    reg        en;  //写数据或者写指令 高脉冲
output    reg        [7:0]        data;


//上电20ms稳定电源
parameter    TIME_20MS = 20'd1_0-1;//为了仿真将时间缩短
reg    [19:0]        cnt_init;
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt_init <= 'd0;
    else if(cnt_init == TIME_20MS)
        cnt_init <= TIME_20MS;
    else 
        cnt_init <= cnt_init + 1'b1;

        
        
//分频  1602为慢速器件,要降低clk频率
parameter    DIV_CNT = 20'd5 - 1;//加快仿真速度;
reg    [19:0]        cnt_div;
reg    clk_500hz;
always @(posedge clk or negedge rst_n)
    if(!rst_n)begin
        cnt_div <= 'd0;
        clk_500hz <= 'd0;
    end
    else if(cnt_div == DIV_CNT)begin
        cnt_div <= 'd0;
        clk_500hz =~ clk_500hz;
    end    
    else
        cnt_div <= cnt_div + 1'b1;
        
//fsm
reg        [4:0]        state;
reg        [2:0]        cnt_ms;
always @(posedge clk_500hz or negedge rst_n)
    if(!rst_n)begin    
        data <= 8'd0;
        en <= 1'd0;
        rs <= 1'd0;
        state <= 'd0;
        cnt_ms <= 'd0;
    end
    else if(cnt_init == TIME_20MS)
        case(state)
        5'd0:begin
            data <= 8'd0;
            en <= 1'd0;
            rs <= 1'd0;
            state <= 5'd1;
        end
        5'd1:begin 
            data <= 8'h38;  //显示模式
            en   <= 1'd0;
            rs   <= 1'd0;
            state <= 5'd2;
        end
        5'd2:
            if(cnt_ms == 3'd2)begin
                cnt_ms <= 'd0;
                en <= 1'd1;
                rs <= 1'd0;
                state <= 5'd3;
            end
            else cnt_ms <= cnt_ms + 1'b1;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
        5'd3:begin //0x0c 开显示不显示光标
            data <= 8'h0c;
            en <= 1'd0;
            rs <= 1'd0;
            state <= 5'd4;
            end
        5'd4:begin
            en <= 1'd1;
            state <= 5'd5;
            end
        5'd5:
            if(cnt_ms == 3'd2)begin
                cnt_ms <= 'd0;
                en <= 1'd0;
                state <= 5'd6;
            end
            else cnt_ms <= cnt_ms + 1'b1;
        5'd6:begin //0x80  首地址
            en <= 1'd0;
            data <= 8'h80;
            state <= 5'd7;
            end
        5'd7:begin
            en <= 1'd1;
            state <= 5'd8;
            end
        5'd8:if(cnt_ms == 3'd2)begin //write_data
            cnt_ms <= 'd0;
            en <= 1'd0;
            rs <= 1'd1;
            data <= 8'h1;
            state <= 5'd9;
            end
            else cnt_ms <= cnt_ms + 1'b1;
        5'd9:begin
            en <= 1'd1;
            state <= 5'd10;
            end
        5'd10:
            if(cnt_ms == 3'd2)begin
                cnt_ms <= 'd0;
                en <= 1'd0;
                state <= 5'd0;
                end
            else cnt_ms <= cnt_ms + 1'b1;
        default:state <= 5'd0;
    endcase

                
    

assign     rw    = 1'b0;

endmodule

原文地址:https://www.cnblogs.com/bixiaopengblog/p/6287938.html