BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / circuit / #17274同步于 2011/5/19
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Circuit机器人发帖

verilog编一个液晶显示,问题求助

anhenaiguo
2011/5/19镜像同步2 回复
现在的问题是,烧进了cpld里面以后,液晶1602只能出现一行黑框,我琢磨是不是不能直接给赋值字符,得有一个转换模块呢?求改编,只要能显示hello就行,代码如下 // LCD_Top.v //连接Clock_Gen模块和LCD_Driver模块 module LCD_Top(clk_48M,rst,LCD_EN,RS,RW,DB8); input clk_48M,rst; output LCD_EN,RS,RW; output [7:0] DB8; wire clk_LCD; //用于将Clock_Gen模块clk_LCD输出连接至LCD_Driver模块的clk_LCD输入 Clock_Gen U1(.clk_48M(clk_48M), .rst(rst), .clk_LCD(clk_LCD)); LCD_Driver U2(.clk_LCD(clk_LCD), .rst(rst), .LCD_EN(LCD_EN), .RS(RS), .RW(RW), .DB8(DB8)); endmodule // Clock_Gen.v /****************为LCD_Drvier模块产生500Hz的时钟信号**************/ module Clock_Gen(clk_48M,rst,clk_LCD); input clk_48M,rst; //rst为全局复位信号(高电平有效) output clk_LCD; wire clk_counter; reg [11:0] cnt; //对时钟进行计数分频 wire clk_equ; reg [9:0] count; reg clk_BUF; parameter counter= 50; //多少分频 /******************************************************************************** ** 模块名称:分频器 ** 功能描述:通过计数器实现分频功能. ********************************************************************************/ always@(posedge clk_48M) begin if(!rst) //低电平复位 cnt <= 12'd0; else if(clk_equ) cnt <= 12'd0; else cnt <= cnt+1'b1; end assign clk_equ = (cnt==counter); assign clk_counter = clk_equ; always @(posedge clk_counter or negedge rst) begin //利用计数器分频产生500Hz时钟 if(!rst) begin clk_BUF <= 1'b0; count <= 10'b0; end else begin if(count == 10'd1000) begin clk_BUF <= ~clk_BUF; count <= 10'b0; end else begin clk_BUF <= clk_BUF; //clk_BUF为500Hz的时钟信号 count <= count + 1'b1; end end end assign clk_LCD = clk_BUF; //clk_LCD为LCD_Drvier模块所需要的500Hz的时钟信号 endmodule // LCD_Driver.v //功能简述:在1602液晶模块上显示字符串,其中第一行显示"Welcom to hx" // 在第二行显示"www.mcuhx.com" //液晶模块为TC1602A,相关特性请参考其数据手册 module LCD_Driver(clk_LCD,rst,LCD_EN,RS,RW,DB8); input clk_LCD,rst; //rst为全局复位信号(高电平有效) output LCD_EN,RS,RW; //LCD_EN为LCD模块的使能信号(下降沿触发) //RS=0时为写指令;RS=1时为写数据 //RW=0时对LCD模块执行写操作;RW=1时对LCD模块执行读操作 output [7:0] DB8; //8位指令或数据总线 reg [7:0] DB8; reg [48:0] Data_First_Buf,Data_Second_Buf; //液晶显示的数据缓存 reg RS,LCD_EN_Sel; reg [3:0] disp_count; reg [3:0] state; parameter Clear_Lcd = 4'b0000, //清屏并光标复位 Set_Disp_Mode = 4'b0001, //设置显示模式:8位2行5x7点阵 Disp_On = 4'b0010, //显示器开、光标不显示、光标不允许闪烁 Shift_Down = 4'b0011, //文字不动,光标自动右移 Write_Addr = 4'b0100, //写入显示起始地址 Write_Data_First = 4'b0101, //写入第一行显示的数据 Write_Data_Second = 4'b0110, //写入第二行显示的数据 Idel = 4'b0111; //空闲状态 parameter Data_First = "w", //液晶显示的第一行的数据 Data_Second = "B"; //液晶显示的第二行的数据 assign RW = 1'b0; //RW=0时对LCD模块执行写操作 assign LCD_EN = LCD_EN_Sel ? clk_LCD : 1'b0; //通过LCD_EN_Sel信号来控制LCD_EN的开启与关闭 always @(posedge clk_LCD or negedge rst) begin if(!rst) begin state <= Clear_Lcd; //复位:清屏并光标复位 RS <= 1'b0; //复位:RS=0时为写指令; DB8 <= 8'b0; //复位:使DB8总线输出全0 LCD_EN_Sel <= 1'b1; //复位:开启夜晶使能信号 //Data_First_Buf <= Data_First; //Data_Second_Buf <= Data_Second; disp_count <= 4'b0; end else case(state) //初始化LCD模块 Clear_Lcd: begin state <= Set_Disp_Mode; DB8 <= 8'b00000001; //清屏并光标复位 end Set_Disp_Mode: begin state <= Disp_On; DB8 <= 8'b00111000; //设置显示模式:8位2行5x8点阵 end Disp_On: begin state <= Shift_Down; DB8 <= 8'b00001100; //显示器开、光标不显示、光标不允许闪烁 end Shift_Down: begin state <= Write_Addr; DB8 <= 8'b00000110; //文字不动,光标自动右移 end Write_Addr: begin state <= Write_Data_First; DB8 <= 8'b10000001; //写入第一行显示起始地址:第一行第二个位置 Data_First_Buf <= Data_First; //将第一行显示的数据赋给Data_First_Buf? end Write_Data_First: //写第一行数据 begin if(disp_count == 7) //disp_count等于14时表示第一行数据已写完 begin DB8 <= 8'b11000001; //送入写第二行的指令 RS <= 1'b0; disp_count <= 4'b0; Data_Second_Buf <= Data_Second; state <= Write_Data_Second; //写完第一行进入写第二行状态 end else begin DB8 <= Data_First; Data_First_Buf <= (Data_First_Buf << 8); RS <= 1'b1; //RS=1表示写数据 disp_count <= disp_count + 1'b1; state <= Write_Data_First; end end Write_Data_Second: //写第二行数据 begin if(disp_count == 7) begin LCD_EN_Sel <= 1'b0; RS <= 1'b0; disp_count <= 4'b0; state <= Idel; //写完进入空闲状态 end else begin DB8 <= Data_First; Data_Second_Buf <= (Data_Second_Buf << 8); RS <= 1'b1; disp_count <= disp_count + 1'b1; state <= Write_Data_Second; end end Idel: begin state <= Idel; //在Idel状态循环 end default: state <= Clear_Lcd; //若state为其他值,则将state置为Clear_Lcd endcase end endmodule
订阅后,新回复会通过你的通知中心匿名送达。
2 条回复
huanyu机器人#1 · 2011/5/27
Set_Disp_Mode一定要在第一步做,然后是clear_disp 下面这两行是什么东西?? parameter Data_First = "w", //液晶显示的第一行的数据 Data_Second = "B"; //液晶显示的第二行的数据 可综合的verilog代码只认识二进制,你给个字符串显然是有问题的。 LCD的字符是有映射的,W用8'b0101_0111表示,找个1602的手册看看就知道了
huanyu机器人#2 · 2011/5/27
附件是一款类似芯片的手册,时序是一样的,仅供参考 另外记得看看手册里面的操作顺序,先做什么操作,后做什么操作 【 在 anhenaiguo 的大作中提到: 】 : 现在的问题是,烧进了cpld里面以后,液晶1602只能出现一行黑框,我琢磨是不是不能直接给赋值字符,得有一个转换模块呢?求改编,只要能显示hello就行,代码如下 : // LCD_Top.v : //连接Clock_Gen模块和LCD_Driver模块 : ................... 附件(615.3KB) SITRONIX_ST7066U.pdf