让两条线在DE2-115液晶屏上工作

问题描述 投票:0回答:1

DE2-115 LCD 上的两条线都无法正常工作。我知道我需要更改 DDRAM 地址以获得开始打印消息的起始位置,但是我不确定如何使两条线都工作。这是我当前得到的液晶驱动器,我的顶层是之后的。

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

目前我只收到一条消息,即说明,但我想稍后再写一行。我相信第 2 行的 DDRAM 地址是 h'040。有人可以帮我吗?

我尝试实例化另一个 lcd_driver 但无法使其工作。另一种方法是获得一个大数组,但间距使其变得太复杂并且从未得到正确的结果。

verilog intel-fpga
1个回答
0
投票

尝试以下更改:

module lcd_driver (
    input clk,
    dstream.in in_data,
    output logic [7:0] LCD_DATA,
    output logic LCD_RW, LCD_EN, LCD_RS, LCD_ON, LCD_BLON
);

    // ... (existing code)

    // Additional state variables for second line printing
    enum logic [2:0] {INIT, START, ENABLE, WAIT, NEXT, LINE2_INIT, LINE2_START} 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;

    // ... (existing code)

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

    // Add logic for printing the second line
    always_ff @(posedge clk) begin : second_line_logic
        if (state == LINE2_INIT) begin
            // Initialize for printing the second line
            initialise_index <= 0;
            init_data <= 10'h0C0; // Set DDRAM address to 0x40 (second line)
        end
        else if (state == LINE2_START) begin
            // Print the second line
            LCD_DATA <= in_data.data[7:0];
            LCD_RW <= in_data.data[8];
            LCD_RS <= in_data.data[9];
        end
    end

    // Modify the existing FSM logic to transition to the second line printing
    always_ff @(posedge clk) begin : fsm_ff
        if (state == NEXT && initialise_index == 3) begin
            next_state <= LINE2_INIT; // Transition to initialize second line printing
        end
        else begin
            next_state <= state;
        end
    end

    // ... (existing code)

endmodule
© www.soinside.com 2019 - 2024. All rights reserved.