tiger1125 发表于 2009-8-6 15:45:29

暂时放下FPGA的学习,临别放上自己的文档,以作纪念

这份文档是基于周立功公司的EasyFPGA030开发板的。

研究FPGA也有一段时间了,由于自己资质愚笨,目前只能做到这样的水平,请各位兄弟不要见笑啦。

我所做的工作就是在这块简单的开发板上扩展LCD1602A,并用Verilog代码实现字符显示的功能。
对于高手来说这些是微不足道的,但是我希望自己的工作能帮入门的初学者。

放上文档预览一下吧:

http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_468006.jpg
(原文件名:EasyFPGA030 扩展 LCD应用文档1.jpg)

完整的文档下载:

点击此处下载 ourdev_468007.pdf(文件大小:166K) (原文件名:EasyFPGA030扩展LCD1602A应用文档.pdf)



Verilog源代码

源代码是在Altera公司的DE2开发板中的测试程序分离出来的,正因为它不是针对用户使用而编写的,所以当中很少注释说明。(一切版权归Altera公司所有。)

提示:要读懂下面的代码,建议大家首先了解一下1602的读写时序,时序的介绍在Datasheet中会有详细说明。这里由于篇幅有限,就不多赘述了。在关键的地方已经有注释说明了。


//把下面的代码保存为“LCD_Controller.v”文件

module LCD_Controller (        //        Host Side
                                                iDATA,iRS,
                                                iStart,oDone,
                                                iCLK,iRST_N,
                                                //        LCD Interface
                                                LCD_DATA,
                                                LCD_RW,
                                                LCD_EN,
                                                LCD_RS        );
//        CLK
parameter        CLK_Divide        =        16;

//        Host Side
input                iDATA;
input        iRS,iStart;
input        iCLK,iRST_N;
output        reg                oDone;
//        LCD Interface
output                LCD_DATA;
output        reg                LCD_EN;
output                        LCD_RW;
output                        LCD_RS;
//        Internal Register
reg                        Cont;
reg                        ST;
reg                preStart,mStart;

/////////////////////////////////////////////
//        Only write to LCD, bypass iRS to LCD_RS
assign        LCD_DATA        =        iDATA;
assign        LCD_RW                =        1'b0;//由于现在只写不读,所以LCD_RW直接置低电平
assign        LCD_RS                =        iRS;
/////////////////////////////////////////////

always@(posedge iCLK or negedge iRST_N)
begin
        if(!iRST_N)//?RST_N???????
        begin//???????????????
                oDone        <=        1'b0;
                LCD_EN        <=        1'b0;
                preStart<=        1'b0;
                mStart        <=        1'b0;
                Cont        <=        0;
                ST                <=        0;
        end
        else//???????
        begin
                //////        Input Start Detect ///////
                preStart<=        iStart;
                if({preStart,iStart}==2'b01)
                begin
                        mStart        <=        1'b1;
                        oDone        <=        1'b0;
                end
                //////////////////////////////////
                if(mStart)
                begin
                        case(ST)
                        0:        ST        <=        1;        //        Wait Setup
                        1:        begin
                                        LCD_EN        <=        1'b1;
                                        ST                <=        2;
                                end
                        2:        begin                                       
                                        if(Cont<CLK_Divide)
                                        Cont        <=        Cont+1;
                                        else
                                        ST                <=        3;
                                end
                        3:        begin
                                        LCD_EN        <=        1'b0;
                                        mStart        <=        1'b0;
                                        oDone        <=        1'b1;
                                        Cont        <=        0;
                                        ST                <=        0;
                                end
                        endcase
                end
        end
end

endmodule

//把下面的代码保存为“LCD_TEST.v”

module        LCD_TEST (        //        Host Side
                                        iCLK,iRST_N,
                                        //        LCD Side
                                        LCD_DATA,LCD_RW,LCD_EN,LCD_RS        );
//        Host Side
input                        iCLK,iRST_N;
//        LCD Side
output                LCD_DATA;
output                        LCD_RW,LCD_EN,LCD_RS;
//        Internal Wires/Registers
reg                LUT_INDEX;
reg                LUT_DATA;
reg                mLCD_ST;
reg                mDLY;
reg                        mLCD_Start;
reg                mLCD_DATA;
reg                        mLCD_RS;
wire                mLCD_Done;

parameter        LCD_INTIAL        =        0;
parameter        LCD_LINE1        =        5;
parameter        LCD_CH_LINE        =        LCD_LINE1+16;
parameter        LCD_LINE2        =        LCD_LINE1+16+1;
parameter        LUT_SIZE        =        LCD_LINE1+32+1;

always@(posedge iCLK or negedge iRST_N)
begin
        if(!iRST_N)
        begin
                LUT_INDEX        <=        0;
                mLCD_ST                <=        0;
                mDLY                <=        0;
                mLCD_Start        <=        0;
                mLCD_DATA        <=        0;
                mLCD_RS                <=        0;
        end
        else
        begin
                if(LUT_INDEX<LUT_SIZE)
                begin
                        case(mLCD_ST)
                        0:        begin
                                        mLCD_DATA        <=        LUT_DATA;
                                        mLCD_RS                <=        LUT_DATA;
                                        mLCD_Start        <=        1;
                                        mLCD_ST                <=        1;
                                end
                        1:        begin
                                        if(mLCD_Done)
                                        begin
                                                mLCD_Start        <=        0;
                                                mLCD_ST                <=        2;                                       
                                        end
                                end
                        2:        begin
                                        if(mDLY<18'h3FFFE)
                                        mDLY        <=        mDLY+1;
                                        else
                                        begin
                                                mDLY        <=        0;
                                                mLCD_ST        <=        3;
                                        end
                                end
                        3:        begin
                                        LUT_INDEX        <=        LUT_INDEX+1;
                                        mLCD_ST        <=        0;
                                end
                        endcase
                end
        end
end

always
begin
        case(LUT_INDEX)
        //        Initial
        LCD_INTIAL+0:        LUT_DATA        <=        9'h038;//
        LCD_INTIAL+1:        LUT_DATA        <=        9'h00C;
        LCD_INTIAL+2:        LUT_DATA        <=        9'h001;
        LCD_INTIAL+3:        LUT_DATA        <=        9'h006;//
        LCD_INTIAL+4:        LUT_DATA        <=        9'h080;//
        /*Line 1,下面开始的都是液晶显示部分的代码,想要更改显示的内容,只需要改动后两位即可,例如9’h120,前面的1表示写的是数据,后面的20表示的是数据内容,20表示为空格键,即为不显示内容,把它改为9’h165即可显示字符e,详细的对应可以看看Datasheet的字符表*/
        LCD_LINE1+0:        LUT_DATA        <=        9'h120;        //        Welcome to the
        LCD_LINE1+1:        LUT_DATA        <=        9'h157;
        LCD_LINE1+2:        LUT_DATA        <=        9'h165;
        LCD_LINE1+3:        LUT_DATA        <=        9'h16C;
        LCD_LINE1+4:        LUT_DATA        <=        9'h163;
        LCD_LINE1+5:        LUT_DATA        <=        9'h16F;
        LCD_LINE1+6:        LUT_DATA        <=        9'h16D;
        LCD_LINE1+7:        LUT_DATA        <=        9'h165;
        LCD_LINE1+8:        LUT_DATA        <=        9'h120;
        LCD_LINE1+9:        LUT_DATA        <=        9'h174;
        LCD_LINE1+10:        LUT_DATA        <=        9'h16F;
        LCD_LINE1+11:        LUT_DATA        <=        9'h120;
        LCD_LINE1+12:        LUT_DATA        <=        9'h174;
        LCD_LINE1+13:        LUT_DATA        <=        9'h168;
        LCD_LINE1+14:        LUT_DATA        <=        9'h165;
        LCD_LINE1+15:        LUT_DATA        <=        9'h120;
        //        Change Line
        LCD_CH_LINE:        LUT_DATA        <=        9'h0C0;
        //        Line 2
        LCD_LINE2+0:        LUT_DATA        <=        9'h141;        //        Altera DE2 Board
        LCD_LINE2+1:        LUT_DATA        <=        9'h16C;
        LCD_LINE2+2:        LUT_DATA        <=        9'h174;
        LCD_LINE2+3:        LUT_DATA        <=        9'h165;
        LCD_LINE2+4:        LUT_DATA        <=        9'h172;
        LCD_LINE2+5:        LUT_DATA        <=        9'h161;
        LCD_LINE2+6:        LUT_DATA        <=        9'h120;
        LCD_LINE2+7:        LUT_DATA        <=        9'h144;
        LCD_LINE2+8:        LUT_DATA        <=        9'h145;
        LCD_LINE2+9:        LUT_DATA        <=        9'h132;
        LCD_LINE2+10:        LUT_DATA        <=        9'h120;
        LCD_LINE2+11:        LUT_DATA        <=        9'h142;
        LCD_LINE2+12:        LUT_DATA        <=        9'h16F;
        LCD_LINE2+13:        LUT_DATA        <=        9'h161;
        LCD_LINE2+14:        LUT_DATA        <=        9'h172;
        LCD_LINE2+15:        LUT_DATA        <=        9'h164;
        default:                LUT_DATA        <=        9'hxxx;
        endcase
end

LCD_Controller                 u0        (        //        Host Side
                                                        .iDATA(mLCD_DATA),
                                                        .iRS(mLCD_RS),
                                                        .iStart(mLCD_Start),
                                                        .oDone(mLCD_Done),
                                                        .iCLK(iCLK),
                                                        .iRST_N(iRST_N),
                                                        //        LCD Interface
                                                        .LCD_DATA(LCD_DATA),
                                                        .LCD_RW(LCD_RW),
                                                        .LCD_EN(LCD_EN),
                                                        .LCD_RS(LCD_RS)        );

endmodule

bad_fpga 发表于 2009-8-6 16:50:21

呵呵,为什么要放下FPGA呢

leafing 发表于 2009-8-6 17:06:44

是呀,好东西的啊,不要放掉!

tiger1125 发表于 2009-8-6 18:51:41

【1楼】 bad_fpga
【2楼】 leafing 叶子

之所以打算放下FPGA的学习是因为感觉到自己目前的水平还只是把它当单片机来用,不能发挥FPGA的强大功能。
而且,目前我的专业基础还不够扎实,打算先学好基础再考虑是否重回这条道路

yichuanliu 发表于 2009-8-17 16:25:29

这不是DE2板子的实例嘛!呵呵 怎么还成周立功的了
页: [1]
查看完整版本: 暂时放下FPGA的学习,临别放上自己的文档,以作纪念