下面为基于小脚丫FPGA开发板和Nokia5110液晶显示屏的数字时钟设计 框架如下:
数字时钟功能介绍: 按键K1,模式调节,设计共分4中模式(运行模式、时针调节、分针调节、秒针调节),按动K1依次切换模式 按键K2,时间调节,当数字时钟在时针调节、分针调节或秒针调节模式时,按动K2调节对应时间位 硬件连接图中,程序复位控制线控制程序复位,断开重连设计复位 程序源码如下: Digital_clock.v 顶层文件 - /**************************************************
- module: Digital_clock
- author: wanganran
- description: clock divide, generate pulse and 50 percent clock_div
- input: clk_in,rst_n_in
- output: clk_div_50per_out,clk_div_pulse_out,clk_div_pulse_out1
- date: 2015.10.23
- **************************************************/
- module Digital_clock
- (
- input clk_in, //clk_in = 25mhz
- input rst_n_in, //rst_n_in, active low
- input key1_set, //clock mode select key
- input key2_up, //clock time adapt key
- output led1_set,
- output led2_up,
- output lcd_rst_n_out, //nokia5110 reset, active low
- output lcd_ce_n_out, //nokia5110 chip select, active low
- output lcd_dc_out, //nokia5110 data or command control
- output lcd_bl_out, //nokia5110 backlight
- output lcd_clk_out, //nokia5110 clock
- output lcd_data_out //nokia5110 data
- );
- //reg rst_n_in = 1;
- wire scan_clk;
- wire key_clk;
- wire sec_clk;
- Clock_div Clock_div_uut
- (
- .clk_in(clk_in), //clk_in = 25mhz
- .rst_n_in(rst_n_in), //rst_n_in, active low
- .clk_div_50per_out(scan_clk), //clock divide output, duty cycle is 50 percent
- .clk_div_pulse_out(key_clk), //clock divide output, duty cycle = 1/CLK_DIV_PULSE_PERIOD(one clk_in period)
- .clk_div_pulse_out1(sec_clk) //clock divide output, duty cycle = 1/CLK_DIV_PULSE_PERIOD1(one clk_in period)
- );
- wire set_en;
- wire up_en;
- wire led1_set;
- wire led2_up=s_data[0];
- key_board key_board_uut
- (
- .clk_in(clk_in), //25mhz
- .key_clk_in(key_clk), //replace key_clk
- .rst_n_in(rst_n_in), //active with low
- .key_in(key1_set), //keyboard in, high for normal, low for press
- .key_out(set_en), //key_out will have a pulse when key_in be pressed
- .key_flag_out(led1_set), //flag for key_out's change, floating if not use
- .key1_in(key2_up), //keyboard in, high for normal, low for press
- .key1_out(up_en), //key_out will have a pulse when key_in be pressed
- .key1_flag_out() //flag for key_out's change, floating if not use
- );
- wire [7:0] h_set;
- wire [7:0] m_set;
- wire [7:0] s_set;
- clock_ctl clock_ctl_uut
- (
- .clk_in(clk_in),
- .rst_n_in(rst_n_in),
- .set_en(set_en),
- .h_set(h_set),
- .m_set(m_set),
- .s_set(s_set)
- );
- wire [7:0] h_data;
- wire [7:0] m_data;
- wire [7:0] s_data;
- Clock_cnt Clock_cnt_uut
- (
- .clk_in(clk_in),
- .rst_n_in(rst_n_in),
- .sec_clk(sec_clk),
- .up_en(up_en),
- .h_set(h_set),
- .m_set(m_set),
- .s_set(s_set),
- .h_data(h_data),
- .m_data(m_data),
- .s_data(s_data)
- );
- wire lcd_rst_n_out;
- wire lcd_ce_n_out;
- wire lcd_dc_out;
- wire lcd_bl_out;
- wire lcd_clk_out;
- wire lcd_data_out;
- LCD_nokia5110 LCD_nokia5110_uut
- (
- .clk_in(clk_in), //clk_in = 25mhz
- .scan_clk_in(scan_clk), //replace clk_div
- .rst_n_in(rst_n_in), //rst_n_in, active low
- .data_in({h_data,m_data,s_data}), //need to display
- .lcd_rst_n_out(lcd_rst_n_out), //nokia5110 reset, active low
- .lcd_ce_n_out(lcd_ce_n_out), //nokia5110 chip select, active low
- .lcd_dc_out(lcd_dc_out), //nokia5110 data or command control
- .lcd_bl_out(lcd_bl_out), //nokia5110 backlight
- .lcd_clk_out(lcd_clk_out), //nokia5110 clock
- .lcd_data_out(lcd_data_out) //nokia5110 data
- );
- endmodule
复制代码Clock_div.v 时钟分频管理模块 - /**************************************************
- module: Clock_div
- author: wanganran
- description: clock divide, generate pulse and 50 percent clock_div
- input: clk_in,rst_n_in
- output: clk_div_50per_out,clk_div_pulse_out,clk_div_pulse_out1
- date: 2015.10.23
- **************************************************/
- module Clock_div
- (
- input clk_in, //clk_in = 25mhz
- input rst_n_in, //rst_n_in, active low
- output reg clk_div_50per_out, //clock divide output, duty cycle is 50 percent
- output reg clk_div_pulse_out, //clock divide output, duty cycle = 1/CLK_DIV_PULSE_PERIOD(one clk_in period)
- output reg clk_div_pulse_out1 //clock divide output, duty cycle = 1/CLK_DIV_PULSE_PERIOD1(one clk_in period)
- );
- parameter CLK_DIV_50PER_PERIOD=25000; //related with clk_div_50per_out's frequency
- parameter CLK_DIV_PULSE_PERIOD=250000; //related with clk_div_pulse_out's frequency
- parameter CLK_DIV_PULSE_PERIOD1=25000000; //related with clk_div_pulse_out1's frequency
- //clk_div_50per_out = clk_in/CLK_DIV_50PER_PERIOD, duty cycle is 50 percent
- //1000hz
- reg[24:0] cnt2=0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- cnt2<=0;
- clk_div_50per_out<=0;
- end
- else begin
- cnt2<=cnt2+1;
- if(cnt2==(CLK_DIV_50PER_PERIOD-1)) cnt2<=0;
- if(cnt2<(CLK_DIV_50PER_PERIOD/2)) clk_div_50per_out<=0;
- else clk_div_50per_out<=1;
- end
- end
- //clk_div_pulse_out = clk_in/CLK_DIV_PULSE_PERIOD, duty cycle is 1/CLK_DIV_PULSE_PERIOD(one clk_in period)
- //100hz
- reg[24:0] cnt1=0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- cnt1<=0;
- clk_div_pulse_out<=0;
- end
- else if(cnt1==(CLK_DIV_PULSE_PERIOD-1))
- begin
- cnt1<=0;
- clk_div_pulse_out<=1;
- end
- else begin
- cnt1<=cnt1+1;
- clk_div_pulse_out<=0;
- end
- end
- //clk_div_pulse_out1 = clk_in/CLK_DIV_PULSE_PERIOD1, duty cycle is 1/CLK_DIV_PULSE_PERIOD1(one clk_in period)
- //1hz
- reg[24:0] cnt3=0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- cnt3<=0;
- clk_div_pulse_out1<=0;
- end
- else if(cnt3==(CLK_DIV_PULSE_PERIOD1-1))
- begin
- cnt3<=0;
- clk_div_pulse_out1<=1;
- end
- else begin
- cnt3<=cnt3+1;
- clk_div_pulse_out1<=0;
- end
- end
- endmodule
复制代码key_board.v 按键消抖控制模块 - /**************************************************
- module: key_board
- author: wanganran
- description: elimination buffeting of keystroke, key_out go low-high-low when key_in go high-low-high
- input: clk_in,rst_n_in,key_in
- output: key_out,key_flag_out
- date: 2015.10.23
- **************************************************/
- module key_board
- (
- input clk_in, //25mhz
- input key_clk_in, //replace key_clk
- input rst_n_in, //active with low
- input key_in, //keyboard in, high for normal, low for press
- output key_out, //key_out will have a pulse when key_in be pressed
- output reg key_flag_out, //flag for key_out's change, floating if not use
- input key1_in, //keyboard in, high for normal, low for press
- output key1_out, //key_out will have a pulse when key_in be pressed
- output reg key1_flag_out //flag for key_out's change, floating if not use
- );
- parameter KEY_CLK_PERIOD=250000; //related with key_clk's frequency
- //key_clk = 100hz, duty cycle is 1/250000(one clk_in period)
- reg key_clk;
- reg[17:0] clk_cnt=0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- clk_cnt<=0;
- key_clk<=0;
- end
- else if(clk_cnt==(KEY_CLK_PERIOD-1))
- begin
- clk_cnt<=0;
- key_clk<=1;
- end
- else begin
- clk_cnt<=clk_cnt+1;
- key_clk<=0;
- end
- end
- //delay to elimination buffeting of keystroke
- //every time the key was pressed,the key_out will have a pulse(one clk_in period)
- reg key_n_r1 = 0;
- reg key_n_r2 = 0;
- reg key_n_r3 = 0;
- reg key_n_r5 = 0;
- assign key_n = ~key_in;
- assign key_n_r4 = key_n_r2&key_n_r3;
- assign key_out = key_n_r4&(~key_n_r5);
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- key_n_r1<=0;
- key_n_r2<=0;
- key_n_r3<=0;
- end
- else begin
- key_n_r1<=key_n;
- key_n_r5<=key_n_r4;
- if(key_clk_in)
- begin
- key_n_r2<=key_n_r1;
- key_n_r3<=key_n_r2;
- end
- end
- end
- //key_flag_out turn over every time when key_out active
- //we can judge the key was pressed or not by check the key_flag_out
- reg key_flag_out = 0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in) key_flag_out <= 0;
- else if(key_out) key_flag_out <= ~key_flag_out;
- end
-
- //delay to elimination buffeting of keystroke
- //every time the key was pressed,the key_out will have a pulse(one clk_in period)
- reg key1_n_r1 = 0;
- reg key1_n_r2 = 0;
- reg key1_n_r3 = 0;
- reg key1_n_r5 = 0;
- assign key1_n = ~key1_in;
- assign key1_n_r4 = key1_n_r2&key1_n_r3;
- assign key1_out = key1_n_r4&(~key1_n_r5);
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- key1_n_r1<=0;
- key1_n_r2<=0;
- key1_n_r3<=0;
- end
- else begin
- key1_n_r1<=key1_n;
- key1_n_r5<=key1_n_r4;
- if(key_clk_in)
- begin
- key1_n_r2<=key1_n_r1;
- key1_n_r3<=key1_n_r2;
- end
- end
- end
- //key_flag_out turn over every time when key_out active
- //we can judge the key was pressed or not by check the key_flag_out
- reg key1_flag_out = 0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in) key1_flag_out <= 0;
- else if(key1_out) key1_flag_out <= ~key1_flag_out;
- end
-
- endmodule
复制代码clock_ctl.v 模式控制模块 - /**************************************************
- module: clock_ctl
- author: wanganran
- description: digital clock mode controller
- input: clk_in,rst_n_in,set_en
- output: h_set,m_set,s_set
- date: 2015.10.23
- **************************************************/
- module clock_ctl
- (
- input clk_in,
- input rst_n_in,
- input set_en,
- output h_set,
- output m_set,
- output s_set
- );
- parameter[1:0] normal=2'b00,hour_set=2'b01,minute_set=2'b10,second_set=2'b11;
- reg h_set;
- reg m_set;
- reg s_set;
- reg[1:0] current_state,next_state;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in) begin
- current_state<=normal;
- end
- else current_state<=next_state;
- end
- always@(current_state or set_en)
- begin
- case(current_state)
- normal: if(set_en) next_state<=hour_set;
- else next_state<=normal;
- hour_set: if(set_en) next_state<=minute_set;
- else next_state<=hour_set;
- minute_set:if(set_en) next_state<=second_set;
- else next_state<=minute_set;
- second_set:if(set_en) next_state<=normal;
- else next_state<=second_set;
- endcase
- end
- always@(current_state)
- begin
- case(current_state)
- normal: begin h_set<=0;m_set<=0;s_set<=0;end
- hour_set: begin h_set<=1;m_set<=0;s_set<=0;end
- minute_set: begin h_set<=0;m_set<=1;s_set<=0;end
- second_set: begin h_set<=0;m_set<=0;s_set<=1;end
- endcase
- end
- endmodule
复制代码Clock_cnt.v 时间调节模块 - /**************************************************
- module: Clock_cnt
- author: wanganran
- description: cpu of design,
- input: clk_in,rst_n_in,sec_clk,up_en,h_set,m_set,s_set,
- output: h_data,m_data,s_data
- date: 2015.10.23
- **************************************************/
- module Clock_cnt
- (
- input clk_in,
- input rst_n_in,
- input sec_clk,
- input up_en,
- input h_set,
- input m_set,
- input s_set,
- output [7:0] h_data,
- output [7:0] m_data,
- output [7:0] s_data
- );
- reg [7:0] hour=8'h08; //reset display time
- reg [7:0] min=8'h30; //reset display time
- reg [7:0] sec=8'h00; //reset display time
- reg [2:0] ctl;
- assign h_data=ctl[2]?8'hbb:hour;
- assign m_data=ctl[1]?8'hbb:min;
- assign s_data=ctl[0]?8'hbb:sec;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- ctl<=3'd0;
- hour<=8'h08;
- min<=8'h30;
- sec<=8'h00;
- end
- else
- begin
- if(h_set==0&&m_set==0&&s_set==0)//normal
- begin
- ctl<=3'd0;
- if(sec_clk)
- begin
- if(sec==8'h59)//seconds counter
- begin
- sec<=8'h0;
- if(min==8'h59)//minute counter
- begin
- min<=8'h0;
- if(hour==8'h23)//hour counter
- hour<=8'h0;
- else //hour counter
- begin
- if(hour[3:0]==4'd9)
- begin
- hour[3:0]<=4'd0;
- hour[7:4]<=hour[7:4]+4'd1;
- end
- else hour[3:0]<=hour[3:0]+4'd1;
- end
- end
- else begin//minute counter
- if(min[3:0]==4'd9)
- begin
- min[3:0]<=4'd0;
- min[7:4]<=min[7:4]+4'd1;
- end
- else min[3:0]<=min[3:0]+4'd1;
- end
- end
- else
- begin //seconds counter
- if(sec[3:0]==4'd9)
- begin
- sec[3:0]<=4'd0;
- sec[7:4]<=sec[7:4]+4'd1;
- end
- else sec[3:0]<=sec[3:0]+4'd1;
- end
- end
- end
- else if(h_set==1&&m_set==0&&s_set==0) //hour set
- begin
- if(up_en) //up_en down
- begin
- ctl<=3'd0;
- if(hour==8'h23) hour<=8'h0;
- else begin
- if(hour[3:0]==4'd9)
- begin
- hour[3:0]<=4'd0;
- hour[7:4]<=hour[7:4]+4'd1;
- end
- else hour[3:0]<=hour[3:0]+4'd1;
- end
- end
- else if(sec_clk)
- begin
- ctl[2]<=~ctl[2];
- ctl[1:0]<=2'b00;
- end
- end
- else if(h_set==0&&m_set==1&&s_set==0)
- begin
- if(up_en)
- begin
- ctl<=3'd0;
- if(min==8'h59) min<=8'h0;//minute set
- else begin //minute set
- if(min[3:0]==4'd9)
- begin
- min[3:0]<=4'd0;
- min[7:4]<=min[7:4]+4'd1;
- end
- else min[3:0]<=min[3:0]+4'd1;
- end
- end
- else if(sec_clk)
- begin
- ctl[2]<=0;
- ctl[1]<=~ctl[1];
- ctl[0]<=0;
- end
- end
- else if(h_set==0&&m_set==0&&s_set==1)
- begin
- if(up_en)
- begin
- ctl<=3'd0;
- if(sec==8'h59) sec<=8'h0;//second set
- else begin //second set
- if(sec[3:0]==4'd9)
- begin
- sec[3:0]<=4'd0;
- sec[7:4]<=sec[7:4]+4'd1;
- end
- else sec[3:0]<=sec[3:0]+4'd1;
- end
- end
- else if(sec_clk)
- begin
- ctl[2]<=0;
- ctl[1]<=0;
- ctl[0]<=~ctl[0];
- end
- end
- end
- end
- endmodule
复制代码LCD_nokia5110.v Nokia5110液晶显示模块 - /**************************************************
- module: LCD_nokia5110
- author: wanganran
- description: drive Nokia5110 lcd display with fpga/cpld
- -ECBC 2015
- -10/23 23:30
- input: clk_in,rst_n_in,data_in
- output: rclk_out,sclk_out,sdio_out
- date: 2015.10.23
- **************************************************/
- module LCD_nokia5110
- (
- input clk_in, //clk_in = 25mhz
- input scan_clk_in, //replace clk_div
- input rst_n_in, //rst_n_in, active low
- input [23:0] data_in, //need to display
- output lcd_rst_n_out, //nokia5110 reset, active low
- output reg lcd_ce_n_out, //nokia5110 chip select, active low
- output reg lcd_dc_out, //nokia5110 data or command control
- output lcd_bl_out, //nokia5110 backlight
- output lcd_clk_out, //nokia5110 clock
- output reg lcd_data_out //nokia5110 data
- );
- parameter CLK_DIV_PERIOD=20; //related with clk_div's frequency
- parameter DELAY_PERIOD=10000; //related with delay time and refresh frequency
- parameter CLK_L=2'd0;
- parameter CLK_H=2'd1;
- parameter CLK_RISING_DEGE=2'd2;
- parameter CLK_FALLING_DEGE=2'd3;
- parameter IDLE=3'd0;
- parameter SHIFT=3'd1;
- parameter CLEAR=3'd2;
- parameter SETXY=3'd3;
- parameter DISPLAY=3'd4;
- parameter DELAY=3'd5;
- parameter LOW =1'b0;
- parameter HIGH =1'b1;
- parameter CMD =1'b0;
- parameter DATA =1'b1;
- assign lcd_rst_n_out = 1; //active low level, set 1 for normal
- assign lcd_bl_out = 1; //backlight active high level
- assign lcd_clk_out = clk_div; //////////////////////////////////////scan_clk_in;
- //initial for memory register
- reg [47:0] mem [91:0];
- reg [47:0] temp;
- initial
- begin
- mem[0]= {8'h00, 8'h00, 8'h56, 8'h36, 8'h00, 8'h00}; // 0 ;
- mem[1]= {8'h00, 8'h00, 8'h00, 8'h2f, 8'h00, 8'h00}; // 1 !
- mem[2]= {8'h00, 8'h00, 8'h07, 8'h00, 8'h07, 8'h00}; // 2
- mem[3]= {8'h00, 8'h14, 8'h7f, 8'h14, 8'h7f, 8'h14}; // 3 #
- mem[4]= {8'h00, 8'h24, 8'h2a, 8'h7f, 8'h2a, 8'h12}; // 4 $
- mem[5]= {8'h00, 8'h62, 8'h64, 8'h08, 8'h13, 8'h23}; // 5 %
- mem[6]= {8'h00, 8'h36, 8'h49, 8'h55, 8'h22, 8'h50}; // 6 &
- mem[7]= {8'h00, 8'h00, 8'h05, 8'h03, 8'h00, 8'h00}; // 7 '
- mem[8]= {8'h00, 8'h00, 8'h1c, 8'h22, 8'h41, 8'h00}; // 8 {
- mem[9]= {8'h00, 8'h00, 8'h41, 8'h22, 8'h1c, 8'h00}; // 9 )
- mem[10]= {8'h00, 8'h14, 8'h08, 8'h3E, 8'h08, 8'h14}; // 10 *
- mem[11]= {8'h00, 8'h08, 8'h08, 8'h3E, 8'h08, 8'h08}; // 11 +
- mem[12]= {8'h00, 8'h00, 8'h00, 8'hA0, 8'h60, 8'h00}; // 12 ,
- mem[13]= {8'h00, 8'h08, 8'h08, 8'h08, 8'h08, 8'h08}; // 13 -
- mem[14]= {8'h00, 8'h00, 8'h60, 8'h60, 8'h00, 8'h00}; // 14 .
- mem[15]= {8'h00, 8'h20, 8'h10, 8'h08, 8'h04, 8'h02}; // 15 /
- mem[16]= {8'h00, 8'h3E, 8'h51, 8'h49, 8'h45, 8'h3E}; // 16 0
- mem[17]= {8'h00, 8'h00, 8'h42, 8'h7F, 8'h40, 8'h00}; // 17 1
- mem[18]= {8'h00, 8'h42, 8'h61, 8'h51, 8'h49, 8'h46}; // 18 2
- mem[19]= {8'h00, 8'h21, 8'h41, 8'h45, 8'h4B, 8'h31}; // 19 3
- mem[20]= {8'h00, 8'h18, 8'h14, 8'h12, 8'h7F, 8'h10}; // 20 4
- mem[21]= {8'h00, 8'h27, 8'h45, 8'h45, 8'h45, 8'h39}; // 21 5
- mem[22]= {8'h00, 8'h3C, 8'h4A, 8'h49, 8'h49, 8'h30}; // 22 6
- mem[23]= {8'h00, 8'h01, 8'h71, 8'h09, 8'h05, 8'h03}; // 23 7
- mem[24]= {8'h00, 8'h36, 8'h49, 8'h49, 8'h49, 8'h36}; // 24 8
- mem[25]= {8'h00, 8'h06, 8'h49, 8'h49, 8'h29, 8'h1E}; // 25 9
- mem[26]= {8'h00, 8'h00, 8'h36, 8'h36, 8'h00, 8'h00}; // 26 :
- mem[27]= {8'h00, 8'h00, 8'h00, 8'h00, 8'h00, 8'h00}; // 27 sp
- mem[28]= {8'h00, 8'h08, 8'h14, 8'h22, 8'h41, 8'h00}; // 28 <
- mem[29]= {8'h00, 8'h14, 8'h14, 8'h14, 8'h14, 8'h14}; // 29 =
- mem[30]= {8'h00, 8'h00, 8'h41, 8'h22, 8'h14, 8'h08}; // 30 >
- mem[31]= {8'h00, 8'h02, 8'h01, 8'h51, 8'h09, 8'h06}; // 31 ?
- mem[32]= {8'h00, 8'h32, 8'h49, 8'h59, 8'h51, 8'h3E}; // 32 @
- mem[33]= {8'h00, 8'h7C, 8'h12, 8'h11, 8'h12, 8'h7C}; // 33 A
- mem[34]= {8'h00, 8'h7F, 8'h49, 8'h49, 8'h49, 8'h36}; // 34 B
- mem[35]= {8'h00, 8'h3E, 8'h41, 8'h41, 8'h41, 8'h22}; // 35 C
- mem[36]= {8'h00, 8'h7F, 8'h41, 8'h41, 8'h22, 8'h1C}; // 36 D
- mem[37]= {8'h00, 8'h7F, 8'h49, 8'h49, 8'h49, 8'h41}; // 37 E
- mem[38]= {8'h00, 8'h7F, 8'h09, 8'h09, 8'h09, 8'h01}; // 38 F
- mem[39]= {8'h00, 8'h3E, 8'h41, 8'h49, 8'h49, 8'h7A}; // 39 G
- mem[40]= {8'h00, 8'h7F, 8'h08, 8'h08, 8'h08, 8'h7F}; // 40 H
- mem[41]= {8'h00, 8'h00, 8'h41, 8'h7F, 8'h41, 8'h00}; // 41 I
- mem[42]= {8'h00, 8'h20, 8'h40, 8'h41, 8'h3F, 8'h01}; // 42 J
- mem[43]= {8'h00, 8'h7F, 8'h08, 8'h14, 8'h22, 8'h41}; // 43 K
- mem[44]= {8'h00, 8'h7F, 8'h40, 8'h40, 8'h40, 8'h40}; // 44 L
- mem[45]= {8'h00, 8'h7F, 8'h02, 8'h0C, 8'h02, 8'h7F}; // 45 M
- mem[46]= {8'h00, 8'h7F, 8'h04, 8'h08, 8'h10, 8'h7F}; // 46 N
- mem[47]= {8'h00, 8'h3E, 8'h41, 8'h41, 8'h41, 8'h3E}; // 47 O
- mem[48]= {8'h00, 8'h7F, 8'h09, 8'h09, 8'h09, 8'h06}; // 48 P
- mem[49]= {8'h00, 8'h3E, 8'h41, 8'h51, 8'h21, 8'h5E}; // 49 Q
- mem[50]= {8'h00, 8'h7F, 8'h09, 8'h19, 8'h29, 8'h46}; // 50 R
- mem[51]= {8'h00, 8'h46, 8'h49, 8'h49, 8'h49, 8'h31}; // 51 S
- mem[52]= {8'h00, 8'h01, 8'h01, 8'h7F, 8'h01, 8'h01}; // 52 T
- mem[53]= {8'h00, 8'h3F, 8'h40, 8'h40, 8'h40, 8'h3F}; // 53 U
- mem[54]= {8'h00, 8'h1F, 8'h20, 8'h40, 8'h20, 8'h1F}; // 54 V
- mem[55]= {8'h00, 8'h3F, 8'h40, 8'h38, 8'h40, 8'h3F}; // 55 W
- mem[56]= {8'h00, 8'h63, 8'h14, 8'h08, 8'h14, 8'h63}; // 56 X
- mem[57]= {8'h00, 8'h07, 8'h08, 8'h70, 8'h08, 8'h07}; // 57 Y
- mem[58]= {8'h00, 8'h61, 8'h51, 8'h49, 8'h45, 8'h43}; // 58 Z
- mem[59]= {8'h00, 8'h00, 8'h7F, 8'h41, 8'h41, 8'h00}; // 59 [
- mem[60]= {8'h00, 8'h55, 8'h2A, 8'h55, 8'h2A, 8'h55}; // 60 .
- mem[61]= {8'h00, 8'h00, 8'h41, 8'h41, 8'h7F, 8'h00}; // 61 ]
- mem[62]= {8'h00, 8'h04, 8'h02, 8'h01, 8'h02, 8'h04}; // 62 ^
- mem[63]= {8'h00, 8'h40, 8'h40, 8'h40, 8'h40, 8'h40}; // 63 _
- mem[64]= {8'h00, 8'h00, 8'h01, 8'h02, 8'h04, 8'h00}; // 64 '
- mem[65]= {8'h00, 8'h20, 8'h54, 8'h54, 8'h54, 8'h78}; // 65 a
- mem[66]= {8'h00, 8'h7F, 8'h48, 8'h44, 8'h44, 8'h38}; // 66 b
- mem[67]= {8'h00, 8'h38, 8'h44, 8'h44, 8'h44, 8'h20}; // 67 c
- mem[68]= {8'h00, 8'h38, 8'h44, 8'h44, 8'h48, 8'h7F}; // 68 d
- mem[69]= {8'h00, 8'h38, 8'h54, 8'h54, 8'h54, 8'h18}; // 69 e
- mem[70]= {8'h00, 8'h08, 8'h7E, 8'h09, 8'h01, 8'h02}; // 70 f
- mem[71]= {8'h00, 8'h18, 8'hA4, 8'hA4, 8'hA4, 8'h7C}; // 71 g
- mem[72]= {8'h00, 8'h7F, 8'h08, 8'h04, 8'h04, 8'h78}; // 72 h
- mem[73]= {8'h00, 8'h00, 8'h44, 8'h7D, 8'h40, 8'h00}; // 73 i
- mem[74]= {8'h00, 8'h40, 8'h80, 8'h84, 8'h7D, 8'h00}; // 74 j
- mem[75]= {8'h00, 8'h7F, 8'h10, 8'h28, 8'h44, 8'h00}; // 75 k
- mem[76]= {8'h00, 8'h00, 8'h41, 8'h7F, 8'h40, 8'h00}; // 76 l
- mem[77]= {8'h00, 8'h7C, 8'h04, 8'h18, 8'h04, 8'h78}; // 77 m
- mem[78]= {8'h00, 8'h7C, 8'h08, 8'h04, 8'h04, 8'h78}; // 78 n
- mem[79]= {8'h00, 8'h38, 8'h44, 8'h44, 8'h44, 8'h38}; // 79 o
- mem[80]= {8'h00, 8'hFC, 8'h24, 8'h24, 8'h24, 8'h18}; // 80 p
- mem[81]= {8'h00, 8'h18, 8'h24, 8'h24, 8'h18, 8'hFC}; // 81 q
- mem[82]= {8'h00, 8'h7C, 8'h08, 8'h04, 8'h04, 8'h08}; // 82 r
- mem[83]= {8'h00, 8'h48, 8'h54, 8'h54, 8'h54, 8'h20}; // 83 s
- mem[84]= {8'h00, 8'h04, 8'h3F, 8'h44, 8'h40, 8'h20}; // 84 t
- mem[85]= {8'h00, 8'h3C, 8'h40, 8'h40, 8'h20, 8'h7C}; // 85 u
- mem[86]= {8'h00, 8'h1C, 8'h20, 8'h40, 8'h20, 8'h1C}; // 86 v
- mem[87]= {8'h00, 8'h3C, 8'h40, 8'h30, 8'h40, 8'h3C}; // 87 w
- mem[88]= {8'h00, 8'h44, 8'h28, 8'h10, 8'h28, 8'h44}; // 88 x
- mem[89]= {8'h00, 8'h1C, 8'hA0, 8'hA0, 8'hA0, 8'h7C}; // 89 y
- mem[90]= {8'h00, 8'h44, 8'h64, 8'h54, 8'h4C, 8'h44}; // 90 z
- mem[91]= {8'h14, 8'h14, 8'h14, 8'h14, 8'h14, 8'h14}; // 91 horiz lines
- end
- //clk_div = clk_in/CLK_DIV_PERIOD = 500khz, 50% is high voltage
- reg clk_div;
- reg[15:0] clk_cnt=0;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in) clk_cnt<=0;
- else begin
- clk_cnt<=clk_cnt+1;
- if(clk_cnt==(CLK_DIV_PERIOD-1)) clk_cnt<=0;
- if(clk_cnt<(CLK_DIV_PERIOD/2)) clk_div<=0;
- else clk_div<=1;
- end
- end
- //divide clk_div 4 state, RISING and FALLING state is keeped one cycle of clk_in, like a pulse.
- reg[1:0] clk_div_state=CLK_L;
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in) clk_div_state<=CLK_L;
- else
- case(clk_div_state)
- CLK_L: begin
- if (clk_div) clk_div_state<=CLK_RISING_DEGE; ////////////////////////////////
- else clk_div_state<=CLK_L;
- end
- CLK_RISING_DEGE :clk_div_state<=CLK_H;
- CLK_H:begin
- if (!clk_div) clk_div_state<=CLK_FALLING_DEGE;////////////////////////////////
- else clk_div_state<=CLK_H;
- end
- CLK_FALLING_DEGE:clk_div_state<=CLK_L;
- default;
- endcase
- end
- reg shift_flag = 0;
- reg[6:0] x_reg;
- reg[2:0] y_reg;
- reg[7:0] char_reg;
- reg[8:0] temp_cnt;
- reg[7:0] data_reg;
- reg[2:0] data_state=IDLE;
- reg[2:0] data_state_back;
- reg[7:0] data_state_cnt=0;
- reg[3:0] shift_cnt=0;
- reg[25:0] delay_cnt=0;
- //Finite State Machine,
- always@(posedge clk_in or negedge rst_n_in)
- begin
- if(!rst_n_in)
- begin
- data_state<=IDLE;
- data_state_cnt<=0;
- shift_flag <= 0;
- lcd_ce_n_out<=HIGH;
- end
- else
- case (data_state)
- IDLE: begin
- lcd_ce_n_out<=HIGH;
- data_state_cnt<=data_state_cnt+1;
- case(data_state_cnt)
- 0: begin data_reg<=8'h21;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 1: begin data_reg<=8'hc8;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 2: begin data_reg<=8'h06;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 3: begin data_reg<=8'h13;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 4: begin data_reg<=8'h20;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 5: begin data_reg<=8'h0c;lcd_dc_out<=CMD;data_state<=SHIFT;data_state_back<=IDLE; end
- 6: begin data_state<=CLEAR;data_state_back<=CLEAR; end
-
- 7: begin data_state<=SETXY;data_state_back<=SETXY;x_reg<=7'b0000010;y_reg<=3'b001; end
- 8: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=37; end //E
- 9: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=35; end //C
- 10: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=34; end //B
- 11: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=35; end //C
-
- 12: begin data_state<=SETXY;data_state_back<=SETXY;x_reg<=7'b0000010;y_reg<=3'b010; end
- 13: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=87; end //w
- 14: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=65; end //a
- 15: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=78; end //n
- 16: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=71; end //g
- 17: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=27; end //
- 18: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=65; end //a
- 19: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=78; end //n
- 20: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=82; end //r
- 21: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=65; end //a
- 22: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=78; end //n
-
- 23: begin data_state<=SETXY;data_state_back<=SETXY;x_reg<=7'b0000010;y_reg<=3'b100; end
- 24: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[23:20]+16; end //hour
- 25: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[19:16]+16; end //hour
- 26: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=26; end
- 27: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[15:12]+16; end //min
- 28: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[11:8]+16; end //min
- 29: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=26; end
- 30: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[7:4]+16; end //sec
- 31: begin data_state<=DISPLAY;data_state_back<=DISPLAY;char_reg<=data_in[3:0]+16; end //sec
- 32: begin data_state_cnt<=23; end
- default;
- endcase
- end
-
- SHIFT: begin
- if(!shift_flag)
- begin
- if (clk_div_state==CLK_FALLING_DEGE)
- begin
- if (shift_cnt==8)
- begin
- shift_cnt<=0;
- data_state<=data_state_back;
- end
- else begin
- lcd_ce_n_out<=LOW;
- lcd_data_out<=data_reg[7];
- shift_flag <= 1;
- end
- end
- end
- else
- begin
- if (clk_div_state==CLK_RISING_DEGE)
- begin
- data_reg<={data_reg[6:0], data_reg[7]};
- shift_cnt<=shift_cnt+1;
- shift_flag <= 0;
- end
- end
- end
- CLEAR: begin
- data_reg<=8'h00;
- temp_cnt<=temp_cnt+1;
- lcd_ce_n_out<=HIGH;
- lcd_dc_out<=DATA;
- if (temp_cnt==504)
- begin
- temp_cnt<=0;
- data_state<=IDLE;
- end
- else data_state<=SHIFT;
- end
-
- SETXY: begin
- temp_cnt<=temp_cnt+1;
- lcd_ce_n_out<=HIGH;
- lcd_dc_out<=CMD;
- case (temp_cnt)
- 0 : begin data_reg<=(8'h80 | x_reg); data_state<=SHIFT; end
- 1 : begin data_reg<=(8'h40 | y_reg); data_state<=SHIFT; end
- 2 : begin data_state<=IDLE; temp_cnt<=0; end
- default;
- endcase
- end
- DISPLAY: begin
- temp_cnt<=temp_cnt+1;
- lcd_ce_n_out<=HIGH;
- lcd_dc_out<=DATA;
- if (temp_cnt==6)
- begin
- data_state<=IDLE;
- temp_cnt<=0;
- end
- else
- begin
- temp=mem[char_reg];
- case (temp_cnt)
- 0 : data_reg<=temp[47:40];
- 1 : data_reg<=temp[39:32];
- 2 : data_reg<=temp[31:24];
- 3 : data_reg<=temp[23:16];
- 4 : data_reg<=temp[15:8];
- 5 : data_reg<=temp[7:0];
- default;
- endcase
- data_state<=SHIFT;
- end
- end
- DELAY: begin
- if(delay_cnt==DELAY_PERIOD)
- begin
- data_state<=IDLE;
- delay_cnt<=0;
- end
- else delay_cnt<=delay_cnt+1;
- end
-
- default;
- endcase
- end
- endmodule
复制代码实际编译分配管脚信息如下:
编译加载后按照上面硬件连接,就OK了。
|