loadomain

博客园 首页 新随笔 联系 订阅 管理

开发工具:Quartus II 9.1;

仿真软件:Questa Sim 10.0c;

硬件平台:Terasic DE2-115(EP2C35F672C6);

外设:hd44780控制器lcd1602;

3个工程文件:"lcd1602_cgram_controller.v" + "lcd1602_cgram_driver.v" + "lcd1602_cgram_driver_tsb.v";

设计思路:

  底层直接操作lcd1602的模块为"*_controller.v"文件,三段式状态机,完成初始化液晶工作模式(无光标、5X8、2行...)、在CGRAM写入自定义的8个字符(源文件里条形图,可用于音频FFT波形图显示),完成CGRAM写数据之后进入通用的显示状态,每次显示完一个字符产生的ack信号;

  "_driver.v"完成循环调用显示8个自定义字符;

  "_driver_tsb.v"完成仿真时的驱动(原本是和"_driver.v"在同一个文件,为了方便后续综合,分开了);

注意事项:

  系统工作频率为50MHz,lcd操作的指令、数据周期为2ms(1ms下也能用);

  CYCLONEII的芯片上电未复位之前的寄存器是0,因此程序下载到板子上的时候液晶是不显示的,没有复位引脚的需要自行设计软件复位;

  lcd_on,lcd_blon为DE2-115板子特有设计;

源码1...

  1 `timescale 1 ns / 1 ps
  2 //`define SIM
  3 `define SYS_CLK 50_000_000
  4 //achieve lcd1602 cgram display
  5 //author wuyuehang1990
  6 //version 0.1
  7 module lcd1602_cgram_controller(
  8                                                     sys_clk,
  9                                                     sys_rst_n,
 10                                                     sys_dat_i,
 11                                                     sys_addr_i,
 12                                                     lcd_ack_o,
 13                                                     lcd_en,
 14                                                     lcd_rw,
 15                                                     lcd_rs,
 16                                                     lcd_bus,
 17                                                     lcd_on,
 18                                                     lcd_blon
 19                                                     );
 20 
 21 input sys_clk;
 22 input sys_rst_n;
 23 input [7:0] sys_dat_i;//CGRAM ONLY DISP 8 DIFFERENT FONTS//00~07
 24 input [7:0] sys_addr_i;//DDRAM ADDR
 25 output reg lcd_ack_o;
 26 //lcd interface
 27 output lcd_en;
 28 output lcd_rw;
 29 output reg lcd_rs;
 30 output reg [7:0] lcd_bus;
 31 //spec io
 32 output lcd_on;
 33 output lcd_blon;
 34 
 35 
 36 `ifdef SIM
 37         parameter ST_WIDTH = 64;
 38         parameter CLR = "CLR.....";
 39         parameter FUNC = "FUNC....";
 40         parameter ONOFF = "ON/OFF..";
 41         parameter ENTRY = "ENTRY...";
 42         parameter SETCGRAM = "SETCGRAM";
 43         parameter WRCGRAM = "WR_CGRAM";
 44         parameter SETDDRAM = "SETDDRAM";
 45         parameter WRDDRAM = "WR_DDRAM";
 46         parameter ACK = "ACK....."; 
 47 `else
 48         `define FSM 9
 49         parameter ST_WIDTH = `FSM;
 50         parameter CLR = `FSM'b0_0000_0001;//01
 51         parameter FUNC = `FSM'b0_0000_0010;//38(8BUS-2LINE)        37(8BUS-1LINE)
 52         parameter ONOFF = `FSM'b0_0000_0100;//0C(ON-SHINE)
 53         parameter ENTRY = `FSM'b0_0000_1000;//06(DISP_FIXED-CURSOR_SHIFT)
 54         parameter SETCGRAM = `FSM'b0_0001_0000;
 55         parameter WRCGRAM = `FSM'b0_0010_0000;
 56         parameter SETDDRAM = `FSM'b0_0100_0000;
 57         parameter WRDDRAM = `FSM'b0_1000_0000;
 58         parameter ACK = `FSM'b1_0000_0000;
 59         
 60 `endif
 61 
 62 //generate 1KHz(1ms)
 63 reg [19:0] cnt_1KHz=0;
 64 reg clk_1KHz=0;
 65 reg pulse1ms=0;
 66 
 67 always @ (posedge sys_clk) begin
 68 if(sys_rst_n == 1'b0)    begin
 69                                 cnt_1KHz <= 0;
 70                                 end
 71 else if(cnt_1KHz > 20'd99999) begin
 72                                                 cnt_1KHz <= 0;
 73                                                 end
 74 else begin
 75         cnt_1KHz <= cnt_1KHz + 1'd1;
 76         end
 77 end
 78 
 79 always @ (posedge sys_clk) begin
 80 if(cnt_1KHz < 20'd49999)    begin
 81                                         clk_1KHz <= 1'd1;
 82                                         end
 83 else begin
 84         clk_1KHz <= 1'd0;
 85         end
 86 end
 87 
 88 always @ (posedge sys_clk) begin
 89 if(cnt_1KHz == 20'd99999) pulse1ms <= 1'd1;
 90 else pulse1ms <= 1'd0;
 91 end
 92 
 93 //generate lcd_en,lcd_rw;
 94 assign lcd_en = clk_1KHz;
 95 assign lcd_rw = 1'b0;
 96 //generate spec io
 97 assign lcd_on = 1'b1;
 98 assign lcd_blon = 1'b1;
 99 
100 //FSM
101 reg [5:0] cnt64=0;//count 64 hex char
102 reg [ST_WIDTH-1:0] c_st = FUNC;
103 reg [ST_WIDTH-1:0] n_st = FUNC;
104 //fsm-1
105 always @ (posedge sys_clk) begin
106 if(1'b0 == sys_rst_n)    c_st <= FUNC;
107 else c_st <= n_st;
108 end
109 
110 //fsm-2
111 always @ (*) begin
112         n_st = FUNC;
113         case(c_st)
114             FUNC:begin
115                         n_st = (pulse1ms == 1'b1)?ONOFF:FUNC;
116                         end
117             ONOFF:begin
118                         n_st = (pulse1ms == 1'b1)?ENTRY:ONOFF;
119                         end
120             ENTRY:begin
121                         n_st = (pulse1ms == 1'b1)?CLR:ENTRY;
122                         end
123             CLR:begin
124                         n_st = (pulse1ms == 1'b1)?SETCGRAM:CLR;
125                         end
126             SETCGRAM:begin
127                                 n_st = (pulse1ms == 1'b1)?WRCGRAM:SETCGRAM;
128                                 end
129             WRCGRAM:begin
130                                     if((pulse1ms == 1'b1) && (cnt64 == 6'd63))
131                                             n_st = SETDDRAM;
132                                     else if(pulse1ms == 1'b1)
133                                             n_st = SETCGRAM;
134                                     else 
135                                             n_st = WRCGRAM;
136                                 end
137             SETDDRAM:begin
138                                 n_st = (pulse1ms == 1'b1)?WRDDRAM:SETDDRAM;
139                                 end
140             WRDDRAM:begin
141                                 n_st = (pulse1ms == 1'b1)?ACK:WRDDRAM;
142                                 end
143             ACK:begin
144                     n_st  = SETDDRAM;
145                     end
146             default:begin
147                         n_st = FUNC;
148                         end
149             endcase
150 end
151 
152 //FSM-3
153 //generate lcd_bus lcd_rs and lcd_ack
154 
155 always @ (posedge sys_clk) begin
156 if(1'b0 == sys_rst_n) begin
157                                 lcd_ack_o <= 0;
158                                 lcd_rs <= 0;
159                                 lcd_bus <= 8'h38;
160                                 cnt64 <= 0;
161                                 end
162 else begin
163         case(n_st)
164         FUNC:begin
165                     lcd_rs <= 0;
166                     lcd_ack_o <= 0;
167                     lcd_bus <= 8'h38;//3c(2-line-5*10)//38(2-line-5*8)
168                     cnt64 <= 6'd63;
169                     end
170         ONOFF:begin
171                     lcd_rs <= 0;
172                     lcd_ack_o <= 0;
173                     lcd_bus <= 8'h0d;//no cursor
174                     cnt64 <= 6'd63;
175                     end
176         ENTRY:begin
177                     lcd_rs <= 0;
178                     lcd_ack_o <= 0;
179                     lcd_bus <= 8'h06;
180                     cnt64 <= 6'd63;
181                     end
182         CLR:begin
183                     lcd_rs <= 0;
184                     lcd_ack_o <= 0;
185                     lcd_bus <= 8'h01;
186                     cnt64 <= 6'd63;
187                     end
188         SETCGRAM:begin
189                                 lcd_ack_o <= 0;
190                                 lcd_rs <= 0;
191                                 cnt64 <= (pulse1ms == 1'b1)?cnt64 + 1'd1:cnt64;
192                                 lcd_bus <= {2'b01,cnt64};
193                             end
194         WRCGRAM:begin
195                                 lcd_ack_o <= 0;
196                                 lcd_rs <= 1;
197                                 cnt64 <= cnt64;
198                                 /*
199                                 case(cnt64)
200                                 6'd0,6'd1,6'd2,6'd3,6'd4,6'd5,6'd6,6'd7:lcd_bus <= 8'h00;//empty
201                                 6'd8,6'd9,6'd10,6'd11,6'd12,6'd13:lcd_bus <= 8'h00;
202                                 6'd14:lcd_bus <= 8'h1f;
203                                 6'd15:lcd_bus <= 8'h00;//1step
204                                 6'd16,6'd17,6'd18,6'd19,6'd20:lcd_bus <= 8'h00;
205                                 6'd21,6'd22:lcd_bus <= 8'h1f;
206                                 6'd23:lcd_bus <= 8'h00;//2step
207                                 6'd24,6'd25,6'd26,6'd27:lcd_bus <= 8'h00;
208                                 6'd28,6'd29,6'd30:lcd_bus <= 8'h1f;
209                                 6'd31:lcd_bus <= 8'h00;//3step
210                                 6'd32,6'd33,6'd34:lcd_bus <= 8'h00;
211                                 6'd35,6'd36,6'd37,6'd38:lcd_bus <= 8'h1f;
212                                 6'd39:lcd_bus <= 8'h00;//4step
213                                 6'd40,6'd41:lcd_bus <= 8'h00;
214                                 6'd42,6'd43,6'd44,6'd45,6'd46:lcd_bus <= 8'h1f;
215                                 6'd47:lcd_bus <= 8'h00;//5step
216                                 6'd48:lcd_bus <= 8'h00;
217                                 6'd49,6'd50,6'd51,6'd52,6'd53,6'd54:lcd_bus <= 8'h1f;
218                                 6'd55:lcd_bus <= 8'h00;//6step
219                                 6'd56,6'd57,6'd58,6'd59,6'd60,6'd61,6'd62:lcd_bus <= 8'h1f;
220                                 6'd63:lcd_bus <= 8'h00;//7step
221                                 endcase
222                                 */
223                                 case(cnt64)
224                                 6'd0,6'd1,6'd2,6'd3,6'd4,6'd5,6'd6:lcd_bus <= 8'h00;
225                                 6'd7:lcd_bus <= 8'h1f;//s1
226                                 6'd8,6'd9,6'd10,6'd11,6'd12,6'd13:lcd_bus <= 8'h00;
227                                 6'd14:lcd_bus <= 8'h1f;
228                                 6'd15:lcd_bus <= 8'h1f;//s2
229                                 6'd16,6'd17,6'd18,6'd19,6'd20:lcd_bus <= 8'h00;
230                                 6'd21,6'd22:lcd_bus <= 8'h1f;
231                                 6'd23:lcd_bus <= 8'h1f;//s3
232                                 6'd24,6'd25,6'd26,6'd27:lcd_bus <= 8'h00;
233                                 6'd28,6'd29,6'd30:lcd_bus <= 8'h1f;
234                                 6'd31:lcd_bus <= 8'h1f;//4step
235                                 6'd32,6'd33,6'd34:lcd_bus <= 8'h00;
236                                 6'd35,6'd36,6'd37,6'd38:lcd_bus <= 8'h1f;
237                                 6'd39:lcd_bus <= 8'h1f;//5step
238                                 6'd40,6'd41:lcd_bus <= 8'h00;
239                                 6'd42,6'd43,6'd44,6'd45,6'd46:lcd_bus <= 8'h1f;
240                                 6'd47:lcd_bus <= 8'h1f;//6step
241                                 6'd48:lcd_bus <= 8'h00;
242                                 6'd49,6'd50,6'd51,6'd52,6'd53,6'd54:lcd_bus <= 8'h1f;
243                                 6'd55:lcd_bus <= 8'h1f;//7step
244                                 6'd56,6'd57,6'd58,6'd59,6'd60,6'd61,6'd62:lcd_bus <= 8'h1f;
245                                 6'd63:lcd_bus <= 8'h1f;//8step
246                                 endcase
247                             end
248         SETDDRAM:begin
249                                 lcd_ack_o <= 0;
250                                 lcd_rs <= 0;
251                                 lcd_bus <= sys_addr_i;
252                                 cnt64 <= cnt64;
253                                 end
254         WRDDRAM:begin
255                                 lcd_ack_o <= 0;
256                                 lcd_rs <= 1;
257                                 cnt64 <= cnt64;
258                                 lcd_bus <= sys_dat_i;
259                                 end
260         ACK:begin
261                                 lcd_ack_o <= 1;
262                                 lcd_rs <= 0;
263                                 lcd_bus <= lcd_bus;
264                                 cnt64 <= cnt64;
265                                 end
266         default:begin
267                                 lcd_ack_o <= 0;
268                                 lcd_rs <= 0;
269                                 lcd_bus <= 8'h38;
270                                 cnt64 <= cnt64;
271                                 end
272         endcase
273         end
274 end
275 
276 endmodule

源码2...

 1 `timescale 1 ns / 1 ps
 2 module lcd1602_cgram_driver(
 3                                                             sys_clk,
 4                                                             sys_rst_n,
 5                                                             lcd_en,
 6                                                             lcd_rw,
 7                                                             lcd_rs,
 8                                                             lcd_bus,
 9                                                             lcd_on,
10                                                             lcd_blon
11                                                             );
12 input sys_clk;
13 input sys_rst_n;
14 output lcd_rs;
15 output lcd_rw;
16 output lcd_en;
17 output lcd_on;
18 output lcd_blon;
19 output [7:0] lcd_bus;
20 
21 
22 reg [7:0] sys_dat_i=0;
23 reg [7:0] sys_addr_i=0;
24 wire lcd_ack_o;
25 
26 
27 always @ (posedge sys_clk) begin
28 if(sys_rst_n == 1'b0) begin
29                                 sys_dat_i <= 0;
30                                 sys_addr_i <= 8'h80;
31                                 end
32 else if(lcd_ack_o == 1'b1) begin
33                                             if(sys_dat_i == 8'd7)    begin
34                                                                                 sys_dat_i <= 0;
35                                                                                 sys_addr_i <= 8'h80;
36                                                                                 end
37                                             else begin
38                                                     sys_dat_i <= sys_dat_i + 1'd1;
39                                                     sys_addr_i <= sys_addr_i + 1'd1;
40                                                     end
41                                         end
42 else begin
43         sys_dat_i <= sys_dat_i;
44         sys_addr_i <= sys_addr_i;
45         end
46 end
47 
48 
49 
50 lcd1602_cgram_controller                hal(
51                                                     .sys_clk( sys_clk ),
52                                                     .sys_rst_n( sys_rst_n ),
53                                                     .sys_dat_i( sys_dat_i ),
54                                                     .sys_addr_i( sys_addr_i ),
55                                                     .lcd_ack_o( lcd_ack_o ),
56                                                     .lcd_en( lcd_en ),
57                                                     .lcd_rw( lcd_rw ),
58                                                     .lcd_rs( lcd_rs ),
59                                                     .lcd_bus( lcd_bus ),
60                                                     .lcd_on( lcd_on ),
61                                                     .lcd_blon( lcd_blon )
62                                                     );
63 
64 endmodule

源码3...

`timescale 1 ns / 1 ps
module lcd1602_cgram_driver_tsb();
reg sys_clk;
reg sys_rst_n;

initial begin
sys_clk=1;
sys_rst_n=0;
#100 sys_rst_n=1;
end

always begin
#10 sys_clk=~sys_clk;
end

wire lcd_rw;
wire lcd_rs;
wire lcd_en;
wire [7:0] lcd_bus;
wire lcd_on;
wire lcd_blon;

lcd1602_cgram_driver                            api(
                                                            .sys_clk( sys_clk ),
                                                            .sys_rst_n( sys_rst_n ),
                                                            .lcd_en( lcd_en ),
                                                            .lcd_rw( lcd_rw ),
                                                            .lcd_rs( lcd_rs ),
                                                            .lcd_bus( lcd_bus ),
                                                            .lcd_on( lcd_on ),
                                                            .lcd_blon( lcd_blon )
                                                            );
                                                            
endmodule

 

posted on 2013-07-30 10:51  loadomain  阅读(876)  评论(0编辑  收藏  举报