FPGA_one 发表于 2017-7-22 10:11:07

LCD1602的时钟显示

//***********************************************************
//**********************小墨笔记*****************************

//简易动态可调电子钟设计
//实现时钟在1602上动态显示且可调

module lcd1602(clk,rst_n,rs,wr,lcden,data,sw1,sw2,sw3,sw4);

input clk ;//输入时钟50Mhz
input rst_n;//复位信号
input sw1,sw2,sw3,sw4; //输入四个独立按键
output rs;    //1602数据命令选择端
output wr;    //读写控制端
output lcden;//使能信号控制端
output data;   //8位数据总线


reg rs,lcden;
reg data;
assign wr = 0;
//---------------------------分频模块---------------------------

reg clkr;
reg cnt;
always @ (posedge clk or negedge rst_n) begin//产生1602时钟
    if(!rst_n)begin
          cnt <= 18'd50000;
               clkr <= 0;
               end
       else if(cnt == 18'd50000) begin
              clkr <= ~clkr;
                        cnt <= 18'd0;
       end
       else cnt<= cnt + 1'b1;

end

//------------------------状态机控制液晶初始化模块--------------------------
parameter
         s0= 5'd0,
                        s1= 5'd1,
                        s2= 5'd2,
                        s3= 5'd3,
                   s4= 5'd4,
                   s5= 5'd5,
                   s6= 5'd6,
                   s7= 5'd7,
                   s8= 5'd8,       
                        s9= 5'd9,
                        s10 = 5'd10,
                        s11 = 5'd11,
                        s12 = 5'd12,
                        s13 = 5'd13,
                        s14 = 5'd14,
                        s15 = 5'd15,
                        s16 = 5'd16,
                        s17 = 5'd17,
                        s18 = 5'd18,       
                        s19 = 5'd19,
                        s20 = 5'd20,
                        s21 = 5'd21,
                        s22 = 5'd22,
                        s23 = 5'd23,
                        s24 = 5'd24,
                        s25 = 5'd25,
                        s26 = 5'd26;
                       
                       
reg state;
reg init_over;   //液晶初始化完成标志位

always @ (posedge clkr or negedge rst_n)begin
   if(!rst_n) begin         //上电复位初始化
           rs <= 1'b1;
                lcden <= 1'b0;
                data <= 8'd0;
                state <=4'd0;
                       
        end
       
        else case (state)
             s0 : begin            
                        rs <= 0;
                                  lcden <= 0;
                                  data <= 8'h38;//送数据,设置16 x 2显示,5 X 7点阵,8位数据接口
                                  state <= s1;
                  end                                    
                  s1:begin         //数据有效
                        lcden <= 1;
                                  state <= s2;
                  end                                    
                  s2 : begin
                     lcden <= 0;
                               data <= 8'h0c;// 开显示,显示光标,光标闪烁
                               state <= s3;
                  end
                  s3 : begin
                     lcden <= 1;
                               state <= s4;
                  end
                  s4 : begin
                         lcden <=0;
                                        data <= 8'h06;// 写一个字符后地址指针加1
                                        state <= s5;
                  end
                  s5 : begin
                         lcden <= 1;
                                        state <= s6;
                  end
                  s6 : begin
                         lcden <= 0;
                                        data <= 8'h01;   // 显示清0,数据指针清0
                                        state <= s7;
                  end
                  s7 : begin
                        lcden <= 1;       
                        state <= s8;       
                             init_over <=1;                //初始化结束标志位          
                  end
//---------------------------------1602初始化结束-----------------------------               
                  s8 : begin
                        lcden <= 0;
                                  data <= 8'h84;   
                                  state <= s9;
                  end
                  s9 : begin
                        lcden <= 1;
            state <= s10;       
                   
                  end
          
                  
                  s10 : begin
                        rs <= 1;          //改为写数据状态
                        lcden <= 0;
                                  data <= shi_s+8'h30;    //写小时的十位
                                  state <= s11;
                  end
                  s11 : begin
                         lcden <= 1;
                                        state <= s12;
                  end
                  s12 : begin                                  
                        lcden <=0;
                                  data <= shi_g+8'h30;    //写小时的个位
                                  state <= s13;
                  end
                  s13 : begin
                        lcden <= 1;
                                  state <= s14;
                  end
                  s14 : begin                         
                        lcden <= 0;
                                  data <= ":";      //写冒号
                                  state <= s15;
                                  
                  end
                  s15 : begin
                        lcden <= 1;
                                  state <= s16;
                  end

                  s16 : begin
                        lcden <= 0;
                                  data <= fen_s+8'h30;//写分钟的十位
                                  state <= s17;
                  end
                  s17 : begin
                        lcden <= 1;
                                  state <= s18;
                  end
                  s18 : begin
                        lcden <= 0;
                                  data <= fen_g+ 8'h30;//写分钟的个位
                                  state <= s19;
                  end
                  s19 : begin
                        lcden <= 1;
                                  state <= s20;
                  end
                  s20 : begin
                        lcden <= 0;
                                  data <= ":";    //写冒号
                                  state <= s21;
                  end
                  s21 : begin
                        lcden <= 1;
                                  state <= s22;
                  end
                  s22 : begin
                        lcden <= 0;
                                  data <= miao_s+ 8'h30;   //写秒钟的十位
                                  state <= s23;
                  end
                  s23 : begin
                        lcden <= 1;
                                  state <= s24;
                  end
                  s24 : begin
                        lcden <= 0;
                                  data<= miao_g + 8'h30;    //写秒钟的个位
                                  state <= s25;
                  end
                  s25 : begin
                        lcden <= 1;
                                  state <= s26;
                                  
                  end
                  s26 : begin
                        lcden <= 0;
                                  state <= s8;          //回到写起始地址的状态,来回刷新
                                  rs <= 0;
                  end
                  default : begin
                            rs <= 1'b1;                                       
                                                lcden <= 1'b0;
                                                data <= 8'd0;
                                                state <= 0;
                  end

        endcase
end

//-------------------------------时分秒产生模块---------------------------------

reg shi;
reg fen;
reg miao;
reg cntr;// 产生1秒钟的时钟,要计数到50_000_000;
always @ (posedge clk or negedge rst_n)begin
    if(!rst_n) begin
            shi <= 6'd18;               //设置初始时间
                                fen<= 6'd22;
                                miao <= 6'd36;
                                cntr <= 26'd0;
       end
       elseif(init_over ==1'b1 && flag ==1'b1)begin
                          if(cntr == 26'd50000000) begin
                                       cntr <= 26'd0;
                                       miao <= miao + 1'b1;
                                               if(miao == 6'd59) begin
                                                          miao <= 6'd0;
                                                          fen <= fen +1'b1;
                                                                  if(fen == 6'd59)begin
                                                                          fen <= 6'd0;
                                                                          shi <= shi +1'b1;
                                                                          if(shi == 6'd23)
                                                                                  shi <= 6'd0;
                                                                  end
                                               end
                               
                       end
                  else cntr <= cntr+1'b1;
       end
       
       else if(key_state == 4'b1000)begin
              miao <= miao + 1'b1;//如果键1按下,那么调整秒针
                        if(miao == 6'd59) miao <= 6'd0;
                        end
       else if(key_state == 4'b0100)begin
             fen <= fen +1'b1;       //如果键2按下,那么调整分针
                       if(fen == 6'd59) fen <= 6'd0;
                       end
       else if(key_state == 4'b0010)   begin
             shi <= shi +1'b1;   //如果键3按下,那么调整时针
                       if(shi == 6'd23) shi <= 6'd0;
                       end


end

//--------------------------------时分秒处理模块----------------------------

wire miao_s;   
wire miao_g;

wire fen_s;
wire fen_g;

wire shi_s;
wire shi_g;

//对时分秒进行求模求余运算
assign miao_s = miao /10;   
assign miao_g = miao %10;
assign fen_s = fen /10;
assign fen_g = fen %10;
assign shi_s = shi /10;
assign shi_g = shi %10;

//-----------------------------按键消抖部分----------------------------------
reg key_rst;

always @ (posedge clk or negedge rst_n)begin
    if(!rst_n) key_rst <= 4'b1111;
       else key_rst <= {sw4,sw3,sw2,sw1};                 //将按键状态送给第一级锁存器锁存               
end

reg key_rst_r;   //定义二级锁存器

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) key_rst_r <= 4'b1111;
       else key_rst_r <= key_rst;    //送第二级锁存器
end

wire key_an;   //抖动标志位
assign key_an = key_rst_r & (~key_rst);//边沿检测算法

reg cnt_k;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) cnt_k <= 18'd0;
        else if(key_an)cnt_k <= 18'd0;    //一旦有抖动,计数器马上清零
        else cnt_k <= cnt_k +1'b1;
end

reg key;
always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) key <= 4'b1111;
        else if(cnt_k == 18'd250000) // 等待5ms,再记录按键状态
          key <= {sw4,sw3,sw2,sw1};
end

reg key_r;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) key_r <= 4'b1111;
        else key_r <= key;   //送到二级锁存器
end

wire key_state = key_r& (~key); //边沿检测算法

//--------------------------时钟暂停----------------------------
regflag;

always @ (posedge clk or negedge rst_n) begin
   if(!rst_n) flag <= 1'b1;
        else if(key_state == 3'b0001)   //如果键4按下,那么时钟暂停
           flag <= ~flag;
       
end

endmodule

fpga_wuhan 发表于 2017-7-22 11:53:43

LCD1602的时钟显示

小舍YZ 发表于 2017-7-22 16:37:55

赞,,,,,,,,,,,,,,,,,,谢谢分享。。。。。。。。。。。。。。。。。。。。:lol

奋斗的小孩 发表于 2017-7-23 10:05:44

挺不错的呀

fpga_feixiang 发表于 7 天前

6                           
页: [1]
查看完整版本: LCD1602的时钟显示