UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Newbie beitel
Newbie
15,025 Views
Registered: ‎10-03-2008

Spartan 3a LCD programming with verilog

I'm wondering if anyone has seen or written any verilog to write to the 16x2 LCD on the Spartan 3a development board?

 

Thanks,

 

Bill

0 Kudos
7 Replies
15,009 Views
Registered: ‎06-18-2008

Re: Spartan 3a LCD programming with verilog

You probably aren't going to find anything like that floating around on the internet.  It's a lot of work and I doubt people will be willing to give it away.  (they did the time and they'll want you to do it too).  But, if you are interested in doing it, use a "3 process" state machine as described here:

 

http://toolbox.xilinx.com/docsan/xilinx4/data/docs/xst/hdlcode15.html

 

When you are setting counters as timers for your wait states, don't do them in your state machine.  Instead, use a separate module and use control signals to indicate to the state machine that the counter has expired.  An alternative way is to use a DCM with the clock divided down to slow enough period to act as your timer signal.  

 

Depending on your board, you probably have multiple devices sharing I/O pins on your fpga (lcd signals, flash, etc...), and if so you'll have to disable those devices so you don't have any unexpected contention on the signals.  

 

Travis

0 Kudos
13,048 Views
Registered: ‎01-28-2010

Re: Spartan 3a LCD programming with verilog

I'm wondering if anyone has seen or written any VHDL to write to the 16x2 LCD on the Spartan 3a development board?

thank you ,

süleyman

Tags (1)
0 Kudos
Explorer
Explorer
13,042 Views
Registered: ‎11-26-2008

Re: Spartan 3a LCD programming with verilog

I wouldn't say that it's a lot of work writing a hardware module for a 16x2 lcd display. The HD44780 interface used by basically all lcd displays of that type (at least, I can't remember seeing any that don't use it) is fairly straight-forward. Sure, a module with support for all available functions may take some time to complete, but if you only need to display a few text strings, it can be done in a couple of hundred lines of code...
0 Kudos
Historian
Historian
13,034 Views
Registered: ‎02-25-2008

Re: Spartan 3a LCD programming with verilog


travislagrone wrote:

You probably aren't going to find anything like that floating around on the internet.  It's a lot of work and I doubt people will be willing to give it away.  (they did the time and they'll want you to do it too).  But, if you are interested in doing it, use a "3 process" state machine as described here:

 

http://toolbox.xilinx.com/docsan/xilinx4/data/docs/xst/hdlcode15.html


 

For the love of all that is holy and good, don't recommend that a newbie use a 3-process state machine. They are unmaintainable nightmares. I expect that his next question will be, "Why do the tools tell me that I am getting all of these latches?"

----------------------------Yes, I do this for a living.
0 Kudos
Newbie ranchbox
Newbie
12,995 Views
Registered: ‎02-07-2010

Re: Spartan 3a LCD programming with verilog

This is my own code for the 16x2 LCD in Spartan 3A kit.  Not well polished and not documented, but hope this will have some place for learning purposes.  I'm sure others will have better way of writing the code.

 

Enjoy.

 

Fitz

 

 

 

 

 

 `timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    21:43:40 05/12/2008
// Design Name:
// Module Name:    text_lcd
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/*********************************************************
 *
 *   This is part that will control the display
 *
 *
 *
 *********************************************************/

`include "text_chars.v"


`define CMD_STATE_INIT 6'h00
`define CMD_STATE_MVBUF 6'h02
`define CMD_STATE_01   6'h04
`define CMD_STATE_02   6'h06
`define CMD_STATE_03   6'h08
`define CMD_STATE_04   6'h0A
`define CMD_STATE_05   6'h0C
`define CMD_STATE_06   6'h0E
`define CMD_STATE_07   6'h10
`define CMD_STATE_08   6'h12
`define CMD_STATE_09   6'h14
`define CMD_STATE_0A   6'h16
`define CMD_STATE_0B   6'h18
`define CMD_STATE_0C   6'h1A
`define CMD_STATE_0D   6'h1C
`define CMD_STATE_0E   6'h1E
`define CMD_STATE_10   6'h20
`define CMD_STATE_11   6'h22
`define CMD_STATE_12   6'h24
`define CMD_STATE_14   6'h26
`define CMD_STATE_16   6'h28
`define CMD_STATE_18   6'h2A
`define CMD_STATE_1A   6'h2C
`define CMD_STATE_1B   6'h2E

`define CMD_STATE_30   6'h30
`define CMD_STATE_32   6'h32
`define CMD_STATE_DELAY 6'b?????1


module display_lcd (
    input wire rst,
    input wire clk,
    input wire [255:0] msg,

    output reg busy,
    output reg lcd_e,
    output reg lcd_rs,
    output reg lcd_rw,
    output reg [7:0] lcd_db
    );

    //parameter FUNC_SET = 1, DATA_INPUT = 2;

    //reg lcd_e;
    //reg [7:0] lcd_db;
    //reg lcd_rs = 0;
    //reg lcd_rw = 0;

    //reg busy = 0;

    reg [255:0] in_msg = 0;

    reg [255:0] in_msg_stack = 0;


    reg [19:0] counter = 0;

    reg cnt_rst = 0;
    reg [5:0] lcd_state = 0;
    //reg [5:0] nxt_state = 0;
    reg [7:0] col = 0;
    reg [7:0] row = 0;
    reg [7:0] str;
    //wire [7:0] wstr;

    wire count_flag;
    //wire status_w;
    //wire rst_w;

    //fx_delay #(.WIDTH(20))delay0 (
    //    .clk_w_i(CLOCK),
    //    .rst_w_i(rst_w),
    //    .count_w_i(counter),
    //    .status_w_o(status_w)
    //);
    //
    //assign zz = in_msg_stack[251:248];
    //
    //

   //assign count_flag = ~&counter;
    always @(posedge clk)
    begin
       if(rst == 1)
            lcd_state <= `CMD_STATE_INIT;
       else if (~&counter == 0)

            //casez ({lcd_state[5:1],~&counter})
            case (lcd_state)

            `CMD_STATE_INIT:
                begin

                    if(in_msg_stack != msg)
                    begin
                        in_msg <= msg;
                        in_msg_stack <= msg;
                        busy <= 1;
                        lcd_state <= `CMD_STATE_MVBUF;

                        counter <= 0;
                        str <= 0;
                    end
                end

            `CMD_STATE_MVBUF:
                begin
                    if(in_msg[255:248] == 8'b00000000)
                    begin
                        in_msg <= in_msg << 8;
                        in_msg[7:0] <= 8'b00100000;
                    end
                    else
                    begin
                        lcd_state <= `CMD_STATE_01;
                        counter <= 0;
                    end
                end
            `CMD_STATE_01:
                begin

                    lcd_db <= 8'h3F;
                    lcd_rs <= 0;

                    counter <= 2;
                    lcd_state <= `CMD_STATE_02;

                end

            `CMD_STATE_02:
                begin
                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_03;

                end

            `CMD_STATE_03:
                begin
                    lcd_e <= 0;
                    counter <= 2000;
                    lcd_state <= `CMD_STATE_04;

                end


            `CMD_STATE_04:
                begin
                    lcd_db <= 8'h3B;
                    counter <= 2;
                    lcd_state <= `CMD_STATE_05;

                end


            `CMD_STATE_05:
                begin
                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_06;

                end
            `CMD_STATE_06:
                begin
                    lcd_e <= 0;
                    counter <= 2000;
                    lcd_state <= `CMD_STATE_07;

                end

            `CMD_STATE_07:
                begin
                    lcd_db <= 8'hC;
                    counter <= 2;
                    lcd_state <= `CMD_STATE_08;

                end

            `CMD_STATE_08:
                begin
                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_09;

                end
            `CMD_STATE_09:
                begin
                    lcd_e <= 0;
                    counter <= 2000;
                    lcd_state <= `CMD_STATE_0A;


                end

            `CMD_STATE_0A:
                begin
                    lcd_db <= 8'h1;
                    counter <= 2;
                    lcd_state <= `CMD_STATE_0B;

                end

            `CMD_STATE_0B:
                begin
                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_0C;

                end
            `CMD_STATE_0C:
                begin
                    lcd_e <= 0;
                    counter <= 100000;
                    lcd_state <= `CMD_STATE_0D;


                end


            `CMD_STATE_0D:
                begin
                    lcd_db <= 8'b0000110;

                    counter <= 2;
                    lcd_state <= `CMD_STATE_0E;


                end

            `CMD_STATE_0E:
                begin
                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_10;

                end
            `CMD_STATE_10:
                begin
                    lcd_e <= 0;
                    counter <= 2000;
                    lcd_state <= `CMD_STATE_11;
                end

            `CMD_STATE_11:
                begin
                    lcd_db <= `LCD_ADDR_00 |  col | row ;   // address
                    lcd_rs <= 0;

                    counter <= 2;
                    lcd_state <= `CMD_STATE_12;

                end

            `CMD_STATE_12:
                begin

                    lcd_e <= 1;
                    counter <= 12;
                    lcd_state <= `CMD_STATE_14;

                end

            `CMD_STATE_14:
                begin
                    lcd_e <= 0;

                    counter <= 2000;
                    lcd_state <= `CMD_STATE_16;
                end
            // After 40 microsecond
            `CMD_STATE_16:

                begin
                    //lcd_db = `LCD_TEXT_s;   // data
                    lcd_db <= in_msg[255:248];


                    lcd_rs <= 1;

                    counter <= 12;
                    lcd_state <= `CMD_STATE_18;

                end

            `CMD_STATE_18:
                begin
                    lcd_e <= 1;

                    counter <= 12;
                    lcd_state <= `CMD_STATE_1A;

                end



            `CMD_STATE_1A:
                begin
                    lcd_e <= 0;
                    counter <= 0;

                    //counter <= 2000;
                    // go to next col, else go to next state

                    if (col == 8'h0F)
                        lcd_state <= `CMD_STATE_30;
                    else
                        lcd_state <= `CMD_STATE_32;
                 end

            `CMD_STATE_30:

                begin
                    counter <= 2000;
                    if (row == 8'b01000000) begin

                        lcd_state <= `CMD_STATE_1B;

                    end
                    else
                    begin
                        lcd_state <= `CMD_STATE_11;
                        col <= 0;
                        row <= 8'b01000000;
                        in_msg <= in_msg << 8;

                    end

                end
                    //else
            `CMD_STATE_32:

                begin
                    counter <= 2000;
                    lcd_state <= `CMD_STATE_11;
                    col <= col + 1;
                    in_msg <= in_msg << 8;

                end



            `CMD_STATE_1B:

                begin
                    busy <= 0;

                    lcd_state <= `CMD_STATE_INIT;
                    row <= 0;
                    col <= 0;
                    counter <= 0;
                end
            //`CMD_STATE_DELAY:
            //    begin
            //        counter <= counter - 1;
            //
            //    end
            default:
                begin
                    busy <= 0;

                    lcd_state <= `CMD_STATE_INIT;
                    row <= 0;
                    col <= 0;
                    counter <= 0;
                end

            endcase
         else
            counter <= counter - 1;






    end



endmodule

 

 

 

 

0 Kudos
Highlighted
Newbie vijayseshu
Newbie
9,830 Views
Registered: ‎11-29-2012

Re: Spartan 3a LCD programming with verilog

hello,

 

but why the code is that much lengthy..?

if we write the code for lcd in keil(for 8051) it will be very short, right?

then, why this much long for fpga to code the same lcd??

im a beguinner in vlsi and just finished the concepts of verilog..

help me accessing the lcd on my own..

 

regards,

vijay

Tags (1)
0 Kudos
Historian
Historian
9,819 Views
Registered: ‎02-25-2008

Re: Spartan 3a LCD programming with verilog


@vijayseshu wrote:

hello,

 

but why the code is that much lengthy..?

if we write the code for lcd in keil(for 8051) it will be very short, right?

then, why this much long for fpga to code the same lcd??

im a beguinner in vlsi and just finished the concepts of verilog..

help me accessing the lcd on my own..

 

regards,

vijay


Microcontroller programming and digital hardware design are two different disciplines. While the end results might be the same, they are very different.

You must understand that.

----------------------------Yes, I do this for a living.
0 Kudos