Getting both lines to work on DE2-115 LCD screen

108 Views Asked by At

having trouble to get both lines on the DE2-115's LCD to work. I understand that I need to change the DDRAM address to have a starting location of where to start printing your message however I'm not sure on how to get both lines working. This is the current lcd driver I got and my toplevel is after.

module lcd_driver ( //  Host Side
    input clk,
    dstream.in in_data,  // data from controller
    //  LCD Side
    output logic [7:0] LCD_DATA,
    output logic LCD_RW,LCD_EN,LCD_RS,LCD_ON,LCD_BLON
);

    assign LCD_ON   = 1'b1;        // Turn LCD on
    assign LCD_BLON = 1'b0;        // Display backlight (Not supported on DE2-115).

    enum logic [2:0] {INIT, START, ENABLE, WAIT, NEXT} state, next_state;
    
    logic   [5:0]   initialise_index = 0;
    logic   [9:0]   init_data;

    integer start_count = 0;
    integer delay_count = 0;
    integer enable_count = 0;

    always_comb begin : next_state_logic
        next_state = state;
        case (state)
            INIT:   next_state = start_count > 3   ? ENABLE : INIT;   // start_count: wait for 80ns
            START:  next_state = start_count > 3   ? ENABLE : START;
            ENABLE: next_state = enable_count < 16 ? ENABLE : WAIT;   // Wait 320ns
            WAIT:   next_state = delay_count < 262142 ? WAIT : NEXT;  // Wait for 262142 cycles -> 5.24284 ms
            NEXT:   next_state = initialise_index < 4 ? INIT : START; // Stay in initialisation sequence
        endcase
    end

    always_ff @(posedge clk) begin : fsm_ff
        state <= next_state;
    end

    assign LCD_EN = state == ENABLE;
    assign in_data.ready = state == START; // Only ready for new data in the start state

    logic in_data_handshake; // Store if the handshake has taken place

    always_ff @(posedge clk) begin : output_ff
            case(state)
                INIT: begin
                    LCD_DATA    <=  init_data[7:0];  // First 8 bits = DB* data bits
                    LCD_RW      <=  init_data[8];    // RS bit
                    LCD_RS      <=  init_data[9];    // RS bit
                    start_count <= start_count + 1;
                end  
                START: begin
                    LCD_DATA    <=  in_data.data[7:0];
                    LCD_RW      <=  in_data.data[8];
                    LCD_RS      <=  in_data.data[9];
                    if (in_data_handshake) start_count <= start_count + 1; // If handshake already occured, start counting. Start_count: wait for 80ns
                    else in_data_handshake <= in_data.valid; // Handshake occured
                end  
                ENABLE: begin
                    enable_count <= enable_count+1; // Wait 320ns
                    start_count <= 0;
                    in_data_handshake <= 0; // Reset handshake for next packet.
                end
                WAIT: begin
                    delay_count <=  delay_count+1; // Wait for 262142 cycles -> 5.24284 ms
                    enable_count <= 0;
                end
                NEXT: begin
                    delay_count <=  0;
                    initialise_index    <=  initialise_index+1; // Move to next initialisation instruction.
                end
            endcase
    end


    /* Initialise Lookup Table : */
    always_comb begin : init_lut
        case(initialise_index)
        //  Initial
        0:  init_data   =   10'h038;     // Function set
        1:  init_data   =   10'h00C;     // Display on
        2:  init_data   =   10'h001;     // Clear Display
        3:  init_data   =   10'h006;     // Entry mode
        4:  init_data   =   10'h080;     // DDRAM Addr set to 0 10'b0010000000 //for lower screen 10'b0011000000 
        default: init_data  =   10'h010; // Return Home
        endcase
    end
endmodule

module top_level (
    input CLOCK_50,  // 50 MHz
    output LCD_BLON,
    inout   [7:0] LCD_DATA,
    output LCD_EN,
    output LCD_ON,
    output LCD_RS,
    output LCD_RW
);

    dstream #(.N(10)) in_data (CLOCK_50);
    lcd_driver u5   (.clk(CLOCK_50), .*);
    
    logic [9:0] instructions [0:15] ='{10'h220, 10'h220, 10'h248, 10'h265, 10'h26C, 
    10'h26C, 10'h26F, 10'h220, 10'h220, 10'h257, 10'h26F, 10'h272, 10'h26C, 10'h264, 10'h220, 10'h220};
    integer count=0;

    always_ff @(posedge CLOCK_50) begin // Read instructions and pass them to the LCD driver module.
        count <= count + 1;
        in_data.valid <= 0;
        if(count[23:0] == 24'hFFFFFF) begin // Write to the display every ~0.34 seconds (2^24 counts)
            // Implementation note: we should really check for a handshake before moving to the next instruction!
            in_data.out.data    <=  instructions[count[27:24]]; // Clever trick to count every ~0.67 seconds.
            in_data.valid <= 1; // pulse valid.
        end
        if(count[28] == 1'b1) count <= count; // Pause count once it gets to 2^28.
    end

endmodule

Currently I've only got one message which is instructions but I want to write another line afterwards. I believe the DDRAM address for line 2 is h'040. Can someone please help me out?

I tried to just instantiate another lcd_driver but could not get that to work. Other method was to get a big array but spacing made it too complicated and never got the right results.

0

There are 0 best solutions below