交一下LCD1602的作业。
这次学到了不少,刚开始自己听完课之后,看着数据手册,写完了代码,慢慢编译过来,成功了一大部分,最后的两个状态转换搞错了,后来跟51FPGA 大神的源代码进行比较,根据他的正确代码一点点纠正状态机的源代码,结果,跟51FPGA 大大的几乎一样了。不过还是学到了很多。
以下是源代码:
`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: Charles Wang // // Create Date: 06/23/2014 // Design Name: lcd1602_clock // Module Name: lcd1602_clock // Project Name: lcd1602_clock // Target Devices: EP4CE6E22C8 // Tool versions: Quartus II 13.1 // Description: 用LCD1602显示数字时钟 // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module lcd1602_clock(clk,rst_n,lcd_en,lcd_rs,lcd_rw,lcd_data); input clk; input rst_n; output lcd_en; output lcd_rs; output lcd_rw; output [7:0]lcd_data; reg lcd_rs; reg [7:0]lcd_data; reg clk_div; reg [4:0]char_cnt; reg [9:0]state; reg [17:0]delay_cnt; reg [7:0]lcd_data_r; parameter idle =10'b00_0000_0001, clear =10'b00_0000_0010, set_function =10'b00_0000_0100, switch_mode =10'b00_0000_1000, set_mode =10'b00_0001_0000, shift =10'b00_0010_0000, set_ddram1 =10'b00_0100_0000, set_ddram2 =10'b00_1000_0000, write_ddram1 =10'b01_0000_0000, write_ddram2 =10'b10_0000_0000; assign lcd_en = clk_div; assign lcd_rw = 1'b0; /////////////////////////////////////////////////////////////////////////////// always@(posedge clk or negedge rst_n) begin if(!rst_n) begin delay_cnt <= 18'h0; clk_div <= 1'b0; end else if(delay_cnt == 18'd249999) begin delay_cnt <= 18'h0; clk_div <= ~ clk_div; end else begin delay_cnt <= delay_cnt + 1'b1; clk_div <= clk_div; end end //////////////////////////////////////////////////////////////////////////////// always@(posedge clk_div or negedge rst_n)//状态机模块 begin if(!rst_n) begin state <= idle; char_cnt<= 5'd0; end else case(state) idle: //起始状态 begin lcd_data <= 8'bzzzz_zzzz; state <= clear; end clear: //清屏 begin lcd_rs <= 1'b0; lcd_data <= 8'b0000_0001; state <= set_function; end set_function: //功能设置:8位数据接口/2行显示/5*8点阵字符 begin lcd_rs <= 1'b0; lcd_data <= 8'b0011_1000; state <= switch_mode; end switch_mode: //开关模式:开显示,关闭光标和闪烁 begin lcd_rs <= 1'b0; lcd_data <= 8'b0000_1100; state <= set_mode; end set_mode: //输入方式:数据读写操作后,地址自动加一/画面不动 begin lcd_rs <= 1'b0; state <= shift; lcd_data <= 8'b0000_0110; end shift: begin lcd_rs <= 1'b0; lcd_data <= 8'b0001_0000; state <= set_ddram1; end set_ddram1: begin lcd_rs <= 1'b0; lcd_data <= 8'b1000_0000; state <= write_ddram1; end set_ddram2: begin lcd_rs <= 1'b0; lcd_data <= 8'b1100_0000; state <= write_ddram2; end write_ddram1: begin if(char_cnt <= 5'd15) begin lcd_rs <= 1'b1; char_cnt <= char_cnt + 1'b1; lcd_data <= lcd_data_r; state <= write_ddram1; end else state <= set_ddram2; end write_ddram2: begin if(char_cnt <= 5'd30) begin char_cnt <= char_cnt + 1'b1; lcd_rs <= 1'b1; lcd_data <= lcd_data_r; state <= write_ddram2; end else begin char_cnt <= 5'd0; state <= shift; end end default: state <= idle; endcase end always@(char_cnt) //显示相关字符 begin case(char_cnt) 5'd0: lcd_data_r <= "D"; 5'd1: lcd_data_r <= "e"; 5'd2: lcd_data_r <= "s"; 5'd3: lcd_data_r <= "i"; 5'd4: lcd_data_r <= "g"; 5'd5: lcd_data_r <= "n"; 5'd6: lcd_data_r <= " "; 5'd7: lcd_data_r <= "b"; 5'd8: lcd_data_r <= "y"; 5'd9: lcd_data_r <= " "; 5'd10: lcd_data_r <= "C"; 5'd11: lcd_data_r <= "h"; 5'd12: lcd_data_r <= "a"; 5'd13: lcd_data_r <= "r"; 5'd14: lcd_data_r <= "l"; 5'd15: lcd_data_r <= "e"; 5'd16: lcd_data_r <= " "; 5'd17: lcd_data_r <= "T"; 5'd18: lcd_data_r <= "i"; 5'd19: lcd_data_r <= "m"; 5'd20: lcd_data_r <= "e"; 5'd21: lcd_data_r <= ":"; 5'd22: lcd_data_r <= " "; 5'd23: lcd_data_r <= hour_reg_dec_char; 5'd24: lcd_data_r <= hour_reg_bit_char; 5'd25: lcd_data_r <= "-"; 5'd26: lcd_data_r <= minu_reg_dec_char; 5'd27: lcd_data_r <= minu_reg_bit_char; 5'd28: lcd_data_r <= "-"; 5'd29: lcd_data_r <= sec_reg_dec_char; 5'd30: lcd_data_r <= sec_reg_bit_char; default: lcd_data_r <= ""; endcase end //////////////////////////////////////////////////////////////////////////////// reg [2:0]sec_reg_dec;//秒的十位 reg [3:0]sec_reg_bit;//秒的个位 reg [2:0]minu_reg_dec;//分的十位 reg [3:0]minu_reg_bit;//分的个位 reg [3:0]hour_reg_dec;//小时的十位 reg [1:0]hour_reg_bit;//小时的个位 reg [27:0]delay_cnt_clock;//数字时钟计数器分频寄存器 always@(posedge clk or negedge rst_n)//数字时钟计数器分频模块,50MHz → 1Hz begin if(!rst_n) delay_cnt_clock <= 28'h0000000; else if(delay_cnt_clock == 28'd49999999) delay_cnt_clock <= 28'd0; else delay_cnt_clock <= delay_cnt_clock + 1'b1; end always@(posedge clk or negedge rst_n)//数字时钟模块 begin if(!rst_n) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= 4'd0; minu_reg_dec<= 3'd0; hour_reg_bit<= 4'd0; hour_reg_dec<= 2'd0; end else if(delay_cnt_clock == 28'd49999999) begin if(sec_reg_bit == 4'd9 && sec_reg_dec == 3'd5) begin if(hour_reg_bit == 4'd3 && hour_reg_dec == 2'd2 && minu_reg_bit == 4'd9 && minu_reg_dec == 3'd5) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= 4'd0; minu_reg_dec<= 3'd0; hour_reg_bit<= 4'd0; hour_reg_dec<= 2'd0; end else if(hour_reg_bit == 4'd9 && hour_reg_dec < 2'd2 && minu_reg_bit == 4'd9 && minu_reg_dec == 3'd5) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= 4'd0; minu_reg_dec<= 3'd0; hour_reg_bit<= 4'd0; hour_reg_dec <= hour_reg_dec + 1'b1; end else if(hour_reg_bit <4'd9 && minu_reg_bit == 4'd9 && minu_reg_dec == 3'd5) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= 4'd0; minu_reg_dec<= 3'd0; hour_reg_bit <= hour_reg_bit + 1'b1; hour_reg_dec <= hour_reg_dec; end else if(minu_reg_bit == 4'd9 && minu_reg_dec < 3'd5) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= 4'd0; minu_reg_dec<= minu_reg_dec + 1'b1; hour_reg_bit<= hour_reg_bit; hour_reg_dec<= hour_reg_dec; end else if(minu_reg_bit < 4'd9) begin sec_reg_bit <= 4'd0; sec_reg_dec <= 3'd0; minu_reg_bit<= minu_reg_bit + 1'b1; minu_reg_dec<= minu_reg_dec; hour_reg_bit<= hour_reg_bit; hour_reg_dec<= hour_reg_dec; end end else if(sec_reg_bit == 4'd9 && sec_reg_dec < 3'd5) begin sec_reg_bit <= 4'd0; sec_reg_dec <= sec_reg_dec + 1'b1; minu_reg_bit<= minu_reg_bit; minu_reg_dec<= minu_reg_dec; hour_reg_bit<= hour_reg_bit; hour_reg_dec<= hour_reg_dec; end else begin sec_reg_bit <= sec_reg_bit + 1'b1; sec_reg_dec <= sec_reg_dec; minu_reg_bit<= minu_reg_bit; minu_reg_dec<= minu_reg_dec; hour_reg_bit<= hour_reg_bit; hour_reg_dec<= hour_reg_dec; end end else begin sec_reg_bit <= sec_reg_bit; sec_reg_dec <= sec_reg_dec; minu_reg_bit<= minu_reg_bit; minu_reg_dec<= minu_reg_dec; hour_reg_bit<= hour_reg_bit; hour_reg_dec<= hour_reg_dec; end end //////////////////////////////////////////////////////////////////////////////// //将数字时钟的秒、分、时以字符的形式显示在LCD屏幕上 reg[7:0] sec_reg_bit_char; reg[7:0] sec_reg_dec_char; reg[7:0] minu_reg_bit_char; reg[7:0] minu_reg_dec_char; reg[7:0] hour_reg_bit_char; reg[7:0] hour_reg_dec_char; always@(sec_reg_bit) begin case(sec_reg_bit) 4'd0: sec_reg_bit_char <= "0"; 4'd1: sec_reg_bit_char <= "1"; 4'd2: sec_reg_bit_char <= "2"; 4'd3: sec_reg_bit_char <= "3"; 4'd4: sec_reg_bit_char <= "4"; 4'd5: sec_reg_bit_char <= "5"; 4'd6: sec_reg_bit_char <= "6"; 4'd7: sec_reg_bit_char <= "7"; 4'd8: sec_reg_bit_char <= "8"; 4'd9: sec_reg_bit_char <= "9"; default:sec_reg_bit_char <= sec_reg_bit_char; endcase end always@(sec_reg_dec) begin case(sec_reg_dec) 3'd0: sec_reg_dec_char <= "0"; 3'd1: sec_reg_dec_char <= "1"; 3'd2: sec_reg_dec_char <= "2"; 3'd3: sec_reg_dec_char <= "3"; 3'd4: sec_reg_dec_char <= "4"; 3'd5: sec_reg_dec_char <= "5"; default:sec_reg_dec_char <= "0"; endcase end always@(minu_reg_bit) begin case(minu_reg_bit) 4'd0: minu_reg_bit_char <= "0"; 4'd1: minu_reg_bit_char <= "1"; 4'd2: minu_reg_bit_char <= "2"; 4'd3: minu_reg_bit_char <= "3"; 4'd4: minu_reg_bit_char <= "4"; 4'd5: minu_reg_bit_char <= "5"; 4'd6: minu_reg_bit_char <= "6"; 4'd7: minu_reg_bit_char <= "7"; 4'd8: minu_reg_bit_char <= "8"; 4'd9: minu_reg_bit_char <= "9"; default: minu_reg_bit_char <= "0"; endcase end always@(minu_reg_dec) begin case(minu_reg_dec) 3'd0: minu_reg_dec_char <= "0"; 3'd1: minu_reg_dec_char <= "1"; 3'd2: minu_reg_dec_char <= "2"; 3'd3: minu_reg_dec_char <= "3"; 3'd4: minu_reg_dec_char <= "4"; 3'd5: minu_reg_dec_char <= "5"; default:minu_reg_dec_char <= "0"; endcase end always@(hour_reg_bit) begin case(hour_reg_bit) 4'd0: hour_reg_bit_char <= "0"; 4'd1: hour_reg_bit_char <= "1"; 4'd2: hour_reg_bit_char <= "2"; 4'd3: hour_reg_bit_char <= "3"; 4'd4: hour_reg_bit_char <= "4"; 4'd5: hour_reg_bit_char <= "5"; 4'd6: hour_reg_bit_char <= "6"; 4'd7: hour_reg_bit_char <= "7"; 4'd8: hour_reg_bit_char <= "8"; 4'd9: hour_reg_bit_char <= "9"; default: hour_reg_bit_char <= "0"; endcase end always@(hour_reg_dec) begin case(hour_reg_dec) 2'd0: hour_reg_dec_char <= "0"; 2'd1: hour_reg_dec_char <= "1"; 2'd2: hour_reg_dec_char <= "2"; default:hour_reg_dec_char <= "0"; endcase end endmodule